Class: Timber::Integrations::Rack::HTTPEvents
- Inherits:
-
Middleware
- Object
- Middleware
- Timber::Integrations::Rack::HTTPEvents
- Defined in:
- lib/timber-rack/http_events.rb
Overview
A Rack middleware that is reponsible for capturing and logging HTTP server requests and response events. The Events::HTTPRequest and Events::HTTPResponse events respectively.
Constant Summary collapse
- CONTENT_LENGTH_KEY =
'Content-Length'.freeze
Class Method Summary collapse
-
.capture_request_body=(value) ⇒ Object
Allows you to capture the HTTP request body, default is off (false).
-
.capture_request_body? ⇒ Boolean
Accessor method for #capture_request_body=.
-
.capture_response_body=(value) ⇒ Object
Just like #capture_request_body= but for the Events::HTTPResponse event.
-
.capture_response_body? ⇒ Boolean
Accessor method for #capture_response_body=.
-
.collapse_into_single_event=(value) ⇒ Object
Collapse both the HTTP request and response events into a single log line event.
-
.collapse_into_single_event? ⇒ Boolean
Accessor method for #collapse_into_single_event=.
-
.http_body_limit ⇒ Object
Accessor method for #http_body_limit=.
- .http_body_limit=(value) ⇒ Object
-
.http_header_filters ⇒ Object
Accessor method for #http_header_filters=.
- .http_header_filters=(value) ⇒ Object
-
.silence_request ⇒ Object
Accessor method for #silence_request=.
-
.silence_request=(proc) ⇒ Object
This setting allows you to silence requests based on any conditions you desire.
Instance Method Summary collapse
Methods inherited from Middleware
enabled=, enabled?, #initialize
Constructor Details
This class inherits a constructor from Timber::Integrations::Rack::Middleware
Class Method Details
.capture_request_body=(value) ⇒ Object
Allows you to capture the HTTP request body, default is off (false).
Capturing HTTP bodies can be extremely helpful when debugging issues, but please proceed with caution:
-
Capturing HTTP bodies can use quite a bit of data (this can be mitigated, see below)
If you opt to capture bodies, you can also truncate the size to reduce the data captured. See Events::HTTPRequest.
30 31 32 |
# File 'lib/timber-rack/http_events.rb', line 30 def capture_request_body=(value) @capture_request_body = value end |
.capture_request_body? ⇒ Boolean
Accessor method for #capture_request_body=
35 36 37 |
# File 'lib/timber-rack/http_events.rb', line 35 def capture_request_body? @capture_request_body == true end |
.capture_response_body=(value) ⇒ Object
Just like #capture_request_body= but for the Events::HTTPResponse event. Please see #capture_request_body= for more details. The documentation there also applies here.
42 43 44 |
# File 'lib/timber-rack/http_events.rb', line 42 def capture_response_body=(value) @capture_response_body = value end |
.capture_response_body? ⇒ Boolean
Accessor method for #capture_response_body=
47 48 49 |
# File 'lib/timber-rack/http_events.rb', line 47 def capture_response_body? @capture_response_body == true end |
.collapse_into_single_event=(value) ⇒ Object
Collapse both the HTTP request and response events into a single log line event. While we don’t recommend this, it can help to reduce log volume if desired. The reason we don’t recommend this, is because the logging service you use should not be so expensive that you need to strip out useful logs. It should also provide the tools necessary to properly search your logs and reduce noise. Such as viewing logs for a specific request.
To provide an example. This setting turns this:
Started GET "/" for 127.0.0.1 at 2012-03-10 14:28:14 +0100
Completed 200 OK in 79ms (Views: 78.8ms | ActiveRecord: 0.0ms)
Into this:
Get "/" sent 200 OK in 79ms
The single event is still a Events::HTTPResponse event. Because we capture HTTP context, you still get the HTTP details, but you will not get all of the request details that the Events::HTTPRequest event would provide.
74 75 76 |
# File 'lib/timber-rack/http_events.rb', line 74 def collapse_into_single_event=(value) @collapse_into_single_event = value end |
.collapse_into_single_event? ⇒ Boolean
Accessor method for #collapse_into_single_event=.
79 80 81 |
# File 'lib/timber-rack/http_events.rb', line 79 def collapse_into_single_event? @collapse_into_single_event == true end |
.http_body_limit ⇒ Object
Accessor method for #http_body_limit=
110 111 112 |
# File 'lib/timber-rack/http_events.rb', line 110 def http_body_limit @http_body_limit end |
.http_body_limit=(value) ⇒ Object
105 106 107 |
# File 'lib/timber-rack/http_events.rb', line 105 def http_body_limit=(value) @http_body_limit = value end |
.http_header_filters ⇒ Object
Accessor method for #http_header_filters=
119 120 121 |
# File 'lib/timber-rack/http_events.rb', line 119 def http_header_filters @http_header_filters end |
.http_header_filters=(value) ⇒ Object
114 115 116 |
# File 'lib/timber-rack/http_events.rb', line 114 def http_header_filters=(value) @http_header_filters = value end |
.silence_request ⇒ Object
Accessor method for #silence_request=
101 102 103 |
# File 'lib/timber-rack/http_events.rb', line 101 def silence_request @silence_request end |
.silence_request=(proc) ⇒ Object
This setting allows you to silence requests based on any conditions you desire. We require a block because it gives you complete control over how you want to silence requests. The first parameter being the traditional Rack env hash, the second being a [Rack Request](www.rubydoc.info/gems/rack/Rack/Request) object.
92 93 94 95 96 97 98 |
# File 'lib/timber-rack/http_events.rb', line 92 def silence_request=(proc) if proc && !proc.is_a?(Proc) raise ArgumentError.new("The value passed to #silence_request must be a Proc") end @silence_request = proc end |
Instance Method Details
#call(env) ⇒ Object
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 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/timber-rack/http_events.rb', line 126 def call(env) request = Util::Request.new(env) if silenced?(env, request) if Config.instance.logger.respond_to?(:silence) Config.instance.logger.silence do @app.call(env) end else @app.call(env) end elsif collapse_into_single_event? start = Time.now status, headers, body = @app.call(env) Config.instance.logger.info do http_context = CurrentContext.fetch(:http) content_length = headers[CONTENT_LENGTH_KEY] duration_ms = (Time.now - start) * 1000.0 http_response = HTTPResponse.new( content_length: content_length, headers: headers, http_context: http_context, request_id: request.request_id, status: status, duration_ms: duration_ms, body_limit: self.class.http_body_limit, headers_to_sanitize: self.class.http_header_filters, ) { message: http_response., event: { http_response_sent: { body: http_response.body, content_length: http_response.content_length, headers_json: http_response.headers_json, request_id: http_response.request_id, service_name: http_response.service_name, status: http_response.status, duration_ms: http_response.duration_ms, } } } end [status, headers, body] else start = Time.now Config.instance.logger.info do event_body = capture_request_body? ? request.body_content : nil http_request = HTTPRequest.new( body: event_body, content_length: request.content_length, headers: request.headers, host: request.host, method: request.request_method, path: request.path, port: request.port, query_string: request.query_string, request_id: request.request_id, scheme: request.scheme, body_limit: self.class.http_body_limit, headers_to_sanitize: self.class.http_header_filters, ) { message: http_request., event: { http_request_received: { body: http_request.body, content_length: http_request.content_length, headers_json: http_request.headers_json, host: http_request.host, method: http_request.method, path: http_request.path, port: http_request.port, query_string: http_request.query_string, request_id: http_request.request_id, scheme: http_request.scheme, service_name: http_request.service_name, } } } end status, headers, body = @app.call(env) Config.instance.logger.info do event_body = capture_response_body? ? body : nil content_length = headers[CONTENT_LENGTH_KEY] duration_ms = (Time.now - start) * 1000.0 http_response = HTTPResponse.new( body: event_body, content_length: content_length, headers: headers, request_id: request.request_id, status: status, duration_ms: duration_ms, body_limit: self.class.http_body_limit, headers_to_sanitize: self.class.http_header_filters, ) { message: http_response., event: { http_response_sent: { body: http_response.body, content_length: http_response.content_length, headers_json: http_response.headers_json, request_id: http_response.request_id, service_name: http_response.service_name, status: http_response.status, duration_ms: http_response.duration_ms, } } } end [status, headers, body] end end |