Skip to content

Commit 51d2efb

Browse files
feat(traceloop-sdk): add sampling_rate parameter to control trace volume
Add simplified sampling_rate parameter to Traceloop.init() for easy trace sampling configuration without manually creating sampler objects. Closes #2109
1 parent e66894f commit 51d2efb

File tree

2 files changed

+106
-1
lines changed

2 files changed

+106
-1
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import pytest
2+
from opentelemetry.sdk.trace.sampling import TraceIdRatioBased
3+
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter
4+
from traceloop.sdk import Traceloop
5+
from traceloop.sdk.tracing.tracing import TracerWrapper
6+
class TestSamplingRate:
7+
def test_init_with_sampling_rate(self):
8+
if hasattr(TracerWrapper, "instance"):
9+
_trace_wrapper_instance = TracerWrapper.instance
10+
del TracerWrapper.instance
11+
try:
12+
exporter = InMemorySpanExporter()
13+
client = Traceloop.init(
14+
app_name="test-sampling-rate",
15+
sampling_rate=0.5,
16+
exporter=exporter,
17+
disable_batch=True
18+
)
19+
assert client is None
20+
assert hasattr(TracerWrapper, "instance")
21+
assert TracerWrapper.instance is not None
22+
finally:
23+
if '_trace_wrapper_instance' in locals():
24+
TracerWrapper.instance = _trace_wrapper_instance
25+
def test_sampling_rate_validation(self):
26+
if hasattr(TracerWrapper, "instance"):
27+
_trace_wrapper_instance = TracerWrapper.instance
28+
del TracerWrapper.instance
29+
try:
30+
exporter = InMemorySpanExporter()
31+
with pytest.raises(ValueError, match="sampling_rate must be between 0.0 and 1.0"):
32+
Traceloop.init(
33+
app_name="test-invalid-sampling-rate",
34+
sampling_rate=1.5,
35+
exporter=exporter,
36+
disable_batch=True
37+
)
38+
with pytest.raises(ValueError, match="sampling_rate must be between 0.0 and 1.0"):
39+
Traceloop.init(
40+
app_name="test-invalid-sampling-rate",
41+
sampling_rate=-0.1,
42+
exporter=exporter,
43+
disable_batch=True
44+
)
45+
finally:
46+
if '_trace_wrapper_instance' in locals():
47+
TracerWrapper.instance = _trace_wrapper_instance
48+
def test_sampling_rate_and_sampler_conflict(self):
49+
if hasattr(TracerWrapper, "instance"):
50+
_trace_wrapper_instance = TracerWrapper.instance
51+
del TracerWrapper.instance
52+
try:
53+
exporter = InMemorySpanExporter()
54+
sampler = TraceIdRatioBased(0.5)
55+
with pytest.raises(ValueError, match="Cannot specify both 'sampler' and 'sampling_rate'"):
56+
Traceloop.init(
57+
app_name="test-conflict",
58+
sampling_rate=0.5,
59+
sampler=sampler,
60+
exporter=exporter,
61+
disable_batch=True
62+
)
63+
finally:
64+
if '_trace_wrapper_instance' in locals():
65+
TracerWrapper.instance = _trace_wrapper_instance
66+
def test_sampling_rate_edge_cases(self):
67+
if hasattr(TracerWrapper, "instance"):
68+
_trace_wrapper_instance = TracerWrapper.instance
69+
del TracerWrapper.instance
70+
try:
71+
exporter = InMemorySpanExporter()
72+
client = Traceloop.init(
73+
app_name="test-sampling-zero",
74+
sampling_rate=0.0,
75+
exporter=exporter,
76+
disable_batch=True
77+
)
78+
assert client is None
79+
assert hasattr(TracerWrapper, "instance")
80+
del TracerWrapper.instance
81+
client = Traceloop.init(
82+
app_name="test-sampling-one",
83+
sampling_rate=1.0,
84+
exporter=exporter,
85+
disable_batch=True
86+
)
87+
assert client is None
88+
assert hasattr(TracerWrapper, "instance")
89+
finally:
90+
if '_trace_wrapper_instance' in locals():
91+
TracerWrapper.instance = _trace_wrapper_instance

packages/traceloop-sdk/traceloop/sdk/__init__.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from typing import Callable, List, Optional, Set, Union
66
from colorama import Fore
77
from opentelemetry.sdk.trace import SpanProcessor, ReadableSpan
8-
from opentelemetry.sdk.trace.sampling import Sampler
8+
from opentelemetry.sdk.trace.sampling import Sampler, TraceIdRatioBased
99
from opentelemetry.sdk.trace.export import SpanExporter
1010
from opentelemetry.sdk.metrics.export import MetricExporter
1111
from opentelemetry.sdk._logs.export import LogExporter
@@ -62,6 +62,7 @@ def init(
6262
processor: Optional[Union[SpanProcessor, List[SpanProcessor]]] = None,
6363
propagator: TextMapPropagator = None,
6464
sampler: Optional[Sampler] = None,
65+
sampling_rate: Optional[float] = None,
6566
traceloop_sync_enabled: bool = False,
6667
should_enrich_metrics: bool = True,
6768
resource_attributes: dict = {},
@@ -136,6 +137,19 @@ def init(
136137

137138
print(Fore.RESET)
138139

140+
if sampling_rate is not None and sampler is not None:
141+
raise ValueError(
142+
"Cannot specify both 'sampler' and 'sampling_rate'. "
143+
"Please use only one of these parameters."
144+
)
145+
146+
if sampling_rate is not None:
147+
if not 0.0 <= sampling_rate <= 1.0:
148+
raise ValueError(
149+
f"sampling_rate must be between 0.0 and 1.0, got {sampling_rate}"
150+
)
151+
sampler = TraceIdRatioBased(sampling_rate)
152+
139153
# Tracer init
140154
resource_attributes.update({SERVICE_NAME: app_name})
141155
TracerWrapper.set_static_params(

0 commit comments

Comments
 (0)