lib/hanami/web/rack_logger.rb in hanami-2.0.0.rc1 vs lib/hanami/web/rack_logger.rb in hanami-2.0.0

- old
+ new

@@ -6,10 +6,13 @@ # Rack logger for Hanami apps # # @api private # @since 2.0.0 class RackLogger + EMPTY_PARAMS = {}.freeze + private_constant :EMPTY_PARAMS + REQUEST_METHOD = "REQUEST_METHOD" private_constant :REQUEST_METHOD HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR" private_constant :HTTP_X_FORWARDED_FOR @@ -27,53 +30,99 @@ private_constant :ROUTER_PARAMS CONTENT_LENGTH = "Content-Length" private_constant :CONTENT_LENGTH + MILISECOND = "ms" + private_constant :MILISECOND + + MICROSECOND = "µs" + private_constant :MICROSECOND + + # Dynamic extension used in production environments # @api private + module Production + private + + # @since 1.0.0 + # @api private + def data(env, status:, elapsed:) + payload = super + payload[:elapsed] = elapsed + payload[:elapsed_unit] = MICROSECOND + payload + end + end + + # Dynamic extension used in non-production environments + # @api private + module Development + private + + # @since 1.0.0 + # @api private + def data(env, status:, elapsed:) + payload = super + payload[:elapsed] = elapsed > 1000 ? "#{elapsed / 1000}ms" : "#{elapsed}#{MICROSECOND}" + payload + end + end + + # @api private # @since 2.0.0 - def initialize(logger) + def initialize(logger, env: :development) @logger = logger + extend(env == :production ? Production : Development) end # @api private # @since 2.0.0 def attach(rack_monitor) rack_monitor.on :stop do |event| log_request event[:env], event[:status], event[:time] end rack_monitor.on :error do |event| - log_exception event[:exception] + # TODO: why we don't provide time on error? + log_exception event[:env], event[:exception], 500, 0 end end # @api private # @since 2.0.0 def log_request(env, status, elapsed) - data = { - verb: env[REQUEST_METHOD], - status: status, - elapsed: "#{elapsed}ms", - ip: env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR], - path: env[SCRIPT_NAME] + env[PATH_INFO].to_s, - length: extract_content_length(env), - params: env[ROUTER_PARAMS] - } - - logger.info(data) + logger.tagged(:rack) do + logger.info(data(env, status: status, elapsed: elapsed)) + end end # @api private # @since 2.0.0 - def log_exception(exception) - logger.error(exception) + def log_exception(env, exception, status, elapsed) + logger.tagged(:rack) do + logger.error(exception, **data(env, status: status, elapsed: elapsed)) + end end private attr_reader :logger + # @api private + # @since 2.0.0 + def data(env, status:, elapsed:) + { + verb: env[REQUEST_METHOD], + status: status, + ip: env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR], + path: "#{env[SCRIPT_NAME]}#{env[PATH_INFO]}", + length: extract_content_length(env), + params: env.fetch(ROUTER_PARAMS, EMPTY_PARAMS) + } + end + + # @api private + # @since 2.0.0 def extract_content_length(env) value = env[CONTENT_LENGTH] !value || value.to_s == "0" ? "-" : value end end