Skip to content

Commit 60aa1a0

Browse files
committed
Use a Fiber attribute for Context
1 parent 59d1bf8 commit 60aa1a0

File tree

2 files changed

+72
-7
lines changed

2 files changed

+72
-7
lines changed

api/lib/opentelemetry/context.rb

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
require 'opentelemetry/context/propagation'
99

1010
module OpenTelemetry
11+
Fiber.attr_accessor :opentelemetry_context
12+
1113
# Manages context on a per-fiber basis
1214
class Context
1315
EMPTY_ENTRIES = {}.freeze
14-
STACK_KEY = :__opentelemetry_context_storage__
15-
private_constant :EMPTY_ENTRIES, :STACK_KEY
16+
private_constant :EMPTY_ENTRIES
1617

1718
DetachError = Class.new(OpenTelemetry::Error)
1819

@@ -113,11 +114,9 @@ def value(key)
113114
current.value(key)
114115
end
115116

116-
# Clears the fiber-local Context stack. This allocates a new array for the
117-
# stack, which is important in some use-cases to avoid sharing the backing
118-
# array between fibers.
117+
# Clears the fiber-local Context stack.
119118
def clear
120-
Thread.current[STACK_KEY] = []
119+
Fiber.current.opentelemetry_context = []
121120
end
122121

123122
def empty
@@ -127,7 +126,7 @@ def empty
127126
private
128127

129128
def stack
130-
Thread.current[STACK_KEY] ||= []
129+
Fiber.current.opentelemetry_context ||= []
131130
end
132131
end
133132

api/test/opentelemetry/context_test.rb

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,73 @@
289289
end
290290
end
291291

292+
describe 'fibers' do
293+
it 'is isolated with respect to Fiber-local variable manipulation' do
294+
OpenTelemetry::TestHelpers.with_test_logger do |log_stream|
295+
ctx = new_context
296+
Context.with_current(ctx) do
297+
# This is based on code in ActionController::Live#process:
298+
# https://github.com/rails/rails/blob/ad0105c13f61d145a659004efb928a643104e973/actionpack/lib/action_controller/metal/live.rb#L270
299+
t1 = Thread.current
300+
locals = t1.keys.map { |key| [key, t1[key]] }
301+
Fiber.new do
302+
t2 = Thread.current
303+
locals.each { |k, v| t2[k] = v }
304+
# Manipulate _this fiber's_ context stack.
305+
Context.attach(new_context)
306+
ensure
307+
locals.each { |k, _| t2[k] = nil }
308+
end.resume
309+
end
310+
_(log_stream.string).must_be_empty
311+
end
312+
end
313+
314+
it 'is isolated with respect to Fiber-local storage manipulation' do
315+
OpenTelemetry::TestHelpers.with_test_logger do |log_stream|
316+
ctx = new_context
317+
Context.with_current(ctx) do
318+
# This is based on code in ActionController::Live#process, modified to use Fiber-local storage:
319+
# https://github.com/rails/rails/blob/ad0105c13f61d145a659004efb928a643104e973/actionpack/lib/action_controller/metal/live.rb#L270
320+
f1 = Fiber.current
321+
Fiber[:foo] = :bar
322+
locals = f1.storage
323+
Fiber.new do
324+
f2 = Fiber.current
325+
locals.each { |k, v| f2.storage[k] = v }
326+
# Manipulate _this fiber's_ context stack.
327+
Context.attach(new_context)
328+
ensure
329+
locals.each { |k, _| f2.storage[k] = nil }
330+
end.resume
331+
end
332+
_(log_stream.string).must_be_empty
333+
end
334+
end
335+
end
336+
292337
describe 'threading' do
338+
it 'is isolated with respect to Fiber-local variable manipulation' do
339+
OpenTelemetry::TestHelpers.with_test_logger do |log_stream|
340+
ctx = new_context
341+
Context.with_current(ctx) do
342+
# This is based on code in ActionController::Live#process:
343+
# https://github.com/rails/rails/blob/ad0105c13f61d145a659004efb928a643104e973/actionpack/lib/action_controller/metal/live.rb#L270
344+
t1 = Thread.current
345+
locals = t1.keys.map { |key| [key, t1[key]] }
346+
Thread.new do
347+
t2 = Thread.current
348+
locals.each { |k, v| t2[k] = v }
349+
# Manipulate _this thread's_ context stack.
350+
Context.attach(new_context)
351+
ensure
352+
locals.each { |k, _| t2[k] = nil }
353+
end.join
354+
end
355+
_(log_stream.string).must_be_empty
356+
end
357+
end
358+
293359
it 'unwinds the stack on each thread' do
294360
ctx = new_context
295361
t1_ctx_before = Context.current

0 commit comments

Comments
 (0)