diff --git a/.changelog/5821.changed b/.changelog/5821.changed new file mode 100644 index 0000000000..e6291b0e32 --- /dev/null +++ b/.changelog/5821.changed @@ -0,0 +1 @@ +`opentelemetry-sdk`: The experimental `Tracer._start_typed_span` and `Tracer._start_as_current_typed_span` no longer record exception span events by default; pass `record_exception=True` to opt in diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index b108edc271..592e263365 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -431,9 +431,9 @@ def _start_typed_span( a case-sensitive ASCII string of at most 255 characters that starts with a letter, followed by letters, digits, ``_``, ``.``, ``-`` or ``/``. Not validated by the API. - kwargs: Options from :class:`_SpanOptions`, with the same defaults - as :meth:`start_span`. Implementations ignore options they - don't know. + kwargs: Options from :class:`_SpanOptions`. ``record_exception`` + defaults to ``False``, ``set_status_on_exception`` to ``True``. + Implementations ignore options they don't know. The default implementation calls :meth:`start_span` without ``type_``. Implementations that support span type should override this method. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 6394d044cf..28202f204f 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -85,7 +85,7 @@ _KNOWN_SPAN_OPTIONS = frozenset(("record_exception", "set_status_on_exception")) # (record_exception, set_status_on_exception) when no options are passed -_DEFAULT_SPAN_OPTIONS = (True, True) +_DEFAULT_SPAN_OPTIONS = (False, True) def _is_valid_span_type(span_type: object) -> bool: @@ -106,9 +106,10 @@ def _read_span_options(kwargs: Mapping[str, Any]) -> tuple[bool, bool]: "Ignoring unknown span start options: %s", sorted(kwargs.keys() - _KNOWN_SPAN_OPTIONS), ) - # Both default to True. Only an explicit False turns them off, other values are ignored. + # record_exception defaults to False, set_status_on_exception to True. + # Non-bool values fall back to the default. return ( - kwargs.get("record_exception") is not False, + kwargs.get("record_exception") is True, kwargs.get("set_status_on_exception") is not False, ) diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index b41b4f8c94..6cba30b402 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -885,25 +885,25 @@ def test_typed_span_exception_handling_defaults(self): with tracer._start_as_current_typed_span("s", type_="a") as span: raise DummyError() self.assertIs(span.status.status_code, StatusCode.ERROR) - self.assertEqual(span.events[0].name, "exception") + self.assertEqual(len(span.events), 0) def test_typed_span_exception_flags_ignore_non_bool(self): tracer = new_tracer() with self.assertRaises(DummyError): - with tracer._start_as_current_typed_span("s", record_exception="no", set_status_on_exception=0) as span: + with tracer._start_as_current_typed_span("s", record_exception="yes", set_status_on_exception=0) as span: raise DummyError() self.assertIs(span.status.status_code, StatusCode.ERROR) - self.assertEqual(span.events[0].name, "exception") + self.assertEqual(len(span.events), 0) def test_typed_span_exception_handling_from_kwargs(self): tracer = new_tracer() with self.assertRaises(DummyError): with tracer._start_as_current_typed_span( - "s", type_="a", record_exception=False, set_status_on_exception=False + "s", type_="a", record_exception=True, set_status_on_exception=False ) as span: raise DummyError() self.assertIs(span.status.status_code, StatusCode.UNSET) - self.assertEqual(len(span.events), 0) + self.assertEqual(span.events[0].name, "exception") def test_typed_span_unknown_options_warn(self): tracer = new_tracer()