Method: NewRelic::Agent::DistributedTracing#accept_distributed_trace_headers

Defined in:
lib/new_relic/agent/distributed_tracing.rb

#accept_distributed_trace_headers(headers, transport_type = NewRelic::HTTP) ⇒ Transaction

Accepts distributed tracing headers from any source that has been packaged as a Ruby Hash, thereby allowing the user to manually inject distributed tracing headers. It is optimized to process HTTP_TRACEPARENT, HTTP_TRACESTATE, and HTTP_NEWRELIC as the given Hash keys. which is the most common scenario from Rack middleware in most Ruby applications. However, the Hash keys are case-insensitive and the “HTTP_” prefixes may also be omitted.

Calling this method is not necessary in a typical HTTP trace as distributed tracing is already handled by the agent.

When used, invoke this method as early as possible in a transaction’s life-cycle as calling after the headers are already created will have no effect.

This method accepts both W3C trace context and New Relic distributed tracing headers. When both are present, only the W3C headers are utilized. When W3C trace context headers are present, New Relic headers are ignored regardless if W3C trace context headers are valid and parsable.

Parameters:

  • headers (Hash)

    Incoming distributed trace headers as a Ruby Hash object. Hash keys are expected to be one of TRACEPARENT, TRACESTATE, NEWRELIC and are case-insensitive, with or without “HTTP_” prefixes.

    either as a JSON string or as a header-friendly string returned from NewRelic::Agent::DistributedTracePayload#http_safe

  • transport_type (String) (defaults to: NewRelic::HTTP)

    May be one of: HTTP, HTTPS, Kafka, JMS, IronMQ, AMQP, Queue, Other. Values are case sensitive. All other values result in Unknown

Returns:

[View source]

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
# File 'lib/new_relic/agent/distributed_tracing.rb', line 98

def accept_distributed_trace_headers(headers, transport_type = NewRelic::HTTP)
  record_api_supportability_metric(:accept_distributed_trace_headers)

  unless Agent.config[:'distributed_tracing.enabled']
    NewRelic::Agent.logger.debug('Not configured to accept distributed trace headers')
    return nil
  end

  return unless valid_api_argument_class?(headers, 'headers', Hash)
  return unless valid_api_argument_class?(transport_type, 'transport_type', String)

  return unless transaction = Transaction.tl_current

  # assume we have Rack conforming keys when transport_type is HTTP(S)
  # otherwise, fish for key/value pairs regardless of prefix and case-sensitivity.
  hdr = if transport_type.start_with?(NewRelic::HTTP)
    headers
  else
    # start with the most common case first
    hdr = {
      NewRelic::HTTP_TRACEPARENT_KEY => headers[NewRelic::TRACEPARENT_KEY],
      NewRelic::HTTP_TRACESTATE_KEY => headers[NewRelic::TRACESTATE_KEY],
      NewRelic::HTTP_NEWRELIC_KEY => headers[NewRelic::NEWRELIC_KEY]
    }

    # when not found, search for any casing for trace context headers, ignoring potential prefixes
    hdr[NewRelic::HTTP_TRACEPARENT_KEY] ||= variant_key_value(headers, NewRelic::TRACEPARENT_KEY)
    hdr[NewRelic::HTTP_TRACESTATE_KEY] ||= variant_key_value(headers, NewRelic::TRACESTATE_KEY)
    hdr[NewRelic::HTTP_NEWRELIC_KEY] ||= variant_key_value(headers, NewRelic::CANDIDATE_NEWRELIC_KEYS)
    hdr
  end

  transaction.distributed_tracer.accept_incoming_request(hdr, transport_type)
  transaction
rescue => e
  NewRelic::Agent.logger.error('error during accept_distributed_trace_headers', e)
  nil
end