Skip to content

Commit 297388e

Browse files
committed
strip stale th on the invalid-ot sample path
Signed-off-by: ayush-that <ayush1337@hotmail.com>
1 parent 3b30ff1 commit 297388e

2 files changed

Lines changed: 51 additions & 11 deletions

File tree

sdk/src/trace/samplers/probability.cc

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <string>
1010

1111
#include "opentelemetry/nostd/function_ref.h"
12+
#include "opentelemetry/nostd/shared_ptr.h"
1213
#include "opentelemetry/nostd/string_view.h"
1314
#include "opentelemetry/sdk/common/global_log_handler.h"
1415
#include "opentelemetry/sdk/trace/sampler.h"
@@ -131,6 +132,23 @@ namespace sdk
131132
{
132133
namespace trace
133134
{
135+
namespace
136+
{
137+
// Removes the inherited (now stale) "th" sub-key, keeping the other ot sub-keys.
138+
nostd::shared_ptr<trace_api::TraceState> EraseThreshold(
139+
const nostd::shared_ptr<trace_api::TraceState> &parent_trace_state,
140+
const std::string &ot_value)
141+
{
142+
OtelTraceState ot_state = OtelTraceState::Parse(ot_value);
143+
ot_state.has_threshold = false;
144+
std::string stripped = ot_state.Serialize();
145+
auto trace_state = parent_trace_state->Delete(kOtTraceStateKey);
146+
if (!stripped.empty())
147+
trace_state = trace_state->Set(kOtTraceStateKey, stripped);
148+
return trace_state;
149+
}
150+
} // namespace
151+
134152
ProbabilitySampler::ProbabilitySampler(double ratio)
135153
: description_("ProbabilitySampler{" + std::to_string(ClampProbability(ratio)) + "}"),
136154
threshold_(CalculateThreshold(ClampProbability(ratio)))
@@ -171,18 +189,12 @@ SamplingResult ProbabilitySampler::ShouldSample(
171189

172190
if (drop)
173191
{
174-
OtelTraceState ot_state = OtelTraceState::Parse(ot_value);
175-
ot_state.has_threshold = false;
176-
std::string dropped_ot = ot_state.Serialize();
177-
auto trace_state = parent_trace_state->Delete(kOtTraceStateKey);
178-
if (!dropped_ot.empty())
179-
trace_state = trace_state->Set(kOtTraceStateKey, dropped_ot);
180-
return {Decision::DROP, nullptr, trace_state};
192+
return {Decision::DROP, nullptr, EraseThreshold(parent_trace_state, ot_value)};
181193
}
182194

183195
std::string new_ot_value = SetThresholdSubKey(ot_value, EncodeThreshold(threshold_));
184196
if (!trace_api::TraceState::IsValidValue(new_ot_value))
185-
return {Decision::RECORD_AND_SAMPLE, nullptr, {}};
197+
return {Decision::RECORD_AND_SAMPLE, nullptr, EraseThreshold(parent_trace_state, ot_value)};
186198

187199
if (!has_ot)
188200
{

sdk/test/trace/probability_sampler_test.cc

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,16 +352,44 @@ TEST(ProbabilitySampler, OversizedValueKeepsParentTraceState)
352352
uint8_t span_id_buffer[trace_api::SpanId::kSize] = {1};
353353
trace_api::SpanId span_id{span_id_buffer};
354354

355-
// Appending the th sub-key would exceed the 256 character value limit, so
356-
// the span is sampled but the trace state is left untouched.
355+
// The oversized ot value is re-emitted unchanged because it has no th to erase.
357356
std::string ot_value = "a:" + std::string(253, 'b');
358357
auto trace_state = trace_api::TraceState::FromHeader("ot=" + ot_value);
359358
trace_api::SpanContext context(trace_id, span_id, trace_api::TraceFlags{0}, false, trace_state);
360359

361360
auto sampling_result = SampleWithContext(s1, context, TraceIdWithRandomness(0xffffffffffffff));
362361

363362
ASSERT_EQ(Decision::RECORD_AND_SAMPLE, sampling_result.decision);
364-
ASSERT_EQ(nullptr, sampling_result.trace_state);
363+
ASSERT_NE(nullptr, sampling_result.trace_state);
364+
365+
std::string result_ot;
366+
ASSERT_TRUE(sampling_result.trace_state->Get("ot", result_ot));
367+
ASSERT_EQ(ot_value, result_ot);
368+
}
369+
370+
TEST(ProbabilitySampler, OversizedValueErasesStaleThreshold)
371+
{
372+
// ratio 0.1's 17-char th overflows the 256-char limit, so the stale th is erased.
373+
ProbabilitySampler s1(0.1);
374+
375+
uint8_t trace_id_buffer[trace_api::TraceId::kSize] = {1};
376+
trace_api::TraceId trace_id{trace_id_buffer};
377+
uint8_t span_id_buffer[trace_api::SpanId::kSize] = {1};
378+
trace_api::SpanId span_id{span_id_buffer};
379+
380+
std::string rest = "x:" + std::string(245, 'b');
381+
auto trace_state = trace_api::TraceState::FromHeader("ot=th:8;" + rest);
382+
trace_api::SpanContext context(trace_id, span_id, trace_api::TraceFlags{0}, false, trace_state);
383+
384+
auto sampling_result = SampleWithContext(s1, context, TraceIdWithRandomness(0xffffffffffffff));
385+
386+
ASSERT_EQ(Decision::RECORD_AND_SAMPLE, sampling_result.decision);
387+
ASSERT_NE(nullptr, sampling_result.trace_state);
388+
389+
std::string result_ot;
390+
ASSERT_TRUE(sampling_result.trace_state->Get("ot", result_ot));
391+
ASSERT_EQ(rest, result_ot);
392+
ASSERT_EQ(std::string::npos, result_ot.find("th:"));
365393
}
366394

367395
TEST(ProbabilitySampler, IgnoresParentSampledFlag)

0 commit comments

Comments
 (0)