forked from discord/dd-trace-py
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_trace_stats.py
159 lines (126 loc) · 5.22 KB
/
test_trace_stats.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import os
from typing import Generator
import pytest
from ddtrace import Tracer
from ddtrace.constants import SPAN_MEASURED_KEY
from ddtrace.ext import http
from ddtrace.internal.processor.stats import SpanStatsProcessorV06
from ddtrace.sampler import DatadogSampler
from ddtrace.sampler import SamplingRule
from tests.utils import override_global_config
from .test_integration import AGENT_VERSION
pytestmark = pytest.mark.skipif(AGENT_VERSION != "testagent", reason="Tests only compatible with a testagent")
@pytest.fixture
def sample_rate():
# type: () -> Generator[float, None, None]
# Default the sample rate to 0 so no traces are sent for requests.
yield 0.0
@pytest.fixture
def stats_tracer(sample_rate):
# type: (float) -> Generator[Tracer, None, None]
with override_global_config(dict(_trace_compute_stats=True)):
tracer = Tracer()
tracer.configure(
sampler=DatadogSampler(
default_sample_rate=sample_rate,
)
)
yield tracer
tracer.shutdown()
@pytest.mark.parametrize("envvar", ["DD_TRACE_STATS_COMPUTATION_ENABLED", "DD_TRACE_COMPUTE_STATS"])
def test_compute_stats_default_and_configure(run_python_code_in_subprocess, envvar):
"""Ensure stats computation can be enabled."""
# Test enabling via `configure`
t = Tracer()
assert not t._compute_stats
assert not any(isinstance(p, SpanStatsProcessorV06) for p in t._span_processors)
t.configure(compute_stats_enabled=True)
assert any(isinstance(p, SpanStatsProcessorV06) for p in t._span_processors)
assert t._compute_stats
# Test enabling via environment variable
env = os.environ.copy()
env.update({envvar: "true"})
out, err, status, _ = run_python_code_in_subprocess(
"""
from ddtrace import tracer
from ddtrace import config
from ddtrace.internal.processor.stats import SpanStatsProcessorV06
assert config._trace_compute_stats is True
assert any(isinstance(p, SpanStatsProcessorV06) for p in tracer._span_processors)
""",
env=env,
)
assert status == 0, out + err
# Can't use a value between 0 and 1 since sampling is not deterministic.
@pytest.mark.parametrize("sample_rate", [1.0, 0.0])
@pytest.mark.snapshot()
def test_sampling_rate(stats_tracer, sample_rate):
"""Ensure traces are sent according to the sampling rate."""
for _ in range(10):
with stats_tracer.trace("operation"):
pass
@pytest.mark.snapshot()
def test_stats_1000(stats_tracer, sample_rate):
for i in range(1000):
with stats_tracer.trace("name", service="abc", resource="/users/list"):
pass
@pytest.mark.snapshot()
def test_stats_errors(stats_tracer, sample_rate):
for i in range(1000):
with stats_tracer.trace("name", service="abc", resource="/users/list") as span:
if i % 2 == 0:
span.error = 1
@pytest.mark.snapshot()
def test_stats_aggrs(stats_tracer, sample_rate):
"""
When different span properties are set
The stats are put into different aggregations
"""
with stats_tracer.trace(name="op", service="my-svc", span_type="web", resource="/users/list"):
pass
# Synthetics
with stats_tracer.trace(name="op", service="my-svc", span_type="web", resource="/users/list") as span:
span.context.dd_origin = "synthetics"
# HTTP status code
with stats_tracer.trace(name="op", service="my-svc", span_type="web", resource="/users/list") as span:
span.set_tag(http.STATUS_CODE, 200)
# Resource
with stats_tracer.trace(name="op", service="my-svc", span_type="web", resource="/users/view"):
pass
# Service
with stats_tracer.trace(name="op", service="diff-svc", span_type="web", resource="/users/list"):
pass
# Name
with stats_tracer.trace(name="diff-op", service="my-svc", span_type="web", resource="/users/list"):
pass
# Type
with stats_tracer.trace(name="diff-op", service="my-svc", span_type="db", resource="/users/list"):
pass
@pytest.mark.snapshot()
def test_measured_span(stats_tracer):
for _ in range(10):
with stats_tracer.trace("parent"): # Should have stats
with stats_tracer.trace("child"): # Shouldn't have stats
pass
for _ in range(10):
with stats_tracer.trace("parent"): # Should have stats
with stats_tracer.trace("child_stats") as span: # Should have stats
span.set_tag(SPAN_MEASURED_KEY)
@pytest.mark.snapshot()
def test_top_level(stats_tracer):
for _ in range(100):
with stats_tracer.trace("parent", service="svc-one"): # Should have stats
with stats_tracer.trace("child", service="svc-two"): # Should have stats
pass
@pytest.mark.parametrize(
"sampling_rule",
[SamplingRule(sample_rate=0, service="test"), SamplingRule(sample_rate=1, service="test")],
)
@pytest.mark.snapshot()
def test_single_span_sampling(stats_tracer, sampling_rule):
sampler = DatadogSampler([sampling_rule])
stats_tracer.configure(sampler=sampler)
with stats_tracer.trace("parent", service="test"):
with stats_tracer.trace("child") as child:
# FIXME: Replace with span sampling rule
child.set_metric("_dd.span_sampling.mechanism", 8)