sentry-opentelemetry/lib/sentry/opentelemetry/propagator.rb
# frozen_string_literal: true
module Sentry
module OpenTelemetry
class Propagator
FIELDS = [SENTRY_TRACE_HEADER_NAME, BAGGAGE_HEADER_NAME].freeze
SENTRY_TRACE_KEY = ::OpenTelemetry::Context.create_key("sentry-trace")
SENTRY_BAGGAGE_KEY = ::OpenTelemetry::Context.create_key("sentry-baggage")
def inject(
carrier,
context: ::OpenTelemetry::Context.current,
setter: ::OpenTelemetry::Context::Propagation.text_map_setter
)
span_context = ::OpenTelemetry::Trace.current_span(context).context
return unless span_context.valid?
span_map = SpanProcessor.instance.span_map
sentry_span = span_map[span_context.hex_span_id]
return unless sentry_span
setter.set(carrier, SENTRY_TRACE_HEADER_NAME, sentry_span.to_sentry_trace)
baggage = sentry_span.to_baggage
setter.set(carrier, BAGGAGE_HEADER_NAME, baggage) if baggage && !baggage.empty?
end
def extract(
carrier,
context: ::OpenTelemetry::Context.current,
getter: ::OpenTelemetry::Context::Propagation.text_map_getter
)
sentry_trace = getter.get(carrier, SENTRY_TRACE_HEADER_NAME)
return context unless sentry_trace
sentry_trace_data = Transaction.extract_sentry_trace(sentry_trace)
return context unless sentry_trace_data
context = context.set_value(SENTRY_TRACE_KEY, sentry_trace_data)
trace_id, span_id, _parent_sampled = sentry_trace_data
span_context = ::OpenTelemetry::Trace::SpanContext.new(
trace_id: [trace_id].pack("H*"),
span_id: [span_id].pack("H*"),
# we simulate a sampled trace on the otel side and leave the sampling to sentry
trace_flags: ::OpenTelemetry::Trace::TraceFlags::SAMPLED,
remote: true
)
baggage_header = getter.get(carrier, BAGGAGE_HEADER_NAME)
baggage =
if baggage_header && !baggage_header.empty?
Baggage.from_incoming_header(baggage_header)
else
# If there's an incoming sentry-trace but no incoming baggage header,
# for instance in traces coming from older SDKs,
# baggage will be empty and frozen and won't be populated as head SDK.
Baggage.new({})
end
baggage.freeze!
context = context.set_value(SENTRY_BAGGAGE_KEY, baggage)
span = ::OpenTelemetry::Trace.non_recording_span(span_context)
::OpenTelemetry::Trace.context_with_span(span, parent_context: context)
end
def fields
FIELDS
end
end
end
end