From b2985d4f57a6be31c20edb7b1c590760686bbbab Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sun, 1 Nov 2020 20:06:16 +0530 Subject: [PATCH 1/4] Update Span.record_exception to to adhere to specs --- opentelemetry-api/CHANGELOG.md | 1 + .../src/opentelemetry/trace/span.py | 14 +++- opentelemetry-sdk/CHANGELOG.md | 1 + .../src/opentelemetry/sdk/trace/__init__.py | 22 ++++-- opentelemetry-sdk/tests/trace/test_trace.py | 79 +++++++++++++++++++ 5 files changed, 107 insertions(+), 10 deletions(-) diff --git a/opentelemetry-api/CHANGELOG.md b/opentelemetry-api/CHANGELOG.md index 977dd6375c0..9e91c377d98 100644 --- a/opentelemetry-api/CHANGELOG.md +++ b/opentelemetry-api/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- Updating `Span.record_exception` to adhere to specs - Updating status codes to adhere to specs ([#1282](https://github.com/open-telemetry/opentelemetry-python/pull/1282)) ## Version 0.14b0 diff --git a/opentelemetry-api/src/opentelemetry/trace/span.py b/opentelemetry-api/src/opentelemetry/trace/span.py index 2b206468afa..5cf4c36a3e8 100644 --- a/opentelemetry-api/src/opentelemetry/trace/span.py +++ b/opentelemetry-api/src/opentelemetry/trace/span.py @@ -79,7 +79,12 @@ def set_status(self, status: Status) -> None: """ @abc.abstractmethod - def record_exception(self, exception: Exception) -> None: + def record_exception( + self, + exception: Exception, + attributes: types.Attributes = None, + timestamp: typing.Optional[int] = None, + ) -> None: """Records an exception as a span event.""" def __enter__(self) -> "Span": @@ -263,7 +268,12 @@ def update_name(self, name: str) -> None: def set_status(self, status: Status) -> None: pass - def record_exception(self, exception: Exception) -> None: + def record_exception( + self, + exception: Exception, + attributes: types.Attributes = None, + timestamp: typing.Optional[int] = None, + ) -> None: pass diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index 2c1c3d971d0..71603afa97e 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- Updating `Span.record_exception` to adhere to specs - Make `SpanProcessor.on_start` accept parent Context ([#1251](https://github.com/open-telemetry/opentelemetry-python/pull/1251)) - Fix b3 propagator entrypoint diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 400600bec83..05132768438 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -676,7 +676,12 @@ def __exit__( super().__exit__(exc_type, exc_val, exc_tb) - def record_exception(self, exception: Exception) -> None: + def record_exception( + self, + exception: Exception, + attributes: types.Attributes = None, + timestamp: Optional[int] = None, + ) -> None: """Records an exception as a span event.""" try: stacktrace = traceback.format_exc() @@ -685,14 +690,15 @@ def record_exception(self, exception: Exception) -> None: # an AttributeError if the __context__ on # an exception is None stacktrace = "Exception occurred on stacktrace formatting" - + _attributes = { + "exception.type": exception.__class__.__name__, + "exception.message": str(exception), + "exception.stacktrace": stacktrace, + } + if attributes: + _attributes.update(attributes) self.add_event( - name="exception", - attributes={ - "exception.type": exception.__class__.__name__, - "exception.message": str(exception), - "exception.stacktrace": stacktrace, - }, + name="exception", attributes=_attributes, timestamp=timestamp ) diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index d08e12dee26..521bde00c8c 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -874,6 +874,85 @@ def test_record_exception(self): exception_event.attributes["exception.stacktrace"], ) + def test_record_exception_with_attributes(self): + span = trace._Span("name", mock.Mock(spec=trace_api.SpanContext)) + try: + raise RuntimeError("error") + except RuntimeError as err: + attributes = {"has_additional_attributes": True} + span.record_exception(err, attributes) + exception_event = span.events[0] + self.assertEqual("exception", exception_event.name) + self.assertEqual( + "error", exception_event.attributes["exception.message"] + ) + self.assertEqual( + "RuntimeError", exception_event.attributes["exception.type"] + ) + self.assertIn( + "RuntimeError: error", + exception_event.attributes["exception.stacktrace"], + ) + self.assertIn( + "has_additional_attributes", exception_event.attributes, + ) + self.assertEqual( + True, exception_event.attributes["has_additional_attributes"], + ) + + def test_record_exception_with_timestamp(self): + span = trace._Span("name", mock.Mock(spec=trace_api.SpanContext)) + try: + raise RuntimeError("error") + except RuntimeError as err: + timestamp = 1604238587112021089 + span.record_exception(err, timestamp=timestamp) + exception_event = span.events[0] + self.assertEqual("exception", exception_event.name) + self.assertEqual( + "error", exception_event.attributes["exception.message"] + ) + self.assertEqual( + "RuntimeError", exception_event.attributes["exception.type"] + ) + self.assertIn( + "RuntimeError: error", + exception_event.attributes["exception.stacktrace"], + ) + self.assertEqual( + 1604238587112021089, exception_event.timestamp, + ) + + def test_record_exception_with_attributes_and_timestamp(self): + span = trace._Span("name", mock.Mock(spec=trace_api.SpanContext)) + try: + raise RuntimeError("error") + except RuntimeError as err: + attributes = {"has_additional_attributes": True} + timestamp = 1604238587112021089 + span.record_exception(err, attributes, timestamp) + exception_event = span.events[0] + self.assertEqual("exception", exception_event.name) + self.assertEqual( + "error", exception_event.attributes["exception.message"] + ) + self.assertEqual( + "RuntimeError", exception_event.attributes["exception.type"] + ) + self.assertIn( + "RuntimeError: error", + exception_event.attributes["exception.stacktrace"], + ) + self.assertIn( + "has_additional_attributes", exception_event.attributes, + ) + self.assertEqual( + True, exception_event.attributes["has_additional_attributes"], + ) + self.assertEqual( + 1604238587112021089, exception_event.timestamp, + ) + def test_record_exception_context_manager(self): try: with self.tracer.start_as_current_span("span") as span: From de6ab4d5620a9472a731a2d9a1983a927b528dc4 Mon Sep 17 00:00:00 2001 From: Baymax Date: Mon, 2 Nov 2020 10:50:14 +0530 Subject: [PATCH 2/4] Update opentelemetry-api/CHANGELOG.md Co-authored-by: Leighton Chen --- opentelemetry-api/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/CHANGELOG.md b/opentelemetry-api/CHANGELOG.md index 9e91c377d98..7a969047f24 100644 --- a/opentelemetry-api/CHANGELOG.md +++ b/opentelemetry-api/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- Updating `Span.record_exception` to adhere to specs +- Updating `Span.record_exception` to adhere to specs ([#1314](https://github.com/open-telemetry/opentelemetry-python/pull/1314)) - Updating status codes to adhere to specs ([#1282](https://github.com/open-telemetry/opentelemetry-python/pull/1282)) ## Version 0.14b0 From 326f45a0eca0733d45b78306e0889dce1b539ebf Mon Sep 17 00:00:00 2001 From: Baymax Date: Mon, 2 Nov 2020 20:30:02 +0530 Subject: [PATCH 3/4] Update opentelemetry-api/CHANGELOG.md Co-authored-by: Leighton Chen --- opentelemetry-api/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/CHANGELOG.md b/opentelemetry-api/CHANGELOG.md index 4ec29f0296a..872a26215f4 100644 --- a/opentelemetry-api/CHANGELOG.md +++ b/opentelemetry-api/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- Updating `Span.record_exception` to adhere to specs ([#1314](https://github.com/open-telemetry/opentelemetry-python/pull/1314)) +- Add optional parameter to `record_exception` method ([#1314](https://github.com/open-telemetry/opentelemetry-python/pull/1314)) - Updating status codes to adhere to specs ([#1282](https://github.com/open-telemetry/opentelemetry-python/pull/1282)) ## Version 0.14b0 From eb5cca99e56bde125b6dd35bd2a80904390718af Mon Sep 17 00:00:00 2001 From: Baymax Date: Mon, 2 Nov 2020 20:30:14 +0530 Subject: [PATCH 4/4] Update opentelemetry-sdk/CHANGELOG.md Co-authored-by: Leighton Chen --- opentelemetry-sdk/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index f61d38914fd..33caa513343 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- Updating `Span.record_exception` to adhere to specs +- Add optional parameter to `record_exception` method ([#1314](https://github.com/open-telemetry/opentelemetry-python/pull/1314)) - Make `SpanProcessor.on_start` accept parent Context ([#1251](https://github.com/open-telemetry/opentelemetry-python/pull/1251)) - Fix b3 propagator entrypoint