Class: Rack::KeyValueLogger

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/key_value_logger.rb,
lib/key_value_logger/version.rb

Constant Summary collapse

SEPARATOR =
"|"
VERSION =
'0.4.0'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, opts = {}) ⇒ KeyValueLogger

Returns a new instance of KeyValueLogger.

Examples:

Preventing rails assets from being logged

use Rack::KeyValueLogger, :ignore_paths => /\/assets/

Logging non-success response bodies

use Rack::KeyValueLogger, :log_failure_response_bodies => true
# NOTE: Most fields below have been omitted for brevity and replaced with "..."
# => [1351712789 2012-10-31 19:46:29 UTC] method=GET|url=/422|params=|...|response_body=["{\"errors\"=>{\"key\"=>\"val\"}}"]|runtime=0.07

Parameters:

  • opts (defaults to: {})

Options Hash (opts):

  • :logger (Object)

    A logger instance. Defaults to logging to $stdout.

  • :log_failure_response_bodies (Object)

    Set to ‘true` to log response bodies for non-success codes. Defaults to false.

  • :user_id (Object)

    a string key representing the user id key. Defaults to ‘user_id’

  • :ignore_paths (Object)

    a regular expression indicating url paths we don’t want to in the session hash.



27
28
29
30
31
32
33
# File 'lib/rack/key_value_logger.rb', line 27

def initialize(app, opts = {})
  @app, @opts = app, opts
  @logger = @opts[:logger] || ::Logger.new($stdout)
  @opts[:log_failure_response_bodies] ||= false
  @opts[:user_id] ||= 'user_id'
  @ignore_paths = @opts[:ignore_paths]
end

Instance Attribute Details

#ignore_pathsObject (readonly)

Returns the value of attribute ignore_paths.



9
10
11
# File 'lib/rack/key_value_logger.rb', line 9

def ignore_paths
  @ignore_paths
end

#loggerObject (readonly)

Returns the value of attribute logger.



9
10
11
# File 'lib/rack/key_value_logger.rb', line 9

def logger
  @logger
end

#msgObject (readonly)

Returns the value of attribute msg.



9
10
11
# File 'lib/rack/key_value_logger.rb', line 9

def msg
  @msg
end

#optsObject (readonly)

Returns the value of attribute opts.



9
10
11
# File 'lib/rack/key_value_logger.rb', line 9

def opts
  @opts
end

Instance Method Details

#call(env) ⇒ Object

Logs key=value pairs of useful information about the request and response to the a log. We either piggy-back off the env or we log to $stdout.

Components

* session - session hash, json-encoded
* accept - Accept-Encoding request header
* user-agent - User agent string
* request-time - in seconds since epoch
* method - request method
* status - response status code
* url - the url, without query string
* query-string - query string params
* user-id - user's id
* scheme - http or https
* content-length - length in bytes of the response body
* requested-content-type
* content-type - Content-Type response header
* remote-ip - User's ip address
* runtime - Duration of request in milliseconds
* http-version - http version of the client
* mobile-device - the mobile device return by rack-mobile-detect


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rack/key_value_logger.rb', line 57

def call(env)
  @msg           = []
  start          = Time.now
  request        = Rack::Request.new(env)
  user_id        = env['rack.session'] && env['rack.session'][opts[:user_id]]
  mobile_device  = env['X_MOBILE_DEVICE']
  url            = request.path
  query_string   = env['QUERY_STRING']

  if ignored_path?(url)
    return @app.call(env)
  end

  # record request attributes
  msg << "ts=#{Time.now.utc.iso8601}"
  msg << "method=#{request.request_method}"
  msg << "url=#{url}"
  msg << "params=#{query_string}"
  msg << "user_id=#{user_id}"
  msg << "scheme=#{request.scheme}"
  msg << "user_agent=#{request.user_agent}"
  msg << "remote_ip=#{request.ip}"
  msg << "http_version=#{env['HTTP_VERSION']}"
  msg << "mobile_device=#{mobile_device}" if mobile_device
  msg << "requested_content_type=#{request.content_type}"
  msg << "log_source=key_value_logger"

  begin
    status, headers, body = @app.call(env)

    record_response_attributes(status, headers, body)
  rescue => e
    msg << 'status=500'
    raise e
  ensure
    record_runtime(start)

    # Don't log Rack::Cascade fake 404's
    flush_log unless rack_cascade_404?(headers)
  end

  [status, headers, body]
end