Module: NewRelic::Agent::Transaction::TraceContext

Includes:
Coerce
Included in:
DistributedTracer
Defined in:
lib/new_relic/agent/transaction/trace_context.rb

Defined Under Namespace

Modules: AccountHelpers

Constant Summary collapse

SUPPORTABILITY_PREFIX =
'Supportability/TraceContext'
CREATE_PREFIX =
"#{SUPPORTABILITY_PREFIX}/Create"
ACCEPT_PREFIX =
"#{SUPPORTABILITY_PREFIX}/Accept"
TRACESTATE_PREFIX =
"#{SUPPORTABILITY_PREFIX}/TraceState"
CREATE_SUCCESS_METRIC =
"#{CREATE_PREFIX}/Success"
CREATE_EXCEPTION_METRIC =
"#{CREATE_PREFIX}/Exception"
ACCEPT_SUCCESS_METRIC =
"#{ACCEPT_PREFIX}/Success"
ACCEPT_EXCEPTION_METRIC =
"#{ACCEPT_PREFIX}/Exception"
IGNORE_MULTIPLE_ACCEPT_METRIC =
"#{ACCEPT_PREFIX}/Ignored/Multiple"
IGNORE_ACCEPT_AFTER_CREATE_METRIC =
"#{ACCEPT_PREFIX}/Ignored/CreateBeforeAccept"
NO_NR_ENTRY_TRACESTATE_METRIC =
"#{TRACESTATE_PREFIX}/NoNrEntry"
INVALID_TRACESTATE_PAYLOAD_METRIC =
"#{TRACESTATE_PREFIX}/InvalidNrEntry"

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Coerce

boolean_int!, float, float!, int, int!, int_or_nil, log_failure, scalar, string, value_or_nil

Instance Attribute Details

#trace_context_header_dataObject



39
40
41
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 39

def trace_context_header_data
  @trace_context_header_data
end

#trace_state_payloadObject (readonly)



40
41
42
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 40

def trace_state_payload
  @trace_state_payload
end

Instance Method Details

#accept_trace_context(header_data) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 128

def accept_trace_context(header_data)
  return if ignore_trace_context?

  @trace_context_header_data = header_data
  transaction.trace_id = header_data.trace_id
  transaction.parent_span_id = header_data.parent_id

  return false unless payload = assign_trace_state_payload

  transaction.distributed_tracer.parent_transaction_id = payload.transaction_id

  unless payload.sampled.nil?
    transaction.sampled = payload.sampled
    transaction.priority = payload.priority if payload.priority
  end
  NewRelic::Agent.increment_metric(ACCEPT_SUCCESS_METRIC)
  true
rescue => e
  NewRelic::Agent.increment_metric(ACCEPT_EXCEPTION_METRIC)
  NewRelic::Agent.logger.warn('Failed to accept trace context payload', e)
  false
end

#assign_trace_state_payloadObject



115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 115

def assign_trace_state_payload
  payload = @trace_context_header_data.trace_state_payload
  unless payload
    NewRelic::Agent.increment_metric(NO_NR_ENTRY_TRACESTATE_METRIC)
    return false
  end
  unless payload.valid?
    NewRelic::Agent.increment_metric(INVALID_TRACESTATE_PAYLOAD_METRIC)
    return false
  end
  @trace_state_payload = payload
end

#create_trace_stateObject



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 80

def create_trace_state
  entry_key = AccountHelpers.trace_state_entry_key.dup
  payload = create_trace_state_payload

  if payload
    entry = NewRelic::Agent::DistributedTracing::TraceContext.create_trace_state_entry( \
      entry_key,
      payload.to_s
    )
  else
    entry = NewRelic::EMPTY_STR
  end

  trace_context_header_data ? trace_context_header_data.trace_state(entry) : entry
end

#create_trace_state_payloadObject



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 96

def create_trace_state_payload
  unless Agent.config[:'distributed_tracing.enabled']
    NewRelic::Agent.logger.warn('Not configured to create WC3 trace context payload')
    return
  end

  span_guid = Agent.config[:'span_events.enabled'] ? transaction.current_segment.guid : nil
  transaction_guid = Agent.config[:'transaction_events.enabled'] ? transaction.guid : nil

  TraceContextPayload.create( \
    parent_account_id: Agent.config[:account_id],
    parent_app_id: Agent.config[:primary_application_id],
    transaction_id: transaction_guid,
    sampled: transaction.sampled?,
    priority: float!(transaction.priority, NewRelic::PRIORITY_PRECISION),
    id: span_guid
  )
end

#ignore_trace_context?Boolean

Returns:

  • (Boolean)


151
152
153
154
155
156
157
158
159
160
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 151

def ignore_trace_context?
  if trace_context_header_data
    NewRelic::Agent.increment_metric(IGNORE_MULTIPLE_ACCEPT_METRIC)
    return true
  elsif trace_context_inserted?
    NewRelic::Agent.increment_metric(IGNORE_ACCEPT_AFTER_CREATE_METRIC)
    return true
  end
  false
end

#insert_trace_context_header(header, format = NewRelic::FORMAT_NON_RACK) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 58

def insert_trace_context_header(header, format = NewRelic::FORMAT_NON_RACK)
  return unless Agent.config[:'distributed_tracing.enabled']

  NewRelic::Agent::DistributedTracing::TraceContext.insert( \
    format: format,
    carrier: header,
    trace_id: transaction.trace_id.rjust(32, '0').downcase,
    parent_id: transaction.current_segment.guid,
    trace_flags: transaction.sampled? ? 0x1 : 0x0,
    trace_state: create_trace_state
  )

  @trace_context_inserted = true

  NewRelic::Agent.increment_metric(CREATE_SUCCESS_METRIC)
  true
rescue Exception => e
  NewRelic::Agent.increment_metric(CREATE_EXCEPTION_METRIC)
  NewRelic::Agent.logger.warn('Failed to create trace context payload', e)
  false
end

#trace_context_inserted?Boolean

Returns:

  • (Boolean)


162
163
164
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 162

def trace_context_inserted?
  @trace_context_inserted ||= false
end

#trace_parent_header_present?(request) ⇒ Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/new_relic/agent/transaction/trace_context.rb', line 42

def trace_parent_header_present?(request)
  request[NewRelic::HTTP_TRACEPARENT_KEY]
end