Skip to content

Commit 787772f

Browse files
Merge pull request #3368 from newrelic/extend-missing-tracestate-header-sampling-to-otel
Extend sampling decision logic to OTel
2 parents a994540 + edd7bff commit 787772f

File tree

4 files changed

+43
-15
lines changed

4 files changed

+43
-15
lines changed

lib/new_relic/agent/agent.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ def init_components
100100
@monotonic_gc_profiler = VM::MonotonicGCProfiler.new
101101
@adaptive_sampler = AdaptiveSampler.new(Agent.config[:sampling_target],
102102
Agent.config[:sampling_target_period_in_seconds])
103+
# TODO: update the configs used here to match new sampler-specific options
104+
# TODO: Consider refactoring to only create the sampler if 'adaptive' is the sampler's setting
105+
@adaptive_sampler_remote_parent_sampled = AdaptiveSampler.new(Agent.config[:sampling_target],
106+
Agent.config[:sampling_target_period_in_seconds])
107+
@adaptive_sampler_remote_parent_not_sampled = AdaptiveSampler.new(Agent.config[:sampling_target],
108+
Agent.config[:sampling_target_period_in_seconds])
103109
@serverless_handler = ServerlessHandler.new
104110
@opentelemetry_bridge = OpenTelemetryBridge.new
105111
end
@@ -178,6 +184,8 @@ module InstanceMethods
178184
attr_reader :transaction_event_recorder
179185
attr_reader :attribute_filter
180186
attr_reader :adaptive_sampler
187+
attr_reader :adaptive_sampler_remote_parent_sampled
188+
attr_reader :adaptive_sampler_remote_parent_not_sampled
181189
attr_reader :serverless_handler
182190

183191
def transaction_event_aggregator

lib/new_relic/agent/opentelemetry/trace/tracer.rb

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ def start_span(name, with_parent: nil, attributes: nil, links: nil, start_timest
1919
return if internal_span_kind_with_invalid_parent?(kind, parent_otel_context)
2020

2121
nr_item = NewRelic::Agent::Tracer.start_transaction_or_segment(name: name, category: :otel)
22+
2223
add_remote_context_to_txn(nr_item, parent_otel_context)
24+
2325
nr_item
2426
else
2527
NewRelic::Agent::Tracer.start_segment(name: name)
@@ -93,18 +95,24 @@ def set_tracestate(distributed_tracer, otel_context)
9395
def set_nr_trace_state(distributed_tracer, otel_context)
9496
distributed_tracer.instance_variable_set(:@trace_state_payload, otel_context.tracestate)
9597
distributed_tracer.parent_transaction_id = distributed_tracer.trace_state_payload.transaction_id
96-
distributed_tracer.determine_sampling_decision(otel_context.tracestate, otel_context.trace_flags)
98+
trace_flags = parse_trace_flags(otel_context.trace_flags)
99+
100+
distributed_tracer.determine_sampling_decision(otel_context.tracestate, trace_flags)
97101
end
98102

99103
def set_otel_trace_state(distributed_tracer, otel_context)
100104
nr_entry = otel_context.tracestate.value(Transaction::TraceContext::AccountHelpers.trace_state_entry_key)
101-
return unless nr_entry
102-
103-
nr_payload = NewRelic::Agent::TraceContextPayload.from_s(nr_entry)
104-
distributed_tracer.instance_variable_set(:@trace_state_payload, nr_payload)
105-
distributed_tracer.parent_transaction_id = distributed_tracer.trace_state_payload.transaction_id
106105
trace_flags = parse_trace_flags(otel_context.trace_flags)
107-
distributed_tracer.determine_sampling_decision(nr_payload, trace_flags)
106+
107+
if nr_entry
108+
nr_payload = NewRelic::Agent::TraceContextPayload.from_s(nr_entry)
109+
110+
distributed_tracer.instance_variable_set(:@trace_state_payload, nr_payload)
111+
distributed_tracer.parent_transaction_id = distributed_tracer.trace_state_payload.transaction_id
112+
distributed_tracer.determine_sampling_decision(nr_payload, trace_flags)
113+
else
114+
distributed_tracer.determine_sampling_decision(NewRelic::Agent::TraceContextPayload::INVALID, trace_flags)
115+
end
108116
end
109117

110118
def parse_trace_flags(trace_flags)

lib/new_relic/agent/transaction/trace_context.rb

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,32 +157,42 @@ def determine_sampling_decision(payload, trace_flags)
157157
set_priority_and_sampled(
158158
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_sampled'],
159159
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_sampled.trace_id_ratio_based.ratio'],
160-
payload
160+
payload,
161+
trace_flags
161162
)
162163
elsif trace_flags == '00'
163164
set_priority_and_sampled(
164165
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_not_sampled'],
165166
NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_not_sampled.trace_id_ratio_based.ratio'],
166-
payload
167+
payload,
168+
trace_flags
167169
)
168170
else
169-
use_nr_tracestate_sampled(payload)
171+
use_nr_tracestate_sampled(payload, trace_flags)
170172
end
171173
rescue
172-
use_nr_tracestate_sampled(payload)
174+
use_nr_tracestate_sampled(payload, trace_flags)
173175
end
174176

175-
def use_nr_tracestate_sampled(payload)
176-
unless payload.sampled.nil?
177+
def use_nr_tracestate_sampled(payload, trace_flags)
178+
if payload.sampled.nil?
179+
if trace_flags == '01'
180+
transaction.sampled = NewRelic::Agent.instance.adaptive_sampler_remote_parent_sampled.sampled?
181+
elsif trace_flags == '00'
182+
transaction.sampled = NewRelic::Agent.instance.adaptive_sampler_remote_parent_not_sampled.sampled?
183+
end
184+
185+
transaction.priority = transaction.default_priority
186+
else
177187
transaction.sampled = payload.sampled
178188
transaction.priority = payload.priority if payload.priority
179189
end
180190
end
181191

182-
def set_priority_and_sampled(sampler, ratio, payload)
192+
def set_priority_and_sampled(sampler, ratio, payload, trace_flags = nil)
183193
case sampler
184194
when 'adaptive'
185-
use_nr_tracestate_sampled(payload)
195+
use_nr_tracestate_sampled(payload, trace_flags)
186196
when 'always_on'
187197
transaction.sampled = true
188198
transaction.priority = 2.0

test/new_relic/agent/distributed_tracing/trace_context_cross_agent_test.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ def self.focus_tests
4343

4444
define_method("test_#{test_case['test_name']}") do
4545
NewRelic::Agent.instance.adaptive_sampler.stubs(:sampled?).returns(test_case['force_adaptive_sampled_true'])
46+
NewRelic::Agent.instance.adaptive_sampler_remote_parent_sampled.stubs(:sampled?).returns(test_case['force_adaptive_sampled_true'])
47+
NewRelic::Agent.instance.adaptive_sampler_remote_parent_not_sampled.stubs(:sampled?).returns(test_case['force_adaptive_sampled_true'])
4648

4749
config = {
4850
:'distributed_tracing.enabled' => true,

0 commit comments

Comments
 (0)