Class: Foam::Otel::HeaderCapture::FaradayMiddleware

Inherits:
Object
  • Object
show all
Defined in:
lib/foam/otel/header_capture.rb

Overview

Outbound header capture on the official Faraday CLIENT span, via Faraday's first-class public middleware API (a plain #call(env) middleware — no inheritance from Faraday internals, so this file loads without Faraday present). Unlike inbound (the official rack gem's named allowlist), this captures EVERY outbound header — the faraday instrumentation has no header option, so foam's middleware is the seam and it has no list to be limited by (explicitly accepted asymmetry, user ruling 2026-07-28). It must sit directly INSIDE the official :open_telemetry middleware (README recipe):

Faraday.new(url) do |f|
f.use :open_telemetry     # the official client span
f.use :foam_otel_headers  # foam's header capture, inside it
end

because the official tracer middleware activates its span only around the handlers BELOW it. The scope gate makes any other placement a silent no-op — never a wrong-span write (GOTCHAS F14).

Instance Method Summary collapse

Constructor Details

#initialize(app, *_args) ⇒ FaradayMiddleware

Returns a new instance of FaradayMiddleware.



346
347
348
# File 'lib/foam/otel/header_capture.rb', line 346

def initialize(app, *_args)
  @app = app
end

Instance Method Details

#call(env) ⇒ Object

Request headers are captured on the way in (the traceparent the official middleware injected included — it IS an outbound header); response headers via the response's public on_complete hook, which runs while the official span is still open (its own status hook rides the same mechanism). The app's/adapter's exception propagates untouched.



356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'lib/foam/otel/header_capture.rb', line 356

def call(env)
  span = capturable_span
  set_request_headers(span, env) unless span.nil?
  response = @app.call(env)
  unless span.nil?
    begin
      response.on_complete { |renv| set_response_headers(span, renv) }
    rescue StandardError, SystemStackError
      nil
    end
  end
  response
end