diff --git a/api/lib/opentelemetry/context.rb b/api/lib/opentelemetry/context.rb index 42f12d3d7d..6ca0f4334f 100644 --- a/api/lib/opentelemetry/context.rb +++ b/api/lib/opentelemetry/context.rb @@ -28,8 +28,9 @@ def create_key(name) # Returns current context, which is never nil # # @return [Context] - def current - stack.last || ROOT + def current(thread = Thread.current) + # Avoid calling #stack directly so as to not have races in initializing the storage + thread[STACK_KEY]&.last || ROOT end # Associates a Context with the caller's current Fiber. Every call to diff --git a/api/test/opentelemetry/context_test.rb b/api/test/opentelemetry/context_test.rb index a25bf2281a..965d015e5b 100644 --- a/api/test/opentelemetry/context_test.rb +++ b/api/test/opentelemetry/context_test.rb @@ -333,5 +333,25 @@ _(Context.current[bar_key]).must_be_nil end end + + it 'allows accessing the current context for another thread' do + another_thread_context = Queue.new + + another_thread = Thread.new do + ctx = Context.empty.set_value(foo_key, 'bar') + Context.with_current(ctx) do + another_thread_context << Context.current + sleep + end + end + + ctx = another_thread_context.pop + + _(Context.current(another_thread)).must_equal(ctx) + _(Context.current).wont_equal(ctx) + + another_thread.kill + another_thread.join + end end end