Class: Datadog::Tracing::Distributed::Propagation
- Inherits:
-
Object
- Object
- Datadog::Tracing::Distributed::Propagation
- Defined in:
- lib/datadog/tracing/distributed/propagation.rb
Overview
Provides extraction and injection of distributed trace data.
Direct Known Subclasses
Contrib::GRPC::Distributed::Propagation, Contrib::HTTP::Distributed::Propagation, Contrib::Sidekiq::Distributed::Propagation
Instance Method Summary collapse
-
#extract(data) ⇒ Object
extract returns TraceDigest containing the distributed trace information.
-
#initialize(propagation_styles:, propagation_style_inject:, propagation_style_extract:, propagation_extract_first:) ⇒ Propagation
constructor
A new instance of Propagation.
-
#inject!(digest, data) ⇒ Boolean?
inject! populates the env with span ID, trace ID and sampling priority.
Constructor Details
#initialize(propagation_styles:, propagation_style_inject:, propagation_style_extract:, propagation_extract_first:) ⇒ Propagation
Returns a new instance of Propagation.
21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/datadog/tracing/distributed/propagation.rb', line 21 def initialize( propagation_styles:, propagation_style_inject:, propagation_style_extract:, propagation_extract_first: ) @propagation_styles = propagation_styles @propagation_extract_first = propagation_extract_first @propagation_style_inject = propagation_style_inject.map { |style| propagation_styles[style] } @propagation_style_extract = propagation_style_extract.map { |style| propagation_styles[style] } 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`.
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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/datadog/tracing/distributed/propagation.rb', line 92 def extract(data) return unless data return if data.empty? extracted_trace_digest = nil @propagation_style_extract.each do |propagator| # First extraction? unless extracted_trace_digest extracted_trace_digest = propagator.extract(data) next end # Return if we are only inspecting the first valid style. next if @propagation_extract_first # Continue parsing styles to find the W3C `tracestate` header, if present. # `tracestate` must always be propagated, as it might contain pass-through data that we don't control. # @see https://www.w3.org/TR/2021/REC-trace-context-1-20211123/#mutating-the-tracestate-field next unless propagator.is_a?(TraceContext) if (tracecontext_digest = propagator.extract(data)) # Only parse if it represent the same trace as the successfully extracted one next unless tracecontext_digest.trace_id == extracted_trace_digest.trace_id parent_id = extracted_trace_digest.span_id = extracted_trace_digest. unless extracted_trace_digest.span_id == tracecontext_digest.span_id # span_id in the tracecontext header takes precedence over the value in all conflicting headers parent_id = tracecontext_digest.span_id if (lp_id = last_datadog_parent_id(data, tracecontext_digest.)) = extracted_trace_digest.&.dup || {} [Tracing::Metadata::Ext::Distributed::TAG_DD_PARENT_ID] = lp_id end end # Preserve the trace state and last datadog span id extracted_trace_digest = extracted_trace_digest.merge( span_id: parent_id, trace_state: tracecontext_digest.trace_state, trace_state_unknown_fields: tracecontext_digest.trace_state_unknown_fields, trace_distributed_tags: ) end rescue => e # TODO: Not to report Telemetry logs for now ::Datadog.logger.error( "Error extracting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}" ) end extracted_trace_digest end |
#inject!(digest, data) ⇒ Boolean?
inject! populates the env with span ID, trace ID and sampling priority
This method will never raise errors. It can propagate partial data, if deemed useful, instead of failing. In case of unrecoverable errors, it will 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. DEV-3.0: Sample trace here instead of when generating digest.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/datadog/tracing/distributed/propagation.rb', line 53 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) if digest.trace_id.nil? ::Datadog.logger.debug('Cannot inject distributed trace data: digest.trace_id is nil.') return nil end result = false # Inject all configured propagation styles @propagation_style_inject.each do |propagator| propagator.inject!(digest, data) result = true rescue => e result = nil ::Datadog.logger.error( "Error injecting distributed trace data. Cause: #{e} Location: #{Array(e.backtrace).first}" ) ::Datadog::Core::Telemetry::Logger.report( e, description: "Error injecting distributed trace data with #{propagator.class.name}" ) end result end |