Skip to content

Commit 42e557f

Browse files
committed
fix(sdk): correct ownership conversion for parent-based samplers from env vars
ParentBasedSamplerFactory::Create() expects shared_ptr but sampler factories return unique_ptr. Convert ownership correctly using release() and shared_ptr constructor for all parent-based sampler variants. Also adds test coverage for invalid ratio validation in parentbased_traceidratio and fixes trailing whitespace formatting.
1 parent bc2bc5a commit 42e557f

2 files changed

Lines changed: 59 additions & 66 deletions

File tree

‎sdk/src/trace/sampler_env.cc‎

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@ namespace trace
2323
namespace sampler_env
2424
{
2525

26-
static constexpr const char *kTracesSamplerEnv = "OTEL_TRACES_SAMPLER";
27-
static constexpr const char *kTracesSamplerArgEnv = "OTEL_TRACES_SAMPLER_ARG";
28-
static constexpr double kDefaultTraceIdRatio = 1.0;
26+
static constexpr const char *kTracesSamplerEnv = "OTEL_TRACES_SAMPLER";
27+
static constexpr const char *kTracesSamplerArgEnv = "OTEL_TRACES_SAMPLER_ARG";
28+
static constexpr double kDefaultTraceIdRatio = 1.0;
2929

3030
std::unique_ptr<Sampler> GetSamplerFromEnv()
3131
{
3232
std::string sampler_name;
33-
bool has_sampler_env = opentelemetry::sdk::common::GetStringEnvironmentVariable(kTracesSamplerEnv, sampler_name);
33+
bool has_sampler_env =
34+
opentelemetry::sdk::common::GetStringEnvironmentVariable(kTracesSamplerEnv, sampler_name);
3435

3536
if (!has_sampler_env || sampler_name.empty())
3637
{
@@ -39,7 +40,8 @@ std::unique_ptr<Sampler> GetSamplerFromEnv()
3940
}
4041

4142
float ratio_arg = kDefaultTraceIdRatio;
42-
bool has_ratio_env = opentelemetry::sdk::common::GetFloatEnvironmentVariable(kTracesSamplerArgEnv, ratio_arg);
43+
bool has_ratio_env =
44+
opentelemetry::sdk::common::GetFloatEnvironmentVariable(kTracesSamplerArgEnv, ratio_arg);
4345

4446
// For traceidratio and parentbased_traceidratio, default to 1.0 if arg is unset
4547
if (!has_ratio_env)
@@ -61,8 +63,9 @@ std::unique_ptr<Sampler> GetSamplerFromEnv()
6163
// Validate ratio
6264
if (std::isnan(ratio_arg) || std::isinf(ratio_arg) || ratio_arg < 0.0f || ratio_arg > 1.0f)
6365
{
64-
OTEL_INTERNAL_LOG_WARN("Environment variable <" << kTracesSamplerArgEnv << "> has invalid value <"
65-
<< ratio_arg << "> for traceidratio sampler, "
66+
OTEL_INTERNAL_LOG_WARN("Environment variable <" << kTracesSamplerArgEnv
67+
<< "> has invalid value <" << ratio_arg
68+
<< "> for traceidratio sampler, "
6669
<< "falling back to AlwaysOnSampler");
6770
return AlwaysOnSamplerFactory::Create();
6871
}
@@ -73,29 +76,31 @@ std::unique_ptr<Sampler> GetSamplerFromEnv()
7376
// Validate ratio
7477
if (std::isnan(ratio_arg) || std::isinf(ratio_arg) || ratio_arg < 0.0f || ratio_arg > 1.0f)
7578
{
76-
OTEL_INTERNAL_LOG_WARN("Environment variable <" << kTracesSamplerArgEnv << "> has invalid value <"
77-
<< ratio_arg << "> for parentbased_traceidratio sampler, "
79+
OTEL_INTERNAL_LOG_WARN("Environment variable <" << kTracesSamplerArgEnv
80+
<< "> has invalid value <" << ratio_arg
81+
<< "> for parentbased_traceidratio sampler, "
7882
<< "falling back to AlwaysOnSampler");
7983
return AlwaysOnSamplerFactory::Create();
8084
}
8185
auto root_sampler = TraceIdRatioBasedSamplerFactory::Create(ratio_arg);
82-
return ParentBasedSamplerFactory::Create(root_sampler);
86+
return ParentBasedSamplerFactory::Create(std::shared_ptr<Sampler>(root_sampler.release()));
8387
}
8488
else if (sampler_name == "parentbased_always_on")
8589
{
8690
auto root_sampler = AlwaysOnSamplerFactory::Create();
87-
return ParentBasedSamplerFactory::Create(root_sampler);
91+
return ParentBasedSamplerFactory::Create(std::shared_ptr<Sampler>(root_sampler.release()));
8892
}
8993
else if (sampler_name == "parentbased_always_off")
9094
{
9195
auto root_sampler = AlwaysOffSamplerFactory::Create();
92-
return ParentBasedSamplerFactory::Create(root_sampler);
96+
return ParentBasedSamplerFactory::Create(std::shared_ptr<Sampler>(root_sampler.release()));
9397
}
9498
else
9599
{
96100
// Unknown sampler name
97101
OTEL_INTERNAL_LOG_WARN("Environment variable <" << kTracesSamplerEnv << "> has unknown value <"
98-
<< sampler_name << ">, falling back to AlwaysOnSampler");
102+
<< sampler_name
103+
<< ">, falling back to AlwaysOnSampler");
99104
return AlwaysOnSamplerFactory::Create();
100105
}
101106
}

‎sdk/test/trace/sampler_env_test.cc‎

Lines changed: 41 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ using opentelemetry::sdk::common::setenv;
2020
using opentelemetry::sdk::common::unsetenv;
2121
#endif
2222

23-
using opentelemetry::sdk::trace::sampler_env::GetSamplerFromEnv;
2423
using opentelemetry::sdk::trace::AlwaysOffSamplerFactory;
2524
using opentelemetry::sdk::trace::AlwaysOnSamplerFactory;
2625
using opentelemetry::sdk::trace::ParentBasedSamplerFactory;
2726
using opentelemetry::sdk::trace::TraceIdRatioBasedSamplerFactory;
27+
using opentelemetry::sdk::trace::sampler_env::GetSamplerFromEnv;
2828

2929
#ifndef NO_GETENV
3030

@@ -71,52 +71,58 @@ TEST_F(SamplerEnvTest, TraceIdRatioSamplerWithValidRatio)
7171
setenv("OTEL_TRACES_SAMPLER", "traceidratio", 1);
7272
setenv("OTEL_TRACES_SAMPLER_ARG", "0.5", 1);
7373
auto sampler = GetSamplerFromEnv();
74-
EXPECT_EQ(sampler->GetDescription(), TraceIdRatioBasedSamplerFactory::Create(0.5)->GetDescription());
74+
EXPECT_EQ(sampler->GetDescription(),
75+
TraceIdRatioBasedSamplerFactory::Create(0.5)->GetDescription());
7576
}
7677

7778
TEST_F(SamplerEnvTest, TraceIdRatioSamplerWithDefaultRatio)
7879
{
7980
setenv("OTEL_TRACES_SAMPLER", "traceidratio", 1);
8081
// OTEL_TRACES_SAMPLER_ARG not set, should default to 1.0
8182
auto sampler = GetSamplerFromEnv();
82-
EXPECT_EQ(sampler->GetDescription(), TraceIdRatioBasedSamplerFactory::Create(1.0)->GetDescription());
83+
EXPECT_EQ(sampler->GetDescription(),
84+
TraceIdRatioBasedSamplerFactory::Create(1.0)->GetDescription());
8385
}
8486

8587
TEST_F(SamplerEnvTest, ParentBasedTraceIdRatioSamplerWithValidRatio)
8688
{
8789
setenv("OTEL_TRACES_SAMPLER", "parentbased_traceidratio", 1);
8890
setenv("OTEL_TRACES_SAMPLER_ARG", "0.5", 1);
89-
auto sampler = GetSamplerFromEnv();
90-
auto root_sampler = TraceIdRatioBasedSamplerFactory::Create(0.5);
91-
auto expected_sampler = ParentBasedSamplerFactory::Create(root_sampler);
91+
auto sampler = GetSamplerFromEnv();
92+
auto root_sampler = TraceIdRatioBasedSamplerFactory::Create(0.5);
93+
auto expected_sampler = ParentBasedSamplerFactory::Create(
94+
std::shared_ptr<opentelemetry::sdk::trace::Sampler>(root_sampler.release()));
9295
EXPECT_EQ(sampler->GetDescription(), expected_sampler->GetDescription());
9396
}
9497

9598
TEST_F(SamplerEnvTest, ParentBasedTraceIdRatioSamplerWithDefaultRatio)
9699
{
97100
setenv("OTEL_TRACES_SAMPLER", "parentbased_traceidratio", 1);
98101
// OTEL_TRACES_SAMPLER_ARG not set, should default to 1.0
99-
auto sampler = GetSamplerFromEnv();
100-
auto root_sampler = TraceIdRatioBasedSamplerFactory::Create(1.0);
101-
auto expected_sampler = ParentBasedSamplerFactory::Create(root_sampler);
102+
auto sampler = GetSamplerFromEnv();
103+
auto root_sampler = TraceIdRatioBasedSamplerFactory::Create(1.0);
104+
auto expected_sampler = ParentBasedSamplerFactory::Create(
105+
std::shared_ptr<opentelemetry::sdk::trace::Sampler>(root_sampler.release()));
102106
EXPECT_EQ(sampler->GetDescription(), expected_sampler->GetDescription());
103107
}
104108

105109
TEST_F(SamplerEnvTest, ParentBasedAlwaysOnSampler)
106110
{
107111
setenv("OTEL_TRACES_SAMPLER", "parentbased_always_on", 1);
108-
auto sampler = GetSamplerFromEnv();
109-
auto root_sampler = AlwaysOnSamplerFactory::Create();
110-
auto expected_sampler = ParentBasedSamplerFactory::Create(root_sampler);
112+
auto sampler = GetSamplerFromEnv();
113+
auto root_sampler = AlwaysOnSamplerFactory::Create();
114+
auto expected_sampler = ParentBasedSamplerFactory::Create(
115+
std::shared_ptr<opentelemetry::sdk::trace::Sampler>(root_sampler.release()));
111116
EXPECT_EQ(sampler->GetDescription(), expected_sampler->GetDescription());
112117
}
113118

114119
TEST_F(SamplerEnvTest, ParentBasedAlwaysOffSampler)
115120
{
116121
setenv("OTEL_TRACES_SAMPLER", "parentbased_always_off", 1);
117-
auto sampler = GetSamplerFromEnv();
118-
auto root_sampler = AlwaysOffSamplerFactory::Create();
119-
auto expected_sampler = ParentBasedSamplerFactory::Create(root_sampler);
122+
auto sampler = GetSamplerFromEnv();
123+
auto root_sampler = AlwaysOffSamplerFactory::Create();
124+
auto expected_sampler = ParentBasedSamplerFactory::Create(
125+
std::shared_ptr<opentelemetry::sdk::trace::Sampler>(root_sampler.release()));
120126
EXPECT_EQ(sampler->GetDescription(), expected_sampler->GetDescription());
121127
}
122128

@@ -173,71 +179,53 @@ TEST_F(SamplerEnvTest, ParentBasedTraceIdRatioWithInvalidRatioReturnsAlwaysOnSam
173179
EXPECT_EQ(sampler->GetDescription(), AlwaysOnSamplerFactory::Create()->GetDescription());
174180
}
175181

176-
TEST_F(SamplerEnvTest, EmptySamplerNameReturnsAlwaysOnSampler)
182+
TEST_F(SamplerEnvTest, ParentBasedTraceIdRatioWithNegativeRatioReturnsAlwaysOnSampler)
177183
{
178-
setenv("OTEL_TRACES_SAMPLER", "", 1);
184+
setenv("OTEL_TRACES_SAMPLER", "parentbased_traceidratio", 1);
185+
setenv("OTEL_TRACES_SAMPLER_ARG", "-0.5", 1);
179186
auto sampler = GetSamplerFromEnv();
180-
// Empty string should be treated as unset
187+
// Should fall back to AlwaysOnSampler for invalid ratio
181188
EXPECT_EQ(sampler->GetDescription(), AlwaysOnSamplerFactory::Create()->GetDescription());
182189
}
183190

184-
TEST_F(SamplerEnvTest, CaseInsensitiveSamplerNames)
191+
TEST_F(SamplerEnvTest, ParentBasedTraceIdRatioWithNaNReturnsAlwaysOnSampler)
185192
{
186-
setenv("OTEL_TRACES_SAMPLER", "ALWAYS_ON", 1);
193+
setenv("OTEL_TRACES_SAMPLER", "parentbased_traceidratio", 1);
194+
setenv("OTEL_TRACES_SAMPLER_ARG", "nan", 1);
187195
auto sampler = GetSamplerFromEnv();
188-
// Should fall back to AlwaysOnSampler for case-sensitive mismatch
196+
// Should fall back to AlwaysOnSampler for invalid ratio
189197
EXPECT_EQ(sampler->GetDescription(), AlwaysOnSamplerFactory::Create()->GetDescription());
190198
}
191199

192-
TEST_F(SamplerEnvTest, ParentBasedSamplerWithSampledRemoteParent)
200+
TEST_F(SamplerEnvTest, EmptySamplerNameReturnsAlwaysOnSampler)
193201
{
194-
setenv("OTEL_TRACES_SAMPLER", "parentbased_always_on", 1);
202+
setenv("OTEL_TRACES_SAMPLER", "", 1);
195203
auto sampler = GetSamplerFromEnv();
196-
auto root_sampler = AlwaysOnSamplerFactory::Create();
197-
auto expected_sampler = ParentBasedSamplerFactory::Create(root_sampler);
198-
EXPECT_EQ(sampler->GetDescription(), expected_sampler->GetDescription());
199-
200-
// Test that parent-based sampler respects parent decision
201-
auto context = opentelemetry::trace::SpanContext::GetInvalid();
202-
auto parent_context = opentelemetry::trace::SpanContext(context,
203-
opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kSampled});
204-
205-
auto sampling_result = sampler->ShouldSample(parent_context, opentelemetry::trace::TraceId{},
206-
opentelemetry::trace::SpanKind::kInternal);
207-
EXPECT_EQ(sampling_result.decision, opentelemetry::trace::SamplingResult::Decision::DROP);
204+
// Empty string should be treated as unset
205+
EXPECT_EQ(sampler->GetDescription(), AlwaysOnSamplerFactory::Create()->GetDescription());
208206
}
209207

210-
TEST_F(SamplerEnvTest, ParentBasedSamplerWithUnsampledRemoteParent)
208+
TEST_F(SamplerEnvTest, CaseInsensitiveSamplerNames)
211209
{
212-
setenv("OTEL_TRACES_SAMPLER", "parentbased_always_on", 1);
210+
setenv("OTEL_TRACES_SAMPLER", "ALWAYS_ON", 1);
213211
auto sampler = GetSamplerFromEnv();
214-
auto root_sampler = AlwaysOnSamplerFactory::Create();
215-
auto expected_sampler = ParentBasedSamplerFactory::Create(root_sampler);
216-
EXPECT_EQ(sampler->GetDescription(), expected_sampler->GetDescription());
217-
218-
// Test that parent-based sampler respects parent decision
219-
auto context = opentelemetry::trace::SpanContext::GetInvalid();
220-
auto parent_context = opentelemetry::trace::SpanContext(context,
221-
opentelemetry::trace::TraceFlags{});
222-
223-
auto sampling_result = sampler->ShouldSample(parent_context, opentelemetry::trace::TraceId{},
224-
opentelemetry::trace::SpanKind::kInternal);
225-
EXPECT_EQ(sampling_result.decision, opentelemetry::trace::SamplingResult::Decision::RECORD_AND_SAMPLE);
212+
// Should fall back to AlwaysOnSampler for case-sensitive mismatch
213+
EXPECT_EQ(sampler->GetDescription(), AlwaysOnSamplerFactory::Create()->GetDescription());
226214
}
227215

228216
TEST_F(SamplerEnvTest, ExplicitSamplerOverridesEnvironmentVariables)
229217
{
230218
setenv("OTEL_TRACES_SAMPLER", "always_off", 1);
231219
setenv("OTEL_TRACES_SAMPLER_ARG", "0.5", 1);
232-
220+
233221
// Create a sampler directly - this should override environment variables
234222
auto explicit_sampler = AlwaysOnSamplerFactory::Create();
235-
auto description = explicit_sampler->GetDescription();
236-
223+
auto description = explicit_sampler->GetDescription();
224+
237225
// Environment variable should still return AlwaysOffSampler when called
238226
auto env_sampler = GetSamplerFromEnv();
239227
EXPECT_EQ(env_sampler->GetDescription(), AlwaysOffSamplerFactory::Create()->GetDescription());
240-
228+
241229
// But explicit sampler should be AlwaysOnSampler
242230
EXPECT_EQ(description, AlwaysOnSamplerFactory::Create()->GetDescription());
243231
}

0 commit comments

Comments
 (0)