Skip to content
This repository was archived by the owner on Mar 24, 2025. It is now read-only.

Commit 10d5082

Browse files
authored
Fix local span metrics observers registering child observers (#592)
This fixes an issue where the local span metrics observers (tagged and untagged) would not register child observers when nesting spans beneath local spans.
1 parent 33668aa commit 10d5082

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

baseplate/observers/metrics.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@ def on_start(self) -> None:
124124
def on_incr_tag(self, key: str, delta: float) -> None:
125125
self.batch.counter(key).increment(delta, sample_rate=self.sample_rate)
126126

127+
def on_child_span_created(self, span: Span) -> None:
128+
observer: SpanObserver
129+
if isinstance(span, LocalSpan):
130+
observer = MetricsLocalSpanObserver(self.batch, span, self.sample_rate)
131+
else:
132+
observer = MetricsClientSpanObserver(self.batch, span, self.sample_rate)
133+
span.register(observer)
134+
127135
def on_finish(self, exc_info: Optional[_ExcInfo]) -> None:
128136
self.timer.stop()
129137

baseplate/observers/metrics_tagged.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,18 @@ def on_incr_tag(self, key: str, delta: float) -> None:
160160
def on_set_tag(self, key: str, value: Any) -> None:
161161
self.tags[key] = value
162162

163+
def on_child_span_created(self, span: Span) -> None:
164+
observer: SpanObserver
165+
if isinstance(span, LocalSpan):
166+
observer = TaggedMetricsLocalSpanObserver(
167+
self.batch, span, self.allowlist, self.sample_rate
168+
)
169+
else:
170+
observer = TaggedMetricsClientSpanObserver(
171+
self.batch, span, self.allowlist, self.sample_rate
172+
)
173+
span.register(observer)
174+
163175
def on_finish(self, exc_info: Optional[_ExcInfo]) -> None:
164176
filtered_tags = {k: v for (k, v) in self.tags.items() if k in self.allowlist}
165177

tests/unit/observers/metrics_tagged_tests.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import pytest
1010

1111
from baseplate import RequestContext
12+
from baseplate import ServerSpan
1213
from baseplate import Span
1314
from baseplate.lib.metrics import Counter
1415
from baseplate.lib.metrics import Gauge
@@ -156,3 +157,21 @@ def test_observer(observer_cls, name):
156157
assert counter["tags"].pop("endpoint") == "span"
157158
assert counter["tags"].pop("tag2") == "bar"
158159
assert counter["tags"] == {}
160+
161+
162+
def test_nested():
163+
batch = FakeBatch()
164+
span = ServerSpan(
165+
trace_id=1234,
166+
parent_id=2345,
167+
span_id=3456,
168+
sampled=None,
169+
flags=None,
170+
name="fancy.span",
171+
context=RequestContext({}),
172+
)
173+
observer = TaggedMetricsLocalSpanObserver(batch, span, {"client", "endpoint"})
174+
span.register(observer)
175+
176+
with span.make_child("foo", local=True, component_name="foo") as child_span:
177+
assert len(child_span.observers) == 1

tests/unit/observers/metrics_tests.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,19 @@ def test_metrics(self):
120120

121121
observer.on_finish(exc_info=None)
122122
self.assertEqual(mock_timer.stop.call_count, 1)
123+
124+
def test_spans_under_local_spans(self):
125+
mock_batch = mock.Mock(spec=Batch)
126+
127+
mock_local_span = mock.Mock(spec=LocalSpan)
128+
mock_local_span.name = "example"
129+
mock_local_span.component_name = "some_component"
130+
131+
mock_nested_span = mock.Mock(spec=LocalSpan)
132+
mock_nested_span.name = "nested"
133+
mock_nested_span.component_name = "some_component2"
134+
135+
observer = MetricsLocalSpanObserver(mock_batch, mock_local_span)
136+
observer.on_child_span_created(mock_nested_span)
137+
138+
self.assertEqual(mock_nested_span.register.call_count, 1)

0 commit comments

Comments
 (0)