Skip to content

Commit

Permalink
Use alternative context implementation
Browse files Browse the repository at this point in the history
We should still do some benchmarking, but I think this is going to be a
better implementation, so I'm preemptively using it for the purpose of
the initial PR.
  • Loading branch information
mwear committed Dec 25, 2019
1 parent 804bcf2 commit a226469
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 17 deletions.
20 changes: 11 additions & 9 deletions api/lib/opentelemetry/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ module OpenTelemetry
# Manages context on a per-thread basis
class Context
KEY = :__opentelemetry_context__
EMPTY_ENTRIES = {}.freeze

class << self
# Returns current context, which is never nil
Expand Down Expand Up @@ -80,21 +79,26 @@ def clear
end

def empty
new(nil, EMPTY_ENTRIES)
new(nil, nil, nil)
end
end

def initialize(parent = nil, entries = {})
def initialize(parent, key, value)
@parent = parent
@entries = entries.freeze
@key = key
@value = value
end

# Returns the corresponding value (or nil) for key
#
# @param [String] key The lookup key
# @return [Object]
def value(key)
@entries[key]
if key == @key
@value
elsif @parent
@parent.value(key)
end
end

alias [] value
Expand All @@ -105,9 +109,7 @@ def value(key)
# @param [Object] value Object to be stored under key
# @return [Context]
def set_value(key, value)
new_entries = @entries.dup
new_entries[key] = value
Context.new(self, new_entries)
Context.new(self, key, value)
end

# Returns a new Context with the current context's entries merged with the
Expand All @@ -118,7 +120,7 @@ def set_value(key, value)
# @param [Object] value Object to be stored under key
# @return [Context]
def set_values(values) # rubocop:disable Naming/AccessorMethodName:
Context.new(self, @entries.merge(values))
values.inject(self) { |parent, (k, v)| Context.new(parent, k, v) }
end

# Makes the this context the currently active context and returns the
Expand Down
18 changes: 10 additions & 8 deletions api/test/opentelemetry/context_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
Context.clear
end

let(:new_context) { Context.new(nil, 'foo', 'bar') }

describe '.current' do
it 'defaults to the root context' do
_(Context.current).must_equal(Context::ROOT)
Expand All @@ -23,7 +25,7 @@

describe '.with_current' do
it 'handles nested contexts' do
c1 = Context.new(nil, 'foo' => 'bar')
c1 = new_context
Context.with_current(c1) do
_(Context.current).must_equal(c1)
c2 = Context.current.set_value('bar', 'baz')
Expand All @@ -35,7 +37,7 @@
end

it 'resets context when an exception is raised' do
c1 = Context.new(nil, 'foo' => 'bar')
c1 = new_context
Context.current = c1

_(proc do
Expand Down Expand Up @@ -68,7 +70,7 @@

describe '#value' do
it 'returns corresponding value for key' do
ctx = Context.new(nil, 'foo' => 'bar')
ctx = new_context
_(ctx.value('foo')).must_equal('bar')
end
end
Expand All @@ -93,15 +95,15 @@

describe '#set_values' do
it 'assigns multiple values' do
ctx = Context.new(nil, 'foo' => 'bar')
ctx = new_context
ctx2 = ctx.set_values('bar' => 'baz', 'baz' => 'quux')
_(ctx2.value('foo')).must_equal('bar')
_(ctx2.value('bar')).must_equal('baz')
_(ctx2.value('baz')).must_equal('quux')
end

it 'merges new values' do
ctx = Context.new(nil, 'foo' => 'bar')
ctx = new_context
ctx2 = ctx.set_values('foo' => 'foobar', 'bar' => 'baz')
_(ctx2.value('foo')).must_equal('foobar')
_(ctx2.value('bar')).must_equal('baz')
Expand Down Expand Up @@ -152,7 +154,7 @@
end

it 'restores root for ctx without parent' do
ctx = Context.new(nil, 'foo' => 'bar')
ctx = new_context
ctx.detach
_(Context.current).must_equal(Context::ROOT)
end
Expand Down Expand Up @@ -184,7 +186,7 @@

describe 'threading' do
it 'unwinds the stack on each thread' do
ctx = Context.new(nil, 'foo' => 'bar')
ctx = new_context
t1_ctx_before = Context.current
Context.with_current(ctx) do
Thread.new do
Expand All @@ -204,7 +206,7 @@
end

it 'scopes changes to the current thread' do
ctx = Context.new(nil, 'foo' => 'bar')
ctx = new_context
Context.with_current(ctx) do
Thread.new do
Context.with_current(ctx) do
Expand Down

0 comments on commit a226469

Please sign in to comment.