Current section

Files

Jump to
new_relic_agent lib new_relic distributed_trace w3c_trace_context.ex
Raw

lib/new_relic/distributed_trace/w3c_trace_context.ex

defmodule NewRelic.DistributedTrace.W3CTraceContext do
@moduledoc false
alias NewRelic.Harvest.Collector.AgentRun
alias NewRelic.DistributedTrace.Context
alias __MODULE__.{TraceParent, TraceState}
@w3c_traceparent "traceparent"
@w3c_tracestate "tracestate"
def extract(headers) do
with traceparent_header <- Map.get(headers, @w3c_traceparent),
tracestate_header <- Map.get(headers, @w3c_tracestate),
%TraceParent{} = traceparent <- TraceParent.decode(traceparent_header),
%TraceState{} = tracestate <- TraceState.decode(tracestate_header) do
case TraceState.restrict_access(tracestate) do
{newrelic, others} ->
NewRelic.report_metric(:supportability, [:trace_context, :accept, :success])
%Context{
source:
{:w3c,
%{
tracestate: :new_relic,
sampled: traceparent.flags.sampled,
others: others,
span_id: newrelic.span_id,
tracing_vendors: Enum.map(others, & &1.key)
}},
type: newrelic.parent_type,
account_id: newrelic.account_id,
app_id: newrelic.app_id,
parent_id: newrelic.transaction_id,
span_guid: traceparent.parent_id,
trace_id: traceparent.trace_id,
trust_key: newrelic.trusted_account_key,
priority: newrelic.priority,
sampled: newrelic.sampled,
timestamp: newrelic.timestamp
}
others ->
NewRelic.report_metric(:supportability, [:trace_context, :accept, :success])
NewRelic.report_metric(:supportability, [:trace_context, :tracestate, :non_new_relic])
%Context{
source:
{:w3c,
%{
tracestate: :non_new_relic,
sampled: traceparent.flags.sampled,
others: others,
tracing_vendors: Enum.map(others, & &1.key)
}},
parent_id: traceparent.parent_id,
span_guid: traceparent.parent_id,
trace_id: traceparent.trace_id,
trust_key: AgentRun.trusted_account_key()
}
end
else
_ ->
NewRelic.report_metric(:supportability, [:trace_context, :accept, :exception])
:bad_trace_context
end
end
def generate(%{source: source} = context) do
{others, traceparent_sampled} =
case source do
{:w3c, %{others: others, sampled: sampled}} -> {others, sampled}
_ -> {[], context.sampled}
end
traceparent =
TraceParent.encode(%TraceParent{
trace_id: context.trace_id,
parent_id: context.span_guid,
flags: %{sampled: traceparent_sampled}
})
tracestate =
TraceState.encode(%TraceState{
members: [
%{
key: :new_relic,
value: %TraceState.NewRelicState{
trusted_account_key: context.trust_key,
parent_type: context.type,
account_id: context.account_id,
app_id: context.app_id,
span_id: context.span_guid,
transaction_id: context.parent_id,
sampled: context.sampled,
priority: context.priority,
timestamp: context.timestamp
}
}
| others
]
})
{traceparent, tracestate}
end
end