Class: RailsOtelContext::BodyCapture
- Inherits:
-
Object
- Object
- RailsOtelContext::BodyCapture
- Defined in:
- lib/rails_otel_context/body_capture.rb
Overview
Rack middleware that captures request and response bodies as OpenTelemetry span attributes. Works with any OTel Rack instrumentation — the middleware must sit inside (after) the span-creating middleware so current_span is set.
Usage:
# config/application.rb (or an initializer after OTel is configured)
config.middleware.use RailsOtelContext::BodyCapture
# With options:
config.middleware.use RailsOtelContext::BodyCapture,
on_error_only: true,
max_bytes: 4096
Span attributes set:
http.request.body — captured request body (when content type matches)
http.response.body — captured response body (when content type matches)
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, capture_request: true, capture_response: true, max_bytes: DEFAULT_MAX_BYTES, on_error_only: false, content_types: DEFAULT_CONTENT_TYPES, include_paths: [], exclude_paths: DEFAULT_EXCLUDE_PATHS) ⇒ BodyCapture
constructor
rubocop:disable Metrics/ParameterLists.
Constructor Details
#initialize(app, capture_request: true, capture_response: true, max_bytes: DEFAULT_MAX_BYTES, on_error_only: false, content_types: DEFAULT_CONTENT_TYPES, include_paths: [], exclude_paths: DEFAULT_EXCLUDE_PATHS) ⇒ BodyCapture
rubocop:disable Metrics/ParameterLists
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/rails_otel_context/body_capture.rb', line 28 def initialize(app, # rubocop:disable Metrics/ParameterLists capture_request: true, capture_response: true, max_bytes: DEFAULT_MAX_BYTES, on_error_only: false, content_types: DEFAULT_CONTENT_TYPES, include_paths: [], exclude_paths: DEFAULT_EXCLUDE_PATHS) @app = app @capture_request = capture_request @capture_response = capture_response @max_bytes = max_bytes @on_error_only = on_error_only @content_types = content_types @include_paths = include_paths @exclude_paths = exclude_paths end |
Instance Method Details
#call(env) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/rails_otel_context/body_capture.rb', line 46 def call(env) return @app.call(env) unless should_capture?(env['PATH_INFO']) request_str = read_request(env) status, headers, body = @app.call(env) # With on_error_only, skip body drain on successful responses — no buffering # overhead on the happy path. (Synchronous Rack means we know status before # deciding to drain, unlike async frameworks that must always buffer.) should_record = !@on_error_only || status >= 400 if should_record && @capture_response body, response_str = drain_response(body, headers) end set_span_attributes(request_str, response_str) if should_record [status, headers, body] end |