From 59921ee75396721f4ea27553b1ff2b651a9e0dbc Mon Sep 17 00:00:00 2001 From: Ivo Anjo Date: Fri, 25 Jun 2021 11:28:38 +0100 Subject: [PATCH] rfc: Allow reading current context for another thread I've been working on integrating Datadog's continuous profiler with opentelemetry traces (see Datadog/dd-trace-rb#1568). The profiler runs on a background thread, and needs to be able to access the current context for a thread, to be able to get the current span's trace id and span ids (if any active). To do so, I was originally using ```ruby thread = ... ::OpenTelemetry::Trace.current_span(thread[::OpenTelemetry::Context::KEY]) ``` Unfortunately, after #807, this interface was changed, and more importantly, `Context::KEY` was removed and replaced with `Context::STACK_KEY`. `STACK_KEY` was marked as `private_constant`. With 1.0.0.rc2, the only way of getting this information is by relying on private implementation details, which isn't great. Thus, I would like to ask if it'd be reasonable to add an optional `thread` parameter to `Context.current`. This would make it easy to access the needed information, and it would even be more future-proof as the outside code doesn't need to care anymore where and how the context is stored. --- api/lib/opentelemetry/context.rb | 8 ++++---- api/test/opentelemetry/context_test.rb | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/api/lib/opentelemetry/context.rb b/api/lib/opentelemetry/context.rb index 42f12d3d7d..185cad310c 100644 --- a/api/lib/opentelemetry/context.rb +++ b/api/lib/opentelemetry/context.rb @@ -28,8 +28,8 @@ def create_key(name) # Returns current context, which is never nil # # @return [Context] - def current - stack.last || ROOT + def current(thread = nil) + stack(thread).last || ROOT end # Associates a Context with the caller's current Fiber. Every call to @@ -123,8 +123,8 @@ def empty private - def stack - Thread.current[STACK_KEY] ||= [] + def stack(thread = nil) + (thread || Thread.current)[STACK_KEY] ||= [] end end 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