class Sawmill::StatsMiddleware

A Rack middleware that writes a stats log. Insert this in your Rack stack to generate a stats log.

Public Class Methods

new(app_, logger_=nil, level_=nil, opts_={}) click to toggle source

Create a middleware object for Rack.

If you do not provide a logger object, one will be generated for you that simply logs to STDOUT.

Recognized options include:

:level

The level to log at. Default is :ANY.

:stats_data_key

The name of a rack environment key where the stats data should be stored. If not specified, defaults to “sawmill.stats_data”.

:request_id_key

The name of a rack environment key where the request ID can be obtained. If not specified, defaults to “sawmill.request_id”.

:start_time_stat

If present, stores the starting timestamp for the request in the given stat key. If absent, does not store this information.

:end_time_stat

If present, stores the ending timestamp for the request in the given stat key. If absent, does not store this information.

:elapsed_time_stat

If present, stores the elapsed time for the request in the given stat key. If absent, does not store this information.

:request_id_stat

If present, stores the request ID for the request in the given stat key. If absent, does not store this information.

:pre_logger

A proc that is called at the start of the request, and passed the logger and the rack environment. Optional. If a proc is provided and returns false, then stats logging is canceled for this request. Furthermore, any post_logger will not be called.

:post_logger

A proc that is called at the end of the request, and passed the logger and the rack environment. Optional. If a proc is provided and returns false, then stats logging is canceled for this request.

# File lib/sawmill/stats_middleware.rb, line 85
def initialize(app_, logger_=nil, level_=nil, opts_={})
  @app = app_
  @logger = logger_ || Logger.new(:progname => 'stats', :processor => Formatter.new(::STDOUT))
  @level = level_ || :ANY
  @stats_data_key = opts_[:stats_data_key] || 'sawmill.stats_data'
  @request_id_key = opts_[:request_id_key] || 'sawmill.request_id'
  @start_time_stat = opts_[:start_time_stat]
  @end_time_stat = opts_[:end_time_stat]
  @elapsed_time_stat = opts_[:elapsed_time_stat]
  @request_id_stat = opts_[:request_id_stat]
  @pre_logger = opts_[:pre_logger]
  @post_logger = opts_[:post_logger]
end

Public Instance Methods

call(env_) click to toggle source
# File lib/sawmill/stats_middleware.rb, line 100
def call(env_)
  env_[@stats_data_key] = stats_data_ = {}
  start_time_ = ::Time.now.utc
  if @start_time_stat
    stats_data_[@start_time_stat.to_s] = start_time_.strftime('%Y-%m-%dT%H:%M:%S.') + ('%06d' % start_time_.usec) + 'Z'
  end
  enable_log_ = true
  if @pre_logger
    enable_log_ &&= @pre_logger.call(stats_data_, env_)
  end
  begin
    return @app.call(env_)
  ensure
    if enable_log_
      if @request_id_stat
        stats_data_[@request_id_stat.to_s] = env_[@request_id_key]
      end
      if @post_logger
        enable_log_ &&= @post_logger.call(stats_data_, env_)
      end
      if enable_log_
        end_time_ = ::Time.now.utc
        if @end_time_stat
          stats_data_[@end_time_stat.to_s] = end_time_.strftime('%Y-%m-%dT%H:%M:%S.') + ('%06d' % end_time_.usec) + 'Z'
        end
        if @elapsed_time_stat
          stats_data_[@elapsed_time_stat.to_s] = end_time_ - start_time_
        end
        @logger.add(@level, ::JSON.dump(stats_data_))
      end
    end
  end
end