Module: RailsOtelContext::FrameContext
- Defined in:
- lib/rails_otel_context/frame_context.rb
Overview
Thread-local storage for explicitly pushed call-frame context.
The default code.namespace / code.function attributes are extracted by walking the Ruby call stack on every span start. That works, but costs O(stack depth) object allocations per span. FrameContext eliminates the walk by letting call sites push their class+method once at entry:
RailsOtelContext::FrameContext.with_frame(class_name: 'OrdersController',
method_name: 'create') do
# every span created inside here reads the pushed frame — no stack walk
end
The Railtie automatically installs an around_action that pushes the controller frame for all controller actions. For jobs, service objects, or any other code that creates spans, use with_frame directly or include RailsOtelContext::Frameable.
The pushed frame is a fallback for the span processor: the stack walk still runs when no frame is pushed, so existing behavior is preserved.
Class Method Summary collapse
-
.current ⇒ Object
Returns the currently pushed frame hash, or nil.
-
.pop ⇒ Object
(also: clear!)
Clears the pushed frame.
-
.push(class_name:, method_name:, filepath: nil, lineno: nil) ⇒ Object
Manual push without a block.
-
.with_frame(class_name:, method_name:, filepath: nil, lineno: nil) ⇒ Object
Pushes
class_name/method_namefor the duration of the block, restoring whatever was pushed before (supports nesting).
Class Method Details
.current ⇒ Object
Returns the currently pushed frame hash, or nil.
51 52 53 |
# File 'lib/rails_otel_context/frame_context.rb', line 51 def current Thread.current[FRAME_KEY] end |
.pop ⇒ Object Also known as: clear!
Clears the pushed frame. Pair with push in an ensure block.
46 47 48 |
# File 'lib/rails_otel_context/frame_context.rb', line 46 def pop Thread.current[FRAME_KEY] = nil end |
.push(class_name:, method_name:, filepath: nil, lineno: nil) ⇒ Object
Manual push without a block. Caller must call pop in an ensure.
41 42 43 |
# File 'lib/rails_otel_context/frame_context.rb', line 41 def push(class_name:, method_name:, filepath: nil, lineno: nil) Thread.current[FRAME_KEY] = build_frame(class_name, method_name, filepath, lineno) end |
.with_frame(class_name:, method_name:, filepath: nil, lineno: nil) ⇒ Object
Pushes class_name/method_name for the duration of the block, restoring whatever was pushed before (supports nesting). Optional filepath: and lineno: are carried through to the span processor so DB adapter call-site info survives the span lifecycle.
32 33 34 35 36 37 38 |
# File 'lib/rails_otel_context/frame_context.rb', line 32 def with_frame(class_name:, method_name:, filepath: nil, lineno: nil) prev = Thread.current[FRAME_KEY] Thread.current[FRAME_KEY] = build_frame(class_name, method_name, filepath, lineno) yield ensure Thread.current[FRAME_KEY] = prev end |