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