From 1e36cca869707db533697293ac6bd526a2c0035a Mon Sep 17 00:00:00 2001 From: Hang Cheng Date: Thu, 9 Feb 2023 10:40:55 -0800 Subject: [PATCH] Fix issue with Flask instrumentation when a request spawn children threads and copie the request context --- CHANGELOG.md | 2 +- .../opentelemetry/instrumentation/flask/__init__.py | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba513aebfa..cb15eaacf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#1618](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1618)) ### Fixed - +- Fix Flask instrumentation to only close the span if it was created by the same thread. `ValueError: generator already executing` ([#1653](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/1653)) - Fix TortoiseORM instrumentation `AttributeError: type object 'Config' has no attribute 'title'` ([#1575](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1575)) - Fix SQLAlchemy uninstrumentation diff --git a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py index 922c5e0b41..ab970e9054 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -238,10 +238,10 @@ def response_hook(span: Span, status: str, response_headers: List): API --- """ - from logging import getLogger from time import time_ns from timeit import default_timer +from threading import get_ident from typing import Collection import flask @@ -397,7 +397,10 @@ def _before_request(): activation = trace.use_span(span, end_on_exit=True) activation.__enter__() # pylint: disable=E1101 - flask_request_environ[_ENVIRON_ACTIVATION_KEY] = activation + flask_request_environ[_ENVIRON_ACTIVATION_KEY] = ( + get_ident(), + activation, + ) flask_request_environ[_ENVIRON_SPAN_KEY] = span flask_request_environ[_ENVIRON_TOKEN] = token @@ -436,8 +439,10 @@ def _teardown_request(exc): if excluded_urls and excluded_urls.url_disabled(flask.request.url): return - activation = flask.request.environ.get(_ENVIRON_ACTIVATION_KEY) - if not activation: + thread_id, activation = flask.request.environ.get( + _ENVIRON_ACTIVATION_KEY + ) + if not activation or thread_id != get_ident(): # This request didn't start a span, maybe because it was created in # a way that doesn't run `before_request`, like when it is created # with `app.test_request_context`.