From 2e9dad1eb092fe2193261193292a666c414df4f7 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Mon, 28 Apr 2025 12:23:58 +0200 Subject: [PATCH 1/6] Slim down outgoing payload --- sentry_sdk/opentelemetry/span_processor.py | 12 ++++++++++-- tests/test_feature_flags.py | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/opentelemetry/span_processor.py b/sentry_sdk/opentelemetry/span_processor.py index 6da616ed87..b9b5b38515 100644 --- a/sentry_sdk/opentelemetry/span_processor.py +++ b/sentry_sdk/opentelemetry/span_processor.py @@ -45,6 +45,11 @@ DEFAULT_MAX_SPANS = 1000 +# Span attributes internal to the SDK that should be omitted from the final payload +IGNORE_SPAN_ATTRIBUTES = [ + "flag.count", +] + class SentrySpanProcessor(SpanProcessor): """ @@ -289,8 +294,11 @@ def _span_to_json(self, span): if parent_span_id: span_json["parent_span_id"] = parent_span_id - if span.attributes: - span_json["data"] = dict(span.attributes) + if getattr(span, "attributes", {}): + span_json["data"] = {} + for key, value in span.attributes.items(): + if key not in IGNORE_SPAN_ATTRIBUTES: + span_json["data"][key] = value return span_json diff --git a/tests/test_feature_flags.py b/tests/test_feature_flags.py index 1b0ed13d49..24b3c3ef88 100644 --- a/tests/test_feature_flags.py +++ b/tests/test_feature_flags.py @@ -259,3 +259,19 @@ def test_flag_limit(sentry_init, capture_events): } ) assert "flag.evaluation.10" not in event["spans"][0]["data"] + + +def test_flag_counter_not_sent(sentry_init, capture_events): + sentry_init(traces_sample_rate=1.0) + + events = capture_events() + + with start_transaction(name="hi"): + with start_span(op="foo", name="bar"): + add_feature_flag("0", True) + add_feature_flag("1", True) + add_feature_flag("2", True) + add_feature_flag("3", True) + + (event,) = events + assert "flag.counter" not in event["spans"][0]["data"] From 4e1fa6f598bb80e792ad9ca4a2c0890add2349a4 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Mon, 28 Apr 2025 12:32:09 +0200 Subject: [PATCH 2/6] just do underscore --- sentry_sdk/opentelemetry/span_processor.py | 7 +------ sentry_sdk/tracing.py | 4 ++-- tests/test_feature_flags.py | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/sentry_sdk/opentelemetry/span_processor.py b/sentry_sdk/opentelemetry/span_processor.py index b9b5b38515..d6de3120a2 100644 --- a/sentry_sdk/opentelemetry/span_processor.py +++ b/sentry_sdk/opentelemetry/span_processor.py @@ -45,11 +45,6 @@ DEFAULT_MAX_SPANS = 1000 -# Span attributes internal to the SDK that should be omitted from the final payload -IGNORE_SPAN_ATTRIBUTES = [ - "flag.count", -] - class SentrySpanProcessor(SpanProcessor): """ @@ -297,7 +292,7 @@ def _span_to_json(self, span): if getattr(span, "attributes", {}): span_json["data"] = {} for key, value in span.attributes.items(): - if key not in IGNORE_SPAN_ATTRIBUTES: + if not key.startswith("_"): span_json["data"][key] = value return span_json diff --git a/sentry_sdk/tracing.py b/sentry_sdk/tracing.py index 7b8004c8b5..acc9faecc3 100644 --- a/sentry_sdk/tracing.py +++ b/sentry_sdk/tracing.py @@ -600,10 +600,10 @@ def set_context(self, key, value): def set_flag(self, flag, value): # type: (str, bool) -> None - flag_count = self.get_attribute("flag.count") or 0 + flag_count = self.get_attribute("_flag.count") or 0 if flag_count < _FLAGS_CAPACITY: self.set_attribute(f"flag.evaluation.{flag}", value) - self.set_attribute("flag.count", flag_count + 1) + self.set_attribute("_flag.count", flag_count + 1) # TODO-neel-potel add deprecation diff --git a/tests/test_feature_flags.py b/tests/test_feature_flags.py index 24b3c3ef88..5c2f1cd352 100644 --- a/tests/test_feature_flags.py +++ b/tests/test_feature_flags.py @@ -274,4 +274,4 @@ def test_flag_counter_not_sent(sentry_init, capture_events): add_feature_flag("3", True) (event,) = events - assert "flag.counter" not in event["spans"][0]["data"] + assert "_flag.count" not in event["spans"][0]["data"] From 92c27b46672ce94a320799c939f56bdb8d27674a Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Mon, 28 Apr 2025 12:46:34 +0200 Subject: [PATCH 3/6] add a span processor test --- tests/opentelemetry/test_span_processor.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/opentelemetry/test_span_processor.py diff --git a/tests/opentelemetry/test_span_processor.py b/tests/opentelemetry/test_span_processor.py new file mode 100644 index 0000000000..7d6283d4ea --- /dev/null +++ b/tests/opentelemetry/test_span_processor.py @@ -0,0 +1,19 @@ +import sentry_sdk + + +def test_span_processor_omits_underscore_attributes(sentry_init, capture_events): + sentry_init(traces_sample_rate=1.0) + + events = capture_events() + + with sentry_sdk.start_span(): + with sentry_sdk.start_span() as span: + span.set_attribute("_internal", 47) + span.set_attribute("noninternal", 23) + + assert span._otel_span.attributes["_internal"] == 47 + assert span._otel_span.attributes["noninternal"] == 23 + + outgoing_span = events[0]["spans"][0] + assert "_internal" not in outgoing_span["data"] + assert "noninternal" in outgoing_span["data"] From 0db50ade77af7a91b9486dd5635c5920710236cc Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Mon, 28 Apr 2025 12:47:37 +0200 Subject: [PATCH 4/6] . --- sentry_sdk/opentelemetry/span_processor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/opentelemetry/span_processor.py b/sentry_sdk/opentelemetry/span_processor.py index d6de3120a2..199c9ad073 100644 --- a/sentry_sdk/opentelemetry/span_processor.py +++ b/sentry_sdk/opentelemetry/span_processor.py @@ -289,7 +289,7 @@ def _span_to_json(self, span): if parent_span_id: span_json["parent_span_id"] = parent_span_id - if getattr(span, "attributes", {}): + if getattr(span, "attributes", {}) or {}: span_json["data"] = {} for key, value in span.attributes.items(): if not key.startswith("_"): From 6d6686323c60a045dd858f26f57c615c90c9575f Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Mon, 28 Apr 2025 12:51:48 +0200 Subject: [PATCH 5/6] mypy --- sentry_sdk/opentelemetry/span_processor.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/opentelemetry/span_processor.py b/sentry_sdk/opentelemetry/span_processor.py index 199c9ad073..786253d90a 100644 --- a/sentry_sdk/opentelemetry/span_processor.py +++ b/sentry_sdk/opentelemetry/span_processor.py @@ -289,9 +289,10 @@ def _span_to_json(self, span): if parent_span_id: span_json["parent_span_id"] = parent_span_id - if getattr(span, "attributes", {}) or {}: + attributes = getattr(span, "attributes", {}) or {} + if attributes: span_json["data"] = {} - for key, value in span.attributes.items(): + for key, value in attributes.items(): if not key.startswith("_"): span_json["data"][key] = value From fea9875176899029b3e91962d32fc577a46d2c4f Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Mon, 28 Apr 2025 14:54:09 +0200 Subject: [PATCH 6/6] eyeroll --- tests/integrations/threading/test_threading.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/integrations/threading/test_threading.py b/tests/integrations/threading/test_threading.py index 4ab742ff1f..8a5dfef62b 100644 --- a/tests/integrations/threading/test_threading.py +++ b/tests/integrations/threading/test_threading.py @@ -9,7 +9,6 @@ import sentry_sdk from sentry_sdk import capture_message from sentry_sdk.integrations.threading import ThreadingIntegration -from sentry_sdk.tracing import _OTEL_VERSION original_start = Thread.start original_run = Thread.run @@ -106,10 +105,7 @@ def double(number): assert len(event["spans"]) == 0 -@pytest.mark.skipif( - sys.version[:3] == "3.8" and (1, 12) <= _OTEL_VERSION < (1, 16), - reason="Fails in CI on 3.8 and specific OTel versions", -) +@pytest.mark.skipif(sys.version[:3] == "3.8", reason="Fails in CI on 3.8") def test_circular_references(sentry_init, request): sentry_init(default_integrations=False, integrations=[ThreadingIntegration()])