Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#4475](https://github.com/open-telemetry/opentelemetry-python/pull/4475))
- Improve performance of baggage operations
([#4466](https://github.com/open-telemetry/opentelemetry-python/pull/4466))
- api: Revert record `BaseException` change in `trace_api.use_span()`
([#4494](https://github.com/open-telemetry/opentelemetry-python/pull/4494))

## Version 1.31.0/0.52b0 (2025-03-12)

Expand All @@ -19,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add type annotations to context's attach & detach
([#4346](https://github.com/open-telemetry/opentelemetry-python/pull/4346))
- Fix OTLP encoders missing instrumentation scope schema url and attributes
([#4359](https://github.com/open-telemetry/opentelemetry-python/pull/4359))
([#4359](https://github.com/open-telemetry/opentelemetry-python/pull/4359))
- prometheus-exporter: fix labels out of place for data points with different
attribute sets
([#4413](https://github.com/open-telemetry/opentelemetry-python/pull/4413))
Expand Down
5 changes: 4 additions & 1 deletion opentelemetry-api/src/opentelemetry/trace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,10 @@ def use_span(
finally:
context_api.detach(token)

except BaseException as exc: # pylint: disable=broad-exception-caught
# Record only exceptions that inherit Exception class but not BaseException, because
# classes that directly inherit BaseException are not technically errors, e.g. GeneratorExit.
# See https://github.com/open-telemetry/opentelemetry-python/issues/4484
except Exception as exc: # pylint: disable=broad-exception-caught
if isinstance(span, Span) and span.is_recording():
# Record the exception as an event
if record_exception:
Expand Down
59 changes: 44 additions & 15 deletions opentelemetry-api/tests/trace/test_globals.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest
from unittest.mock import Mock, patch

Expand All @@ -13,7 +27,12 @@ class SpanTest(trace.NonRecordingSpan):
recorded_status = Status(status_code=StatusCode.UNSET)

def set_status(self, status, description=None):
self.recorded_status = status
if isinstance(status, Status):
self.recorded_status = status
else:
self.recorded_status = Status(
status_code=status, description=description
)

def end(self, end_time=None):
self.has_ended = True
Expand Down Expand Up @@ -133,18 +152,6 @@ class TestUseSpanException(Exception):

self.assertEqual(test_span.recorded_exception, exception)

def test_use_span_base_exception(self):
class TestUseSpanBaseException(BaseException):
pass

test_span = SpanTest(trace.INVALID_SPAN_CONTEXT)
exception = TestUseSpanBaseException("test exception")
with self.assertRaises(TestUseSpanBaseException):
with trace.use_span(test_span):
raise exception

self.assertEqual(test_span.recorded_exception, exception)

def test_use_span_set_status(self):
class TestUseSpanException(Exception):
pass
Expand All @@ -155,10 +162,32 @@ class TestUseSpanException(Exception):
raise TestUseSpanException("test error")

self.assertEqual(
test_span.recorded_status.status_code, # type: ignore[reportAttributeAccessIssue]
test_span.recorded_status.status_code,
StatusCode.ERROR,
)
self.assertEqual(
test_span.recorded_status.description, # type: ignore[reportAttributeAccessIssue]
test_span.recorded_status.description,
"TestUseSpanException: test error",
)

def test_use_span_base_exceptions(self):
base_exception_classes = [
BaseException,
GeneratorExit,
SystemExit,
KeyboardInterrupt,
]

for exc_cls in base_exception_classes:
with self.subTest(exc=exc_cls.__name__):
test_span = SpanTest(trace.INVALID_SPAN_CONTEXT)

with self.assertRaises(exc_cls):
with trace.use_span(test_span):
raise exc_cls()

self.assertEqual(
test_span.recorded_status.status_code,
StatusCode.UNSET,
)
self.assertIsNone(test_span.recorded_status.description)