Class: Datadog::Tracing::Distributed::Propagation

Inherits:
Object
  • Object
show all
Defined in:
lib/datadog/tracing/distributed/propagation.rb

Overview

Provides extraction and injection of distributed trace data.

Instance Method Summary collapse

Constructor Details

#initialize(propagation_styles:) ⇒ Propagation

DEV: This class should receive the value for DEV: ‘Datadog.configuration.tracing.distributed_tracing.propagation_inject_style` DEV: at initialization time, instead of constantly reading global values. DEV: This means this class should be reconfigured on `Datadog.configure` calls, thus DEV: singleton instances should not used as they will become stale.

Parameters:

  • propagation_styles (Hash<String,Object>)


19
20
21
# File 'lib/datadog/tracing/distributed/propagation.rb', line 19

def initialize(propagation_styles:)
  @propagation_styles = propagation_styles
end

Instance Method Details

#extract(data) ⇒ Object

extract returns TraceDigest containing the distributed trace information. sampling priority defined in data.

This method will never raise errors, but instead log them to ‘Datadog.logger`.

Parameters:

  • data (Hash)


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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/datadog/tracing/distributed/propagation.rb', line 74

def extract(data)
  trace_digest = nil
  dd_trace_digest = nil

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

    begin
      extracted_trace_digest = propagator.extract(data)
    rescue => e
      ::Datadog.logger.error(
        'Error extracting distributed trace data. ' \
      "Cause: #{e} Location: #{Array(e.backtrace).first}"
      )
    end

    # Skip if no valid data was found
    next if extracted_trace_digest.nil?

    # Keep track of the Datadog extracted digest, we want to return it if we have it.
    if extracted_trace_digest && style == Tracing::Configuration::Ext::Distributed::PROPAGATION_STYLE_DATADOG
      dd_trace_digest = extracted_trace_digest
    end

    # No previously extracted trace data, use the one we just extracted
    if trace_digest.nil?
      trace_digest = extracted_trace_digest
    else
      unless trace_digest.trace_id == extracted_trace_digest.trace_id \
            && trace_digest.span_id == extracted_trace_digest.span_id
        # We have two mismatched propagation contexts
        ::Datadog.logger.debug do
          'Cannot extract distributed trace data: extracted styles differ, ' \
          "#{trace_digest.trace_id} != #{extracted_trace_digest.trace_id} && " \
          "#{trace_digest.span_id} != #{extracted_trace_digest.span_id}"
        end

        # It's safer to create a new context than to attach ourselves to the wrong context
        return TraceDigest.new # Early return from the whole method
      end
    end
  end

  # Return the extracted trace digest if we found one or else a new empty digest.
  # Always return the Datadog trace digest if one exists since it has more
  # information than the B3 digest, e.g. origin, priority sampling values.
  dd_trace_digest || trace_digest || nil
end

#inject!(digest, data) ⇒ Boolean?

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

This method will never raise errors, but instead log them to ‘Datadog.logger`.

DEV-2.0: inject! should work without arguments, injecting the active_trace’s digest DEV-2.0: and returning a new Hash with the injected data. DEV-2.0: inject! should also accept either a ‘trace` or a `digest`, as a `trace` DEV-2.0: argument is the common use case, but also allows us to set error tags in the `trace` DEV-2.0: if needed. DEV-2.0: Ideally, we’d have a separate stream to report tracer errors and never DEV-2.0: touch the active span.

Parameters:

Returns:

  • (Boolean)

    ‘true` if injected successfully, `false` if no propagation style is configured

  • (nil)

    in case of error, see ‘Datadog.logger` output for details.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/datadog/tracing/distributed/propagation.rb', line 39

def inject!(digest, data)
  if digest.nil?
    ::Datadog.logger.debug('Cannot inject distributed trace data: digest is nil.')
    return nil
  end

  digest = digest.to_digest if digest.respond_to?(:to_digest)

  result = false

  # Inject all configured propagation styles
  ::Datadog.configuration.tracing.distributed_tracing.propagation_inject_style.each do |style|
    propagator = @propagation_styles[style]
    begin
      if propagator
        propagator.inject!(digest, data)
        result = true
      end
    rescue => e
      result = nil
      ::Datadog.logger.error(
        "Error injecting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}"
      )
    end
  end

  result
end