Skip to content

Commit 3bbab02

Browse files
authored
Attributes returned from SamplingResult must be immutable (open-telemetry#1066)
1 parent e45354c commit 3bbab02

File tree

6 files changed

+42
-4
lines changed

6 files changed

+42
-4
lines changed

instrumentation/opentelemetry-instrumentation-system-metrics/setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ package_dir=
4141
packages=find_namespace:
4242
install_requires =
4343
opentelemetry-api == 0.13dev0
44+
opentelemetry-sdk == 0.13dev0
4445
psutil ~= 5.7.0
4546

4647
[options.extras_require]

opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ def start_span( # pylint: disable=too-many-locals
772772
parent=parent_context,
773773
sampler=self.source.sampler,
774774
resource=self.source.resource,
775-
attributes=sampling_result.attributes,
775+
attributes=sampling_result.attributes.copy(),
776776
span_processor=self.source._active_span_processor,
777777
kind=kind,
778778
links=links,

opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"""
6363
import abc
6464
import enum
65+
from types import MappingProxyType
6566
from typing import Optional, Sequence
6667

6768
# pylint: disable=unused-import
@@ -102,11 +103,10 @@ def __init__(
102103
self, decision: Decision, attributes: Attributes = None,
103104
) -> None:
104105
self.decision = decision
105-
# TODO: attributes must be immutable
106106
if attributes is None:
107-
self.attributes = {}
107+
self.attributes = MappingProxyType({})
108108
else:
109-
self.attributes = attributes
109+
self.attributes = MappingProxyType(attributes)
110110

111111

112112
class Sampler(abc.ABC):

opentelemetry-sdk/tests/trace/test_sampling.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,43 @@
2222
TO_SAMPLED = trace.TraceFlags(trace.TraceFlags.SAMPLED)
2323

2424

25+
class TestDecision(unittest.TestCase):
26+
def test_is_recording(self):
27+
self.assertTrue(
28+
sampling.Decision.is_recording(sampling.Decision.RECORD)
29+
)
30+
self.assertTrue(
31+
sampling.Decision.is_recording(
32+
sampling.Decision.RECORD_AND_SAMPLED
33+
)
34+
)
35+
self.assertFalse(
36+
sampling.Decision.is_recording(sampling.Decision.NOT_RECORD)
37+
)
38+
39+
def test_is_sampled(self):
40+
self.assertFalse(
41+
sampling.Decision.is_sampled(sampling.Decision.RECORD)
42+
)
43+
self.assertTrue(
44+
sampling.Decision.is_sampled(sampling.Decision.RECORD_AND_SAMPLED)
45+
)
46+
self.assertFalse(
47+
sampling.Decision.is_sampled(sampling.Decision.NOT_RECORD)
48+
)
49+
50+
51+
class TestSamplingResult(unittest.TestCase):
52+
def test_ctr(self):
53+
attributes = {"asd": "test"}
54+
result = sampling.SamplingResult(sampling.Decision.RECORD, attributes)
55+
self.assertIs(result.decision, sampling.Decision.RECORD)
56+
with self.assertRaises(TypeError):
57+
result.attributes["test"] = "mess-this-up"
58+
self.assertTrue(len(result.attributes), 1)
59+
self.assertEqual(result.attributes["asd"], "test")
60+
61+
2562
class TestSampler(unittest.TestCase):
2663
def test_always_on(self):
2764
no_record_always_on = sampling.ALWAYS_ON.should_sample(

0 commit comments

Comments
 (0)