From 6e282d27e5a7fa337322dda154fe6eecf64380f0 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sun, 12 Jun 2022 00:41:46 +0530 Subject: [PATCH] Allow `set_status` to accept the StatusCode and optional description (#2735) --- CHANGELOG.md | 2 ++ .../src/opentelemetry/trace/span.py | 14 ++++++-- opentelemetry-api/tests/trace/test_globals.py | 2 +- .../src/opentelemetry/sdk/trace/__init__.py | 34 +++++++++++++----- opentelemetry-sdk/tests/trace/test_trace.py | 35 ++++++++++++++++++- 5 files changed, 74 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb8b44adb9..068fdf7bc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#2728](https://github.com/open-telemetry/opentelemetry-python/pull/2728)) - fix: update entry point object references for metrics ([#2731](https://github.com/open-telemetry/opentelemetry-python/pull/2731)) +- Allow set_status to accept the StatusCode and optional description + ([#2735](https://github.com/open-telemetry/opentelemetry-python/pull/2735)) - Configure auto instrumentation to support metrics ([#2705](https://github.com/open-telemetry/opentelemetry-python/pull/2705)) - Add entrypoint for metrics exporter diff --git a/opentelemetry-api/src/opentelemetry/trace/span.py b/opentelemetry-api/src/opentelemetry/trace/span.py index cb9992557c..805b2b06b1 100644 --- a/opentelemetry-api/src/opentelemetry/trace/span.py +++ b/opentelemetry-api/src/opentelemetry/trace/span.py @@ -5,7 +5,7 @@ import typing from collections import OrderedDict -from opentelemetry.trace.status import Status +from opentelemetry.trace.status import Status, StatusCode from opentelemetry.util import types # The key MUST begin with a lowercase letter or a digit, @@ -137,7 +137,11 @@ def is_recording(self) -> bool: """ @abc.abstractmethod - def set_status(self, status: Status) -> None: + def set_status( + self, + status: typing.Union[Status, StatusCode], + description: typing.Optional[str] = None, + ) -> None: """Sets the Status of the Span. If used, this will override the default Span status. """ @@ -524,7 +528,11 @@ def add_event( def update_name(self, name: str) -> None: pass - def set_status(self, status: Status) -> None: + def set_status( + self, + status: typing.Union[Status, StatusCode], + description: typing.Optional[str] = None, + ) -> None: pass def record_exception( diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py index 0ead559f86..a448437e98 100644 --- a/opentelemetry-api/tests/trace/test_globals.py +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -12,7 +12,7 @@ class TestSpan(trace.NonRecordingSpan): recorded_exception = None recorded_status = Status(status_code=StatusCode.UNSET) - def set_status(self, status): + def set_status(self, status, description=None): self.recorded_status = status def end(self, end_time=None): diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index f527967378..7dc65600f4 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -889,16 +889,34 @@ def is_recording(self) -> bool: return self._end_time is None @_check_span_ended - def set_status(self, status: trace_api.Status) -> None: + def set_status( + self, + status: typing.Union[Status, StatusCode], + description: typing.Optional[str] = None, + ) -> None: # Ignore future calls if status is already set to OK # Ignore calls to set to StatusCode.UNSET - if ( - self._status - and self._status.status_code is StatusCode.OK - or status.status_code is StatusCode.UNSET - ): - return - self._status = status + if isinstance(status, Status): + if ( + self._status + and self._status.status_code is StatusCode.OK + or status.status_code is StatusCode.UNSET + ): + return + if description is not None: + logger.warning( + "Description %s ignored. Use either `Status` or `(StatusCode, Description)`", + description, + ) + self._status = status + elif isinstance(status, StatusCode): + if ( + self._status + and self._status.status_code is StatusCode.OK + or status is StatusCode.UNSET + ): + return + self._status = Status(status, description) def __exit__( self, diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index ad16578973..b89734db2f 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -45,7 +45,7 @@ get_span_with_dropped_attributes_events_links, new_tracer, ) -from opentelemetry.trace import StatusCode +from opentelemetry.trace import Status, StatusCode from opentelemetry.util._time import _time_ns @@ -903,6 +903,39 @@ def test_span_override_start_and_end_time(self): span.end(end_time) self.assertEqual(end_time, span.end_time) + def test_span_set_status(self): + + span1 = self.tracer.start_span("span1") + span1.set_status(Status(status_code=StatusCode.ERROR)) + self.assertEqual(span1.status.status_code, StatusCode.ERROR) + self.assertEqual(span1.status.description, None) + + span2 = self.tracer.start_span("span2") + span2.set_status( + Status(status_code=StatusCode.ERROR, description="desc") + ) + self.assertEqual(span2.status.status_code, StatusCode.ERROR) + self.assertEqual(span2.status.description, "desc") + + span3 = self.tracer.start_span("span3") + span3.set_status(StatusCode.ERROR) + self.assertEqual(span3.status.status_code, StatusCode.ERROR) + self.assertEqual(span3.status.description, None) + + span4 = self.tracer.start_span("span4") + span4.set_status(StatusCode.ERROR, "span4 desc") + self.assertEqual(span4.status.status_code, StatusCode.ERROR) + self.assertEqual(span4.status.description, "span4 desc") + + span5 = self.tracer.start_span("span5") + with self.assertLogs(level=WARNING): + span5.set_status( + Status(status_code=StatusCode.ERROR, description="desc"), + description="ignored", + ) + self.assertEqual(span5.status.status_code, StatusCode.ERROR) + self.assertEqual(span5.status.description, "desc") + def test_ended_span(self): """Events, attributes are not allowed after span is ended"""