Class: IuguLogger::RequestLogger
- Inherits:
-
Object
- Object
- IuguLogger::RequestLogger
- Defined in:
- lib/iugu_logger/request_logger.rb
Overview
Rack middleware — emits ONE consolidated log per HTTP request:
event.action = http.request.completed (or http.request.failed on raise)
Behavior:
1. On request start: resets thread-local Buffer, populates context with
trace + iugu (auto-extracted from env via TraceContext / TenantContext).
2. App / controllers call IuguLogger::Buffer.current.push(...) for in-app
logs throughout the request. (Once Railtie lands in v0.5,
Rails.logger.X also routes here.)
3. On request end: drains the buffer, emits a single event including
`logs: [...]` (the buffered entries) plus http status and duration.
4. Always resets the buffer afterward.
Failures: when the downstream app raises, emits ‘http.request.failed` with the partial buffer + exception, then re-raises so other middleware sees the original error.
Insertion: typically right after Rails’ DebugExceptions and before ActionDispatch’s logger so we capture exceptions but bypass Rails’ own request logging.
Spec: IUGU_LOGGING_STANDARD.md §6 (RequestLogger middleware)
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app) ⇒ RequestLogger
constructor
A new instance of RequestLogger.
Constructor Details
#initialize(app) ⇒ RequestLogger
Returns a new instance of RequestLogger.
27 28 29 |
# File 'lib/iugu_logger/request_logger.rb', line 27 def initialize(app) @app = app end |
Instance Method Details
#call(env) ⇒ Object
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 |
# File 'lib/iugu_logger/request_logger.rb', line 31 def call(env) Buffer.reset! buffer = Buffer.current trace = TraceContext.extract(rack_env: env) req = build_request_block(env) # Tenant is best-effort here (covers Rack middleware upstream that may # have populated env['iugu.current_*']). The canonical timing is after # @app.call — host apps typically populate tenant in a controller # before_action, which only runs once Rails has dispatched the action. tenant = TenantContext.from_rack(env) buffer.add_context(trace: trace, iugu: tenant, request: req) start = monotonic_now status, headers, body = @app.call(env) duration_ms = elapsed_ms(start) # Re-read tenant: controllers may have populated env['iugu.current_*'] # via before_actions during @app.call. The earlier extraction would # have missed those — see spec §6.3 (RequestLogger / TenantContext). tenant = TenantContext.from_rack(env) # Enrich request with Rails dispatch info populated during @app.call # (params, format). Pre-call build_request_block couldn't see these. req = enrich_request_post_dispatch(req, env) emit_completed(req: req, trace: trace, tenant: tenant, status: status, duration_ms: duration_ms, rails: extract_rails_info(env), logs: buffer.drain) [status, headers, body] rescue StandardError => e duration_ms = elapsed_ms(start) # Same re-read on failure path: if the controller populated tenant # before raising, we should still report it. tenant = TenantContext.from_rack(env) req = enrich_request_post_dispatch(req, env) emit_failed(req: req, trace: trace, tenant: tenant, error: e, duration_ms: duration_ms, rails: extract_rails_info(env), logs: buffer&.drain || []) raise ensure Buffer.reset! end |