# 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