Skip to content

Commit e63f6f6

Browse files
committed
[Core] Add method for setting span status
Spans started by `OpenTelemetryTracer` in core return an OpenTelemetry span. The set_status on this method requires that a user imports `opentelemetry` types for `StatusCode` enums. We want to avoid SDK developers needing to import `opentelemetry` in order to set a span status, so we are adding a utility method on the `OpenTelemetryTracer` class to enable this. Signed-off-by: Paul Van Eck <[email protected]>
1 parent 7f659e6 commit e63f6f6

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

sdk/core/azure-core/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Features Added
66

7+
- Added a `set_span_status` method to the `OpenTelemetryTracer` class. This method allows users to set the status of a span after it has been created. #40703
8+
79
### Breaking Changes
810

911
### Bugs Fixed

sdk/core/azure-core/azure/core/tracing/opentelemetry.py

+22
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
Span,
1313
SpanKind as OpenTelemetrySpanKind,
1414
Link as OpenTelemetryLink,
15+
StatusCode,
1516
)
1617
from opentelemetry.trace.propagation import get_current_span as get_current_span_otel
1718
from opentelemetry.propagate import extract, inject
@@ -161,6 +162,27 @@ def use_span(cls, span: Span, *, end_on_exit: bool = True) -> Iterator[Span]:
161162
) as active_span:
162163
yield active_span
163164

165+
@staticmethod
166+
def set_span_status(span: Span, status: str, description: Optional[str] = None) -> None:
167+
"""Set the status of a span.
168+
169+
:param span: The span to set the status on
170+
:type span: ~opentelemetry.trace.Span
171+
:param status: The status to set. Valid values are "OK", "ERROR", or "UNSET".
172+
:type status: str
173+
:param description: An optional description of the status. Only valid when status is "ERROR".
174+
:type description: str
175+
"""
176+
status = status.upper()
177+
if status == "OK":
178+
span.set_status(StatusCode.OK)
179+
elif status == "ERROR":
180+
span.set_status(StatusCode.ERROR, description=description)
181+
elif status == "UNSET":
182+
span.set_status(StatusCode.UNSET)
183+
else:
184+
raise ValueError(f"Invalid status value: {status}. Valid values are 'OK', 'ERROR', or 'UNSET'.")
185+
164186
def _parse_links(self, links: Optional[Sequence[Link]]) -> Optional[Sequence[OpenTelemetryLink]]:
165187
if not links:
166188
return None

sdk/core/azure-core/tests/test_tracer_otel.py

+36
Original file line numberDiff line numberDiff line change
@@ -354,3 +354,39 @@ def test_tracer_caching_different_args():
354354

355355
assert tracer1 is tracer2
356356
assert tracer1 is not tracer3
357+
358+
359+
def test_tracer_set_span_status(tracing_helper):
360+
"""Test that the tracer's set_span_status method works correctly."""
361+
tracer = get_tracer()
362+
assert tracer
363+
364+
# Test OK status
365+
with tracer.start_as_current_span(name="ok-span") as span:
366+
tracer.set_span_status(span, "OK")
367+
368+
# Test ERROR status with description
369+
with tracer.start_as_current_span(name="error-span") as span:
370+
tracer.set_span_status(span, "ERROR", "This is an error")
371+
372+
# Test UNSET status
373+
with tracer.start_as_current_span(name="unset-span") as span:
374+
tracer.set_span_status(span, "unset") # Testing case-insensitivity
375+
376+
# Test invalid status
377+
with tracer.start_as_current_span(name="invalid-span") as span:
378+
with pytest.raises(ValueError):
379+
tracer.set_span_status(span, "INVALID")
380+
381+
# Verify status on finished spans
382+
finished_spans = tracing_helper.exporter.get_finished_spans()
383+
assert len(finished_spans) == 4
384+
385+
assert finished_spans[0].status.status_code == OtelStatusCode.OK
386+
assert finished_spans[0].status.description is None
387+
388+
assert finished_spans[1].status.status_code == OtelStatusCode.ERROR
389+
assert finished_spans[1].status.description == "This is an error"
390+
391+
assert finished_spans[2].status.status_code == OtelStatusCode.UNSET
392+
assert finished_spans[2].status.description is None

0 commit comments

Comments
 (0)