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.



87
88
89
90
91
# File 'lib/api_hammer/faraday/request_logger.rb', line 87

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

Instance Method Details

#call(request_env) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/api_hammer/faraday/request_logger.rb', line 93

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

    request = ApiHammer::Faraday::Request.new(request_env, response_env)

    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))

    filtered_request_body = request_body.dup if request_body
    filtered_response_body = request.response_body.dup if request.response_body

    if @options[:filter_keys]
      body_info = [['request', filtered_request_body, request_env.request_headers], ['response', filtered_response_body, response_env.response_headers]]
      body_info.map do |(role, body, headers)|
        if body
          parsed_body = ApiHammer::ParsedBody.new(body, headers['Content-Type'])
          body.replace(parsed_body.filtered_body(@options.slice(:filter_keys)))
        end
      end
    end

    data = {
      'request_role' => 'client',
      'request' => {
        'method' => request_env[:method],
        'uri' => request_env[:url].normalize.to_s,
        'headers' => request_env.request_headers,
        'body' => (filtered_request_body if ContentTypeAttrs.new(request_env.request_headers['Content-Type']).text?),
      }.reject{|k,v| v.nil? },
      'response' => {
        'status' => response_env.status.to_s,
        'headers' => response_env.response_headers,
        'body' => (filtered_response_body if ContentTypeAttrs.new(response_env.response_headers['Content-Type']).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