Class: ApiHammer::Faraday::RequestLogger

Inherits:
Faraday::Middleware
  • Object
show all
Includes:
RequestLoggerHelper, Term::ANSIColor
Defined in:
lib/api_hammer/faraday/request_logger.rb

Overview

Faraday middleware for logging.

logs two lines:

  • an info line, colored prettily to show a brief summary of the request and response
  • a debug line of json to record all relevant info. this is a lot of stuff jammed into one line, not pretty, but informative.

options:

  • :filter_keys defines keys whose values will be filtered out of the logging
  • :log_bodies - true, false, :on_error

Instance Method Summary collapse

Methods included from RequestLoggerHelper

#log_bodies, #status_s

Constructor Details

#initialize(app, logger, options = {}) ⇒ RequestLogger

Returns a new instance of RequestLogger.



24
25
26
27
28
# File 'lib/api_hammer/faraday/request_logger.rb', line 24

def initialize(app, logger, options={})
  @app = app
  @logger = logger
  @options = options
end

Instance Method Details

#call(request_env) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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
# File 'lib/api_hammer/faraday/request_logger.rb', line 30

def call(request_env)
  began_at = Time.now

  log_tags = Thread.current[:activesupport_tagged_logging_tags]
  saved_log_tags = log_tags.dup if log_tags && log_tags.any?

  request_body = request_env[:body].dup if request_env[:body]

  @app.call(request_env).on_complete do |response_env|
    now = Time.now
    status = response_env[:status]

    if log_bodies(status)
      bodies = [
        ['request', request_body, request_env[:request_headers]],
        ['response', response_env[:body], response_env[:response_headers]]
      ].map do |(role, body_s, headers)|
        body = Body.new(body_s, headers['Content-Type'])
        if body.content_type_attrs.text?
          if @options[:filter_keys]
            body = body.filtered(:filter_keys => @options[:filter_keys])
          end
          log_body = body.jsonifiable.body
        end
        {role => log_body}
      end.inject({}, &:update)
    else
      bodies = {}
    end

    data = {
      'request_role' => 'client',
      'request' => {
        'method' => request_env[:method],
        'uri' => request_env[:url].normalize.to_s,
        'headers' => request_env[:request_headers],
        'body' => bodies['request'],
      }.reject{|k,v| v.nil? },
      'response' => {
        'status' => status.to_s,
        'headers' => response_env[:response_headers],
        'body' => bodies['response'],
      }.reject{|k,v| v.nil? },
      'processing' => {
        'began_at' => began_at.utc.to_f,
        'duration' => now - began_at,
        'activesupport_tagged_logging_tags' => log_tags,
      }.reject{|k,v| v.nil? },
    }

    json_data = JSON.generate(data)
    dolog = proc do
      now_s = now.strftime('%Y-%m-%d %H:%M:%S %Z')
      @logger.info "#{bold(intense_magenta('>'))} #{status_s(status)} : #{bold(intense_magenta(request_env[:method].to_s.upcase))} #{intense_magenta(request_env[:url].normalize.to_s)} @ #{intense_magenta(now_s)}"
      @logger.info json_data
    end

    # reapply log tags from the request if they are not applied 
    if @logger.respond_to?(:tagged) && saved_log_tags && Thread.current[:activesupport_tagged_logging_tags] != saved_log_tags
      @logger.tagged(saved_log_tags, &dolog)
    else
      dolog.call
    end
  end
end