Module: Datadog::OpenTelemetry::API::Context

Defined in:
lib/datadog/opentelemetry/api/context.rb

Overview

The OpenTelemetry Context contains a key-value store that can be attached to a trace.

It loosely matches our ‘TraceOperations#tags`, except for the following:

  • Context can store arbitrary objects as values. One example is for the key ‘Context::Key.new(’current-span’)‘, which is associated with a `Span` object. In contrast, `TraceOperations#tags` only stores string values.

  • Context is how spans know who their parent span is. The parenting operation happens on every span created. Parenting is not directly tied to the active Fiber or Thread.

  • Context is immutable: changing a value creates a copy of Context.

  • Context is not bound to a specific trace: it can be reused an arbitrary number of times.

Defined Under Namespace

Modules: SingletonClass

Constant Summary collapse

BAGGAGE_REMOVE_KEY =

sentinel object to indicate the deletion of a value in baggage

Object.new

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.prepended(base) ⇒ Object



179
180
181
# File 'lib/datadog/opentelemetry/api/context.rb', line 179

def self.prepended(base)
  base.singleton_class.prepend(SingletonClass)
end

Instance Method Details

#ensure_traceObject

Because Context can be reused, we have to make sure we have a valid ‘TraceOperation` on every invocation.



35
36
37
38
39
40
41
# File 'lib/datadog/opentelemetry/api/context.rb', line 35

def ensure_trace
  return nil unless @trace

  # The Context can be reused after the root span has finished.
  @trace.send(:reset) if @trace.finished?
  @trace
end

#initialize(entries, trace: nil, baggage: nil) ⇒ Object



26
27
28
29
30
31
# File 'lib/datadog/opentelemetry/api/context.rb', line 26

def initialize(entries, trace: nil, baggage: nil)
  @trace = trace || ::Datadog::Tracing.send(:tracer).send(:start_trace)
  @trace.otel_values.merge!(entries) if entries
  @trace.otel_context ||= self
  @trace.baggage = baggage if baggage
end

#set_value(key, value) ⇒ Context

Returns a new Context where entries contains the newly added key and value

Parameters:

  • key (Key)

    The key to store this value under

  • value (Object)

    Object to be stored under key

Returns:



60
61
62
# File 'lib/datadog/opentelemetry/api/context.rb', line 60

def set_value(key, value)
  set_values(key => value)
end

#set_values(values) ⇒ Context

Returns a new Context with the current context’s entries merged with the

new entries

Parameters:

  • values (Hash)

    The values to be merged with the current context’s entries.

  • value (Object)

    Object to be stored under key

Returns:



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/datadog/opentelemetry/api/context.rb', line 71

def set_values(values)
  if (current_span = values[CURRENT_SPAN_KEY]) && current_span.datadog_trace
    # Because `#set_value` returns new context, we have to create
    # a new copy of the active trace to ensure there's no conflict with
    # other users of the active trace.
    # It effectively becomes an internal trace propagation.
    trace = Datadog::OpenTelemetry::Trace.start_trace_copy(
      current_span.datadog_trace,
      parent_span: current_span.datadog_span
    )
  end

  existing_values = @trace && @trace.otel_values || {}
  existing_baggage = @trace && @trace.baggage || {}

  # Retrieve the baggage removal sentinel and remove it from the values hash
  existing_baggage.delete(values[BAGGAGE_REMOVE_KEY]) if values.key?(BAGGAGE_REMOVE_KEY)

  # If the values hash contains a BAGGAGE_KEY, merge its contents with existing baggage
  # Otherwise, keep the existing baggage unchanged
  new_baggage = if values.key?(::OpenTelemetry::Baggage.const_get(:BAGGAGE_KEY))
                  existing_baggage.merge(values[::OpenTelemetry::Baggage.const_get(:BAGGAGE_KEY)])
                else
                  existing_baggage
                end

  ::OpenTelemetry::Context.new(existing_values.merge(values), trace: trace, baggage: new_baggage)
end

#traceObject

The Datadog TraceOperation associated with this Datadog::OpenTelemetry::API::Context.



101
102
103
# File 'lib/datadog/opentelemetry/api/context.rb', line 101

def trace
  @trace
end

#value(key) ⇒ Object Also known as: []

Returns the corresponding value (or nil) for key

Parameters:

  • key (Key)

    The lookup key

Returns:

  • (Object)


47
48
49
50
51
# File 'lib/datadog/opentelemetry/api/context.rb', line 47

def value(key)
  return nil unless @trace

  @trace.otel_value(key)
end