Class: RackMiddlewareMetrics::Reporter

Inherits:
Object
  • Object
show all
Defined in:
lib/rack_middleware_metrics/reporter.rb

Overview

The metrics reporter middleware.

Instance Method Summary collapse

Constructor Details

#initialize(app, *args) ⇒ Reporter

Initialize the reporter middleware.

Parameters:

  • app (rack::RackApp)

    the app to add metrics reporting to.

  • *args (Array<any>, nil)

    arguments to pass through to the app. A hash passed as the final argument will be used as config options–of which :logpath can be used to specify the metrics reporter logpath.



22
23
24
25
26
27
28
# File 'lib/rack_middleware_metrics/reporter.rb', line 22

def initialize app, *args
  @app = app

  # Rack `use` only allows *args. Use either logpath passed via hash or default path.
  options = args.last.is_a?(Hash) ? args.last : {}
  @logpath = Pathname.new(options.fetch(:logpath, 'rack_metrics.csv'))
end

Instance Method Details

#append_data(data) ⇒ void

This method returns an undefined value.

Run the request–call next step in middleware/server chain with added timing.

Parameters:

  • data (Array<objects>)

    metrics data to append to logfile.



69
70
71
72
73
# File 'lib/rack_middleware_metrics/reporter.rb', line 69

def append_data data
  CSV.open(@logpath, 'a') do |csv|
    csv << data
  end
end

#call(env) ⇒ Array<objects>

Main middleware entry and exit point. Logs metrics as specified.

Parameters:

  • env (rack::ENV)

    the request env.

Returns:

  • (Array<objects>)

    of the form: [status, headers, body]



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/rack_middleware_metrics/reporter.rb', line 79

def call env
  status, headers, body, timing = timed_call(env)

  query_params = params_from(env)
  uri = uri_from(env)
  thread_id =  Thread.current.object_id
  process_id = Process.pid
  md5 = MD5Gen.compute(body.to_s)

  append_data([*timing, uri, query_params, thread_id, process_id, md5])

  [status, headers, body]
end

#params_from(env) ⇒ String

Converts data from rack env object to semicolon delimited parameters. Original semicolons escaped with %3B the ASCII equivalent. See www.december.com/html/spec/esccodes.html for more details.

Parameters:

  • env (rack::ENV)

    the request env.

Returns:

  • (String)

    semicolon delimited parameters..



45
46
47
48
49
# File 'lib/rack_middleware_metrics/reporter.rb', line 45

def params_from env
  params = Hash[URI.decode_www_form(env['QUERY_STRING'])]
  params = params.map { |key, val| "#{ key }=#{ val }" }
  params.map { |param| param.gsub(';', '%3B') }.join(';')
end

#timed_call(env) ⇒ Array<Array<Objects>>

Run the request–call next step in middleware/server chain with added timing.

Parameters:

  • env (rack::ENV)

    the request env.

Returns:

  • (Array<Array<Objects>>)

    the response objects: [status, headers, body] plus added timing such that the final form is:

    [status, headers, body], [start_time, end_time, duration]


57
58
59
60
61
62
63
# File 'lib/rack_middleware_metrics/reporter.rb', line 57

def timed_call env
  start_time = Time.now
  response = @app.call(env)
  end_time = Time.now
  duration = end_time - start_time
  [*response, [start_time, end_time, duration]]
end

#uri_from(env) ⇒ String

Converts data from rack env object to uri.

Parameters:

  • env (rack::ENV)

    the request env.

Returns:

  • (String)

    the uri.



34
35
36
37
# File 'lib/rack_middleware_metrics/reporter.rb', line 34

def uri_from env
  "#{ env['rack.url_scheme'] }://#{ env['SERVER_NAME'] }"\
        ":#{ env['SERVER_PORT'] }#{ env['PATH_INFO'] }"
end