module Semantic class LogSubscriber < ActiveSupport::LogSubscriber include SemanticLogger::Loggable # def logger = SemanticLogger['Rails'] EMPTY = 'none'.freeze def initialize(session_key) @session_key = session_key @transactions = {} super() end def start_processing(event) session_value = session_value(event) @transactions[event.transaction_id] = session_value # preserve session_value to help finish_processing SemanticLogger.tagged(session_value) do request = event.payload[:request] logger.info("Started #{request.raw_request_method} #{request.filtered_path}") format = event.payload[:format] format = format.to_s.upcase if format.is_a?(Symbol) format = '*/*' if format.nil? logger.debug("Processing by #{event.payload[:controller]}##{event.payload[:action]} as #{format}") end end def finish_processing(event) session_value = @transactions.delete(event.transaction_id) # get previous session_value from start_processing SemanticLogger.tagged(session_value) do payload = event.payload additions = ActionController::Base.log_process_action(payload) status = payload[:status] if status.nil? && (exception_class_name = payload[:exception]&.first) status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name) end additions << "GC: #{event.gc_time.round(1)}ms" logger.debug("Processed in #{event.duration.round}ms (#{additions.join(' | ')})") logger.info("Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}") end end private def session_value(event) = event.payload[:headers]['rack.session'].fetch(@session_key, EMPTY) end end