module Datadog::HTTPPropagator

HTTPPropagator helps extracting and injecting HTTP headers.

Constants

PROPAGATION_STYLES

Public Class Methods

extract(env) click to toggle source

extract returns a context containing the span ID, trace ID and sampling priority defined in env.

# File lib/ddtrace/propagation/http_propagator.rb, line 43
def self.extract(env)
  context = nil
  dd_context = nil

  ::Datadog.configuration.distributed_tracing.propagation_extract_style.each do |style|
    propagator = PROPAGATION_STYLES[style]
    next if propagator.nil?

    # Extract context
    # DEV: `propagator.extract` will return `nil`, where `HTTPPropagator#extract` will not
    begin
      extracted_context = propagator.extract(env)
    rescue => e
      Datadog.logger.error(
        'Error extracting propagated context from the environment. ' \
        "Cause: #{e} Location: #{Array(e.backtrace).first}"
      )
    end

    # Skip this style if no valid headers were found
    next if extracted_context.nil?

    # Keep track of the Datadog extract context, we want to return
    #   this one if we have one
    dd_context = extracted_context if extracted_context && style == PROPAGATION_STYLE_DATADOG

    # No previously extracted context, use the one we just extracted
    if context.nil?
      context = extracted_context
    else
      unless context.trace_id == extracted_context.trace_id && context.span_id == extracted_context.span_id
        # Return an empty/new context if we have a mismatch in values extracted
        msg = "#{context.trace_id} != #{extracted_context.trace_id} && " \
              "#{context.span_id} != #{extracted_context.span_id}"
        ::Datadog.logger.debug("Cannot extract context from HTTP: extracted contexts differ, #{msg}".freeze)
        # DEV: This will return from `self.extract` not this `each` block
        return ::Datadog::Context.new
      end
    end
  end

  # Return the extracted context if we found one or else a new empty context
  # Always return the Datadog context if one exists since it has more
  #   information than the B3 headers e.g. origin, expanded priority
  #   sampling values, etc
  dd_context || context || ::Datadog::Context.new
end
inject!(context, env) click to toggle source

inject! popolates the env with span ID, trace ID and sampling priority

# File lib/ddtrace/propagation/http_propagator.rb, line 20
def self.inject!(context, env)
  # Prevent propagation from being attempted if context provided is nil.
  if context.nil?
    ::Datadog.logger.debug('Cannot inject context into env to propagate over HTTP: context is nil.'.freeze)
    return
  end

  # Inject all configured propagation styles
  ::Datadog.configuration.distributed_tracing.propagation_inject_style.each do |style|
    propagator = PROPAGATION_STYLES[style]
    begin
      propagator.inject!(context, env) unless propagator.nil?
    rescue => e
      Datadog.logger.error(
        'Error injecting propagated context into the environment. ' \
        "Cause: #{e} Location: #{Array(e.backtrace).first}"
      )
    end
  end
end