diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f252e8290..af4d00eb6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Fixed + +- `opentelemetry-instrumentation`: Avoid calls to `context.detach` with `None` token. + ([#3673](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3673)) + ## Version 1.36.0/0.57b0 (2025-07-29) ### Fixed diff --git a/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/callback_decorator.py b/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/callback_decorator.py index f10415bdd2..07842851f8 100644 --- a/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/callback_decorator.py +++ b/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/callback_decorator.py @@ -53,7 +53,8 @@ async def decorated(message: AbstractIncomingMessage): with trace.use_span(span, end_on_exit=True): return_value = await callback(message) finally: - context.detach(token) + if token: + context.detach(token) return return_value return decorated diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py index bee39d13b0..c84839deb7 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py @@ -273,7 +273,8 @@ def create_trace_config( def _end_trace(trace_config_ctx: types.SimpleNamespace): elapsed_time = max(default_timer() - trace_config_ctx.start_time, 0) - context_api.detach(trace_config_ctx.token) + if trace_config_ctx.token: + context_api.detach(trace_config_ctx.token) trace_config_ctx.span.end() if trace_config_ctx.duration_histogram_old is not None: diff --git a/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/utils.py b/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/utils.py index 6d8ef6d222..36bfb29efa 100644 --- a/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/utils.py +++ b/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/utils.py @@ -490,7 +490,8 @@ async def _create_consumer_span( await async_consume_hook(span, record, args, kwargs) except Exception as hook_exception: # pylint: disable=W0703 _LOG.exception(hook_exception) - context.detach(token) + if token: + context.detach(token) return span diff --git a/instrumentation/opentelemetry-instrumentation-aws-lambda/src/opentelemetry/instrumentation/aws_lambda/__init__.py b/instrumentation/opentelemetry-instrumentation-aws-lambda/src/opentelemetry/instrumentation/aws_lambda/__init__.py index 827f3b620b..ed40d4c1c9 100644 --- a/instrumentation/opentelemetry-instrumentation-aws-lambda/src/opentelemetry/instrumentation/aws_lambda/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aws-lambda/src/opentelemetry/instrumentation/aws_lambda/__init__.py @@ -384,7 +384,8 @@ def _instrumented_lambda_handler_call( # noqa pylint: disable=too-many-branches result.get("statusCode"), ) finally: - context_api.detach(token) + if token: + context_api.detach(token) now = time.time() _tracer_provider = tracer_provider or get_tracer_provider() diff --git a/instrumentation/opentelemetry-instrumentation-boto3sqs/src/opentelemetry/instrumentation/boto3sqs/__init__.py b/instrumentation/opentelemetry-instrumentation-boto3sqs/src/opentelemetry/instrumentation/boto3sqs/__init__.py index 83e5ed70bc..028009afd6 100644 --- a/instrumentation/opentelemetry-instrumentation-boto3sqs/src/opentelemetry/instrumentation/boto3sqs/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-boto3sqs/src/opentelemetry/instrumentation/boto3sqs/__init__.py @@ -180,8 +180,9 @@ def _safe_end_processing_span(receipt_handle: str) -> None: Boto3SQSInstrumentor.current_span_related_to_token == started_span ): - context.detach(Boto3SQSInstrumentor.current_context_token) - Boto3SQSInstrumentor.current_context_token = None + if Boto3SQSInstrumentor.current_context_token: + context.detach(Boto3SQSInstrumentor.current_context_token) + Boto3SQSInstrumentor.current_context_token = None started_span.end() @staticmethod diff --git a/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/utils.py b/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/utils.py index 60dc13e675..fd8b72848d 100644 --- a/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/utils.py +++ b/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/utils.py @@ -82,7 +82,8 @@ def set(self, carrier: textmap.CarrierT, key: str, value: str) -> None: def _end_current_consume_span(instance): - context.detach(instance._current_context_token) + if instance._current_context_token: + context.detach(instance._current_context_token) instance._current_context_token = None instance._current_consume_span.end() instance._current_consume_span = None diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py index 1a7d6ccc8b..1d744656de 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_server.py @@ -209,7 +209,8 @@ def _set_remote_context(self, servicer_context): try: yield finally: - detach(token) + if token: + detach(token) else: yield diff --git a/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/utils.py b/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/utils.py index 3f9bd6f39c..d428487599 100644 --- a/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/utils.py +++ b/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/utils.py @@ -196,7 +196,8 @@ def _create_consumer_span( consume_hook(span, record, args, kwargs) except Exception as hook_exception: # pylint: disable=W0703 _LOG.exception(hook_exception) - context.detach(token) + if token: + context.detach(token) def _wrap_next( diff --git a/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/utils.py b/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/utils.py index 2b4d1204ea..2e1353d2b2 100644 --- a/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/utils.py +++ b/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/utils.py @@ -80,7 +80,8 @@ def decorated_callback( _LOG.exception(hook_exception) retval = callback(channel, method, properties, body) finally: - context.detach(token) + if token: + context.detach(token) return retval return decorated_callback @@ -252,7 +253,8 @@ def popleft(self, *args, **kwargs): operation=MessagingOperationValues.RECEIVE, ) try: - context.detach(message_ctx_token) + if message_ctx_token: + context.detach(message_ctx_token) self._self_active_token = context.attach( trace.set_span_in_context(span) ) diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py index d5bf5db7fd..e38932e28d 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py @@ -207,7 +207,8 @@ def _suppress_instrumentation(*keys: str) -> Generator[None]: try: yield finally: - context.detach(token) + if token: + context.detach(token) @contextmanager diff --git a/util/opentelemetry-util-http/src/opentelemetry/util/http/httplib.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/httplib.py index 4f5cba957c..c969710cd3 100644 --- a/util/opentelemetry-util-http/src/opentelemetry/util/http/httplib.py +++ b/util/opentelemetry-util-http/src/opentelemetry/util/http/httplib.py @@ -179,7 +179,8 @@ def set_ip_on_next_http_connection(span: Span): try: yield finally: - context.detach(token) + if token: + context.detach(token) else: spans = state["need_ip"] spans.append(span)