Skip to content

Commit a3643d8

Browse files
committed
tests(process_tags): add tests
1 parent d76a11d commit a3643d8

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

.riot/requirements/1645326.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#
2+
# This file is autogenerated by pip-compile with Python 3.13
3+
# by the following command:
4+
#
5+
# pip-compile --allow-unsafe --no-annotate .riot/requirements/1645326.in
6+
#
7+
attrs==25.4.0
8+
coverage[toml]==7.11.0
9+
hypothesis==6.45.0
10+
iniconfig==2.3.0
11+
mock==5.2.0
12+
opentracing==2.4.0
13+
packaging==25.0
14+
pluggy==1.6.0
15+
pygments==2.19.2
16+
pytest==8.4.2
17+
pytest-cov==7.0.0
18+
pytest-mock==3.15.1
19+
sortedcontainers==2.4.0

riotfile.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,11 @@ def select_pys(min_version: str = MIN_PYTHON_VERSION, max_version: str = MAX_PYT
498498
command="pytest --no-cov {cmdargs} tests/coverage -s",
499499
pys=select_pys(max_version="3.12"),
500500
),
501+
Venv(
502+
name="process_tags",
503+
command="pytest -v {cmdargs} tests/process_tags/",
504+
pys=select_pys(min_version="3.9")
505+
),
501506
Venv(
502507
name="internal",
503508
env={

tests/process_tags/__init__.py

Whitespace-only changes.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
from ddtrace.internal.process_tags import normalize_tag
2+
from ddtrace.internal.process_tags import process_tags
3+
from ddtrace.internal.constants import PROCESS_TAGS
4+
from ddtrace.internal.process_tags.constants import ENTRYPOINT_BASEDIR_TAG, ENTRYPOINT_NAME_TAG, ENTRYPOINT_TYPE_SCRIPT, ENTRYPOINT_TYPE_TAG, ENTRYPOINT_WORKDIR_TAG
5+
from tests.utils import TracerTestCase
6+
from tests.utils import override_env
7+
import sys
8+
import os
9+
from pathlib import Path
10+
11+
def test_normalize_tag():
12+
assert normalize_tag("HelloWorld") == "helloworld"
13+
assert normalize_tag("Hello@World!") == "hello_world_"
14+
assert normalize_tag("HeLLo123") == "hello123"
15+
assert normalize_tag("hello world") == "hello_world"
16+
assert normalize_tag("a/b.c_d-e") == "a/b.c_d-e"
17+
assert normalize_tag("héllø") == "h_ll_"
18+
assert normalize_tag("") == ""
19+
assert normalize_tag("💡⚡️") == "___"
20+
assert normalize_tag("!foo@") == "_foo_"
21+
assert normalize_tag("123_abc.DEF-ghi/jkl") == "123_abc.def-ghi/jkl"
22+
assert normalize_tag("Env:Prod-Server#1") == "env_prod-server_1"
23+
24+
class TestProcessTags(TracerTestCase):
25+
26+
def test_process_tags_deactivated(self):
27+
with self.tracer.trace("test"):
28+
pass
29+
30+
span = self.get_spans()[0]
31+
assert span is not None
32+
assert PROCESS_TAGS not in span._meta
33+
34+
def test_process_tags_activated_with_override_env(self):
35+
"""Test process tags using override_env instead of run_in_subprocess"""
36+
with override_env(dict(DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED="True")):
37+
process_tags._enabled = True
38+
process_tags.reload()
39+
40+
with self.tracer.trace("test"):
41+
pass
42+
43+
process_tags._enabled = False
44+
45+
span = self.get_spans()[0]
46+
assert span is not None
47+
assert PROCESS_TAGS in span._meta
48+
49+
expected_name = "pytest"
50+
expected_type = ENTRYPOINT_TYPE_SCRIPT
51+
expected_basedir = Path(sys.argv[0]).resolve().parent.name
52+
expected_workdir = os.path.basename(os.getcwd())
53+
54+
serialized_tags = span._meta[PROCESS_TAGS]
55+
expected_raw = (
56+
f"{ENTRYPOINT_WORKDIR_TAG}:{expected_workdir},"
57+
f"{ENTRYPOINT_BASEDIR_TAG}:{expected_basedir},"
58+
f"{ENTRYPOINT_NAME_TAG}:{expected_name},"
59+
f"{ENTRYPOINT_TYPE_TAG}:{expected_type}"
60+
)
61+
assert serialized_tags == expected_raw
62+
63+
tags_dict = dict(tag.split(":", 1) for tag in serialized_tags.split(","))
64+
assert tags_dict[ENTRYPOINT_NAME_TAG] == expected_name
65+
assert tags_dict[ENTRYPOINT_TYPE_TAG] == expected_type
66+
assert tags_dict[ENTRYPOINT_BASEDIR_TAG] == expected_basedir
67+
assert tags_dict[ENTRYPOINT_WORKDIR_TAG] == expected_workdir
68+
69+
def test_process_tags_only_on_local_root_span(self):
70+
"""Test that only local root spans get process tags, not children"""
71+
with override_env(dict(DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED="True")):
72+
process_tags._enabled = True
73+
process_tags.reload()
74+
75+
with self.tracer.trace("parent"):
76+
with self.tracer.trace("child"):
77+
pass
78+
79+
process_tags._enabled = False
80+
81+
spans = self.get_spans()
82+
assert len(spans) == 2
83+
84+
parent = [s for s in spans if s.name == "parent"][0]
85+
assert PROCESS_TAGS in parent._meta
86+
87+
child = [s for s in spans if s.name == "child"][0]
88+
assert PROCESS_TAGS not in child._meta
89+
90+
def test_add_process_tag_compute_exception(self):
91+
"""Test error handling when compute raises exception"""
92+
with override_env(dict(DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED="True")):
93+
process_tags._enabled = True
94+
process_tags.reload()
95+
96+
def failing_compute():
97+
raise ValueError("Test exception")
98+
99+
process_tags.add_process_tag("test.tag", compute=failing_compute)
100+
101+
assert "test.tag" not in process_tags.process_tags
102+
103+
process_tags.add_process_tag("test.working", value="value")
104+
assert "test.working" in process_tags.process_tags
105+
assert process_tags.process_tags["test.working"] == "value"
106+
107+
process_tags._enabled = False
108+
109+
def test_serialization_caching(self):
110+
"""Test that serialization is cached and invalidated properly"""
111+
with override_env(dict(DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED="True")):
112+
process_tags._enabled = True
113+
process_tags.reload()
114+
115+
result1 = process_tags.get_serialized_process_tags()
116+
assert process_tags._serialized is not None
117+
118+
process_tags.add_process_tag("custom.tag", value="test")
119+
assert process_tags._serialized is None
120+
121+
result3 = process_tags.get_serialized_process_tags()
122+
assert "custom.tag:test" in result3
123+
124+
process_tags._enabled = False

0 commit comments

Comments
 (0)