module OpenTelemetry::Propagator::B3::TextMapExtractor

Extracts trace context using the b3 single or multi header formats, favouring b3 single header.

Constants

B3_CONTEXT_KEY
B3_CONTEXT_REGEX
B3_FLAGS_KEY
B3_SAMPLED_KEY
B3_SPAN_ID_KEY
B3_SPAN_ID_REGEX
B3_TRACE_ID_KEY
B3_TRACE_ID_REGEX
SAMPLED_VALUES

Public Instance Methods

extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter) click to toggle source

Extract trace context from the supplied carrier. The b3 single header takes precedence over the multi-header format. If extraction fails, the original context will be returned.

@param [Carrier] carrier The carrier to get the header from @param [optional Context] context Context to be updated with the trace context

extracted from the carrier. Defaults to +Context.current+.

@param [optional Getter] getter If the optional getter is provided, it

will be used to read the header from the carrier, otherwise the default
text map getter will be used.

@return [Context] context updated with extracted baggage, or the original context

if extraction fails
# File lib/opentelemetry/propagator/b3/text_map_extractor.rb, line 47
def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
  extract_b3_single_header(carrier, context, getter) || extract_b3_multi_header(carrier, context, getter) || context
end

Private Instance Methods

extract_b3_multi_header(carrier, context, getter) click to toggle source
# File lib/opentelemetry/propagator/b3/text_map_extractor.rb, line 62
def extract_b3_multi_header(carrier, context, getter)
  trace_id_hex = getter.get(carrier, B3_TRACE_ID_KEY)
  return unless B3_TRACE_ID_REGEX.match?(trace_id_hex)

  span_id_hex = getter.get(carrier, B3_SPAN_ID_KEY)
  return unless B3_SPAN_ID_REGEX.match?(span_id_hex)

  sampled = getter.get(carrier, B3_SAMPLED_KEY)
  flags = getter.get(carrier, B3_FLAGS_KEY)

  debug = flags == '1'
  sampled = debug || SAMPLED_VALUES.include?(sampled)
  extracted_context(trace_id_hex, span_id_hex, sampled, debug, context)
end
extract_b3_single_header(carrier, context, getter) click to toggle source
# File lib/opentelemetry/propagator/b3/text_map_extractor.rb, line 53
def extract_b3_single_header(carrier, context, getter)
  match = getter.get(carrier, B3_CONTEXT_KEY)&.match(B3_CONTEXT_REGEX)
  return unless match

  debug = match['sampling_state'] == 'd'
  sampled = debug || match['sampling_state'] == '1'
  extracted_context(match['trace_id'], match['span_id'], sampled, debug, context)
end
extracted_context(trace_id_hex, span_id_hex, sampled, debug, context) click to toggle source
# File lib/opentelemetry/propagator/b3/text_map_extractor.rb, line 77
def extracted_context(trace_id_hex, span_id_hex, sampled, debug, context)
  span_context = Trace::SpanContext.new(
    trace_id: to_trace_id(trace_id_hex),
    span_id: to_span_id(span_id_hex),
    trace_flags: to_trace_flags(sampled),
    remote: true
  )

  span = OpenTelemetry::Trace.non_recording_span(span_context)
  context = B3.context_with_debug(context) if debug
  Trace.context_with_span(span, parent_context: context)
end
to_span_id(hex_id) click to toggle source

Convert an id from a hex encoded string to byte array.

# File lib/opentelemetry/propagator/b3/text_map_extractor.rb, line 110
def to_span_id(hex_id)
  Array(hex_id).pack('H*')
end
to_trace_flags(sampled) click to toggle source
# File lib/opentelemetry/propagator/b3/text_map_extractor.rb, line 90
def to_trace_flags(sampled)
  if sampled
    Trace::TraceFlags::SAMPLED
  else
    Trace::TraceFlags::DEFAULT
  end
end
to_trace_id(hex_id) click to toggle source

Convert an id from a hex encoded string to byte array, optionally left padding to the correct length. Assumes the input id has already been validated to be 16 or 32 characters in length.

# File lib/opentelemetry/propagator/b3/text_map_extractor.rb, line 101
def to_trace_id(hex_id)
  if hex_id.length == 32
    Array(hex_id).pack('H*')
  else
    [0, hex_id].pack('qH*')
  end
end