Skip to content

Commit 0341b0f

Browse files
authored
fix: Create span when no active span for error. (#191)
## Summary Create a span for recording errors when one doesn't exist already. Also added a unit test suite for the singleton instance. ## How did you test this change? Unit tests. ## Are there any deployment considerations? <!-- Backend - Do we need to consider migrations or backfilling data? -->
1 parent 2dda77a commit 0341b0f

File tree

4 files changed

+685
-12
lines changed

4 files changed

+685
-12
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.coverage
22
coverage.xml
33
.coveragerc
4-
docs/
4+
docs/
5+
.vscode/

sdk/@launchdarkly/observability-python/ldobserve/_otel/configuration.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ def log_handler(self) -> LoggingHandler:
8080
def meter(self) -> Meter:
8181
return self._meter
8282

83+
@property
84+
def tracer(self) -> otel_trace.Tracer:
85+
return self._tracer
86+
8387
def __init__(self, project_id: str, config: _ProcessedConfig):
8488
self._project_id = project_id
8589
self._config = config

sdk/@launchdarkly/observability-python/ldobserve/observe.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
UpDownCounter as APIUpDownCounter,
1919
)
2020

21-
_name = "launchdarkly-observability"
21+
_NAME = "launchdarkly-observability"
22+
_ERROR_NAME = "launchdarkly.error"
2223

2324

2425
class _ObserveInstance:
@@ -45,22 +46,26 @@ def __init__(self, project_id: str, otel_configuration: _OTELConfiguration):
4546
self._logger.propagate = False
4647
self._logger.addHandler(otel_configuration.log_handler)
4748
self._project_id = project_id
48-
self._tracer = trace.get_tracer(_name)
49+
self._tracer = otel_configuration.tracer
4950

5051
def record_exception(
5152
self, error: Exception, attributes: typing.Optional[Attributes] = None
5253
):
54+
if error is None:
55+
return # Nothing to record
56+
5357
span = trace.get_current_span()
54-
if not span:
55-
self._logger.error("observe.record_exception called without a span context")
56-
return
58+
ctx = contextlib.nullcontext(span)
59+
if not span or not span.is_recording():
60+
ctx = self.start_span(_ERROR_NAME)
5761

58-
attrs = {}
59-
if attributes:
60-
addedAttributes = flatten_dict(attributes, sep=".")
61-
attrs.update(addedAttributes)
62+
with ctx as span:
63+
attrs = {}
64+
if attributes:
65+
addedAttributes = flatten_dict(attributes, sep=".")
66+
attrs.update(addedAttributes)
6267

63-
span.record_exception(error, attrs)
68+
span.record_exception(error, attrs)
6469

6570
def record_metric(
6671
self, name: str, value: float, attributes: typing.Optional[Attributes] = None
@@ -128,7 +133,7 @@ def start_span(
128133
Yields:
129134
The newly-created span.
130135
"""
131-
with trace.get_tracer(__name__).start_as_current_span(
136+
with self._tracer.start_as_current_span(
132137
name,
133138
attributes=attributes,
134139
record_exception=record_exception,

0 commit comments

Comments
 (0)