Class: ApiHammer::Faraday::RequestLogger

Inherits:
Faraday::Middleware
  • Object
show all
Includes:
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

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of RequestLogger.



21
22
23
24
25
# File 'lib/api_hammer/faraday/request_logger.rb', line 21

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

Instance Method Details

#call(request_env) ⇒ Object



27
28
29
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
95
96
97
# File 'lib/api_hammer/faraday/request_logger.rb', line 27

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_color = case response_env.status.to_i
    when 200..299
      :intense_green
    when 400..499
      :intense_yellow
    when 500..599
      :intense_red
    else
      :white
    end
    status_s = bold(send(status_color, response_env.status.to_s))

    bodies = [
      ['request', request_body, request_env.request_headers],
      ['response', response_env.body, response_env.response_headers]
    ].map do |(role, body, headers)|
      {role => Body.new(body, headers['Content-Type']).jsonifiable}
    end.inject({}, &:update)

    if @options[:filter_keys]
      bodies = bodies.map do |(role, body)|
        {role => body.filtered(@options.slice(:filter_keys))}
      end.inject({}, &:update)
    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'].body if bodies['request'].content_type_attrs.text?),
      }.reject{|k,v| v.nil? },
      'response' => {
        'status' => response_env.status.to_s,
        'headers' => response_env.response_headers,
        'body' => (bodies['response'].body if bodies['response'].content_type_attrs.text?),
      }.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} : #{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