lib/opentelemetry/context.rb in opentelemetry-api-0.2.0 vs lib/opentelemetry/context.rb in opentelemetry-api-0.3.0
- old
+ new
@@ -2,30 +2,153 @@
# Copyright 2019 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0
+require 'opentelemetry/context/key'
+require 'opentelemetry/context/propagation'
+
module OpenTelemetry
- # The Context module provides per-thread storage.
- module Context
- extend self
+ # Manages context on a per-fiber basis
+ class Context
+ KEY = :__opentelemetry_context__
+ EMPTY_ENTRIES = {}.freeze
- def get(key)
- storage[key]
+ class << self
+ # Returns a key used to index a value in a Context
+ #
+ # @param [String] name The key name
+ # @return [Context::Key]
+ def create_key(name)
+ Key.new(name)
+ end
+
+ # Returns current context, which is never nil
+ #
+ # @return [Context]
+ def current
+ Thread.current[KEY] ||= ROOT
+ end
+
+ # Sets the current context
+ #
+ # @param [Context] ctx The context to be made active
+ def current=(ctx)
+ Thread.current[KEY] = ctx
+ end
+
+ # Executes a block with ctx as the current context. It restores
+ # the previous context upon exiting.
+ #
+ # @param [Context] ctx The context to be made active
+ # @yield [context] Yields context to the block
+ def with_current(ctx)
+ prev = ctx.attach
+ yield ctx
+ ensure
+ ctx.detach(prev)
+ end
+
+ # Execute a block in a new context with key set to value. Restores the
+ # previous context after the block executes.
+
+ # @param [String] key The lookup key
+ # @param [Object] value The object stored under key
+ # @param [Callable] Block to execute in a new context
+ # @yield [context, value] Yields the newly created context and value to
+ # the block
+ def with_value(key, value)
+ ctx = current.set_value(key, value)
+ prev = ctx.attach
+ yield ctx, value
+ ensure
+ ctx.detach(prev)
+ end
+
+ # Execute a block in a new context where its values are merged with the
+ # incoming values. Restores the previous context after the block executes.
+
+ # @param [String] key The lookup key
+ # @param [Hash] values Will be merged with values of the current context
+ # and returned in a new context
+ # @param [Callable] Block to execute in a new context
+ # @yield [context, values] Yields the newly created context and values
+ # to the block
+ def with_values(values)
+ ctx = current.set_values(values)
+ prev = ctx.attach
+ yield ctx, values
+ ensure
+ ctx.detach(prev)
+ end
+
+ # Returns the value associated with key in the current context
+ #
+ # @param [String] key The lookup key
+ def value(key)
+ current.value(key)
+ end
+
+ def clear
+ self.current = ROOT
+ end
+
+ def empty
+ new(nil, EMPTY_ENTRIES)
+ end
end
- def with(key, value)
- store = storage
- previous = store[key]
- store[key] = value
- yield value
- ensure
- store[key] = previous
+ def initialize(parent, entries)
+ @parent = parent
+ @entries = entries.freeze
end
- private
+ # Returns the corresponding value (or nil) for key
+ #
+ # @param [Key] key The lookup key
+ # @return [Object]
+ def value(key)
+ @entries[key]
+ end
- def storage
- Thread.current[:__opentelemetry__] ||= {}
+ alias [] value
+
+ # Returns a new Context where entries contains the newly added key and value
+ #
+ # @param [Key] key The key to store this value under
+ # @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)
end
+
+ # Returns a new Context with the current context's entries merged with the
+ # new entries
+ #
+ # @param [Hash] values The values to be merged with the current context's
+ # entries.
+ # @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))
+ end
+
+ # @api private
+ def attach
+ prev = self.class.current
+ self.class.current = self
+ prev
+ end
+
+ # @api private
+ def detach(ctx_to_attach = nil)
+ OpenTelemetry.logger.warn 'Calls to detach should match corresponding calls to attach' if self.class.current != self
+
+ ctx_to_attach ||= @parent || ROOT
+ ctx_to_attach.attach
+ end
+
+ ROOT = empty.freeze
end
end