diff --git a/opentelemetry-api/CHANGELOG.md b/opentelemetry-api/CHANGELOG.md index 3f4ed4f0298..80549373127 100644 --- a/opentelemetry-api/CHANGELOG.md +++ b/opentelemetry-api/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Add optional parameter to `record_exception` method ([#1314](https://github.com/open-telemetry/opentelemetry-python/pull/1314)) + ## Version 0.15b0 Released 2020-11-02 diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index fc635bc2392..f1790c0a584 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Add optional parameter to `record_exception` method ([#1314](https://github.com/open-telemetry/opentelemetry-python/pull/1314)) + ## Version 0.15b0 Released 2020-11-02 diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index ab90c9316cd..6b99888a461 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -694,14 +694,15 @@ def record_exception( # 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: