Module: HttpLog

Defined in:
lib/influxdb/rails/httplog/http_log.rb,
lib/influxdb/rails/httplog/helpers/al_helper.rb,
lib/influxdb/rails/httplog/http_configuration.rb

Defined Under Namespace

Classes: AlHelper, BodyParsingError, HttpConfiguration

Constant Summary collapse

LOG_PREFIX =
'[httplog] '.freeze
PARAM_MASK =
'[FILTERED]'

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.http_configuration=(value) ⇒ Object (writeonly)

Sets the attribute http_configuration

Parameters:

  • value

    the value to set the attribute http_configuration to.



16
17
18
# File 'lib/influxdb/rails/httplog/http_log.rb', line 16

def http_configuration=(value)
  @http_configuration = value
end

Class Method Details

.call(options = {}) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/influxdb/rails/httplog/http_log.rb', line 31

def call(options = {})
  if config.json_log
    log_json(options)
  elsif config.compact_log
    log_compact(options[:method], options[:url], options[:response_code], options[:benchmark])
  else
    HttpLog.log_request(options[:method], options[:url] )
    HttpLog.log_headers(options[:request_headers])
    HttpLog.log_data(options[:request_body])
    HttpLog.log_status(options[:response_code])
    HttpLog.log_benchmark(options[:benchmark])
    HttpLog.log_headers(options[:response_headers])
    HttpLog.log_body(options[:response_body], options[:encoding], options[:content_type])
  end
end

.colorize(msg) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/influxdb/rails/httplog/http_log.rb', line 238

def colorize(msg)
  return msg unless config.color
  if config.color.is_a?(Hash)
    msg = Rainbow(msg).color(config.color[:color]) if config.color[:color]
    msg = Rainbow(msg).bg(config.color[:background]) if config.color[:background]
  else
    msg = Rainbow(msg).color(config.color)
  end
  msg
rescue StandardError
  warn "HTTPLOG CONFIGURATION ERROR: #{config.color} is not a valid color"
  msg
end

.configurationObject Also known as: config



18
19
20
# File 'lib/influxdb/rails/httplog/http_log.rb', line 18

def configuration
  @http_configuration ||= HttpConfiguration.new
end

.configure {|configuration| ... } ⇒ Object

Yields:



27
28
29
# File 'lib/influxdb/rails/httplog/http_log.rb', line 27

def configure
  yield(configuration)
end

.log(msg) ⇒ Object



105
106
107
108
109
# File 'lib/influxdb/rails/httplog/http_log.rb', line 105

def log(msg)
  return unless config.enabled

  config.logger.public_send(config.logger_method, config.severity, colorize(prefix + msg))
end

.log_benchmark(seconds) ⇒ Object



138
139
140
141
142
# File 'lib/influxdb/rails/httplog/http_log.rb', line 138

def log_benchmark(seconds)
  return unless config.log_benchmark

  log("Benchmark: #{seconds.to_f.round(6)} seconds")
end

.log_body(body, encoding = nil, content_type = nil) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/influxdb/rails/httplog/http_log.rb', line 144

def log_body(body, encoding = nil, content_type = nil)
  return unless config.log_response

  data = parse_body(body, encoding, content_type)

  if config.prefix_response_lines
    log('Response:')
    log_data_lines(data)
  else
    log("Response:\n#{data}")
  end
rescue BodyParsingError => e
  log("Response: #{e.message}")
end

.log_compact(method, uri, status, seconds) ⇒ Object



196
197
198
199
200
# File 'lib/influxdb/rails/httplog/http_log.rb', line 196

def log_compact(method, uri, status, seconds)
  return unless config.compact_log
  status = Rack::Utils.status_code(status) unless status == /\d{3}/
  log("#{method.to_s.upcase} #{masked(uri)} completed with status code #{status} in #{seconds.to_f.round(6)} seconds")
end

.log_connection(host, port = nil) ⇒ Object



111
112
113
114
115
# File 'lib/influxdb/rails/httplog/http_log.rb', line 111

def log_connection(host, port = nil)
  return if config.json_log || config.compact_log || !config.log_connect

  log("Connecting: #{[host, port].compact.join(':')}")
end

.log_data(data) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/influxdb/rails/httplog/http_log.rb', line 183

def log_data(data)
  return unless config.log_data

  data = utf_encoded(masked(data.dup).to_s) unless data.nil?

  if config.prefix_data_lines
    log('Data:')
    log_data_lines(data)
  else
    log("Data: #{data}")
  end
end

.log_headers(headers = {}) ⇒ Object



123
124
125
126
127
128
129
# File 'lib/influxdb/rails/httplog/http_log.rb', line 123

def log_headers(headers = {})
  return unless config.log_headers

  masked(headers).each do |key, value|
    log("Header: #{key}: #{value}")
  end
end

.log_json(data = {}) ⇒ Object



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/influxdb/rails/httplog/http_log.rb', line 202

def log_json(data = {})
  return unless config.json_log

  data[:response_code] = transform_response_code(data[:response_code]) if data[:response_code].is_a?(Symbol)

  parsed_body = begin
    parse_body(data[:response_body], data[:encoding], data[:content_type])
  rescue BodyParsingError => e
    e.message
  end

  if config.compact_log
    log({
      method: data[:method].to_s.upcase,
      url: masked(data[:url]),
      response_code: data[:response_code].to_i,
      benchmark: data[:benchmark]
    }.to_json)
  else
    log({
      method: data[:method].to_s.upcase,
      url: masked(data[:url]),
      request_body: masked(data[:request_body]),
      request_headers: masked(data[:request_headers].to_h),
      response_code: data[:response_code].to_i,
      response_body: parsed_body,
      response_headers: data[:response_headers].to_h,
      benchmark: data[:benchmark]
    }.to_json)
  end
end

.log_request(method, uri) ⇒ Object



117
118
119
120
121
# File 'lib/influxdb/rails/httplog/http_log.rb', line 117

def log_request(method, uri)
  return unless config.log_request

  log("Sending: #{method.to_s.upcase} #{masked(uri)}")
end

.log_status(status) ⇒ Object



131
132
133
134
135
136
# File 'lib/influxdb/rails/httplog/http_log.rb', line 131

def log_status(status)
  return unless config.log_status

  status = Rack::Utils.status_code(status) unless status == /\d{3}/
  log("Status: #{status}")
end

.parse_body(body, encoding, content_type) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/influxdb/rails/httplog/http_log.rb', line 159

def parse_body(body, encoding, content_type)
  unless text_based?(content_type)
    raise BodyParsingError, "(not showing binary data)"
  end

  if body.is_a?(Net::ReadAdapter)
    # open-uri wraps the response in a Net::ReadAdapter that defers reading
    # the content, so the reponse body is not available here.
    raise BodyParsingError, '(not available yet)'
  end

  if encoding =~ /gzip/ && body && !body.empty?
    begin
      sio = StringIO.new(body.to_s)
      gz = Zlib::GzipReader.new(sio)
      body = gz.read
    rescue Zlib::GzipFile::Error
      log("(gzip decompression failed)")
    end
  end

  utf_encoded(body.to_s, content_type)
end

.reset!Object



23
24
25
# File 'lib/influxdb/rails/httplog/http_log.rb', line 23

def reset!
  @http_configuration = nil
end

.save_in_db(options = {}) ⇒ Object



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
# File 'lib/influxdb/rails/httplog/http_log.rb', line 47

def save_in_db(options = {})
  #log("Connecting rails.http_client #{config.http_request_tracking_measurement} : #{config.http_request_tracking_id}")
  x_request_id = "AL_NONE"
  #al_txn_uid = nil
  al_request_id = "AL_NONE"
  al_request_guid = "AL_NONE"
  al_request_client_id = "AL_NONE"

  options[:request_headers].each do |header,value|
    al_request_client_id = value if(header === "al-request-client-id")
    #al_source = value if(header === "al-source")
    al_request_id = Thread.current["al_request_id"] if Thread.current["al_request_id"]
    al_request_guid = Thread.current["al_request_guid"] if Thread.current["al_request_guid"]

    #al_txn_uid = value if(header === config.http_request_tracking_id)
  end

  data = nil

  if options[:timestamp]
    data = {
        values: {value: options[:benchmark] ,  al_request_id: al_request_id, al_request_guid: al_request_guid, al_request_client_id: al_request_client_id},
        tags:   {app_name:  Rails.application.class.parent, url:  options[:url], method: options[:method], response_code: options[:response_code], location: InfluxDB::Rails.current.location},
        timestamp: options[:timestamp]
    }
  else
    data = {
        values: {value: options[:benchmark] , al_request_id: al_request_id, al_request_client_id: al_request_client_id},
        tags:   {app_name:  Rails.application.class.parent, url:    options[:url], method: options[:method], response_code: options[:response_code], location: InfluxDB::Rails.current.location},
    }
  end

  InfluxDB::Rails.client.write_point config.http_request_tracking_measurement, data
end

.series(options = {}) ⇒ Object



82
83
84
85
86
87
# File 'lib/influxdb/rails/httplog/http_log.rb', line 82

def series(options = {})
    {
        value: options[:benchmark]
    }
  
end

.tags(options = {}) ⇒ Object



89
90
91
92
93
94
95
96
97
# File 'lib/influxdb/rails/httplog/http_log.rb', line 89

def tags(options = {})
  tags = {
      method:      options[:method],
      url:         options[:url],
      app_name:    configuration.application_name,
      host:      Socket.gethostname
  }
  super(tags)
end

.transform_response_code(response_code_name) ⇒ Object



234
235
236
# File 'lib/influxdb/rails/httplog/http_log.rb', line 234

def transform_response_code(response_code_name)
  Rack::Utils::HTTP_STATUS_CODES.detect { |_k, v| v.to_s.casecmp(response_code_name.to_s).zero? }.first
end

.url_approved?(url) ⇒ Boolean

Returns:

  • (Boolean)


99
100
101
102
103
# File 'lib/influxdb/rails/httplog/http_log.rb', line 99

def url_approved?(url)
  return false if config.url_blacklist_pattern && url.to_s.match(config.url_blacklist_pattern)

  !config.url_whitelist_pattern || url.to_s.match(config.url_whitelist_pattern)
end