mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-08-02 19:47:17 +08:00
[opentelemetry-instrumentation-django] Handle exceptions from request/response hooks (#2153)
This commit is contained in:
@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Unreleased
|
||||
|
||||
- `opentelemetry-instrumentation-django` Handle exceptions from request/response hooks
|
||||
([#2153](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2153))
|
||||
- `opentelemetry-instrumentation-asyncio` instrumented `asyncio.wait_for` properly raises `asyncio.TimeoutError` as expected
|
||||
([#2637](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2637))
|
||||
- `opentelemetry-instrumentation-aws-lambda` Bugfix: AWS Lambda event source key incorrect for SNS in instrumentation library.
|
||||
@ -151,7 +153,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
([#2136](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2136))
|
||||
- `opentelemetry-resource-detector-azure` Suppress instrumentation for `urllib` call
|
||||
([#2178](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2178))
|
||||
- AwsLambdaInstrumentor handles and re-raises function exception ([#2245](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2245))
|
||||
- AwsLambdaInstrumentor handles and re-raises function exception
|
||||
([#2245](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2245))
|
||||
|
||||
### Added
|
||||
|
||||
|
@ -187,6 +187,7 @@ class _DjangoMiddleware(MiddlewareMixin):
|
||||
return request.method
|
||||
|
||||
# pylint: disable=too-many-locals
|
||||
# pylint: disable=too-many-branches
|
||||
def process_request(self, request):
|
||||
# request.META is a dictionary containing all available HTTP headers
|
||||
# Read more about request.META here:
|
||||
@ -286,9 +287,14 @@ class _DjangoMiddleware(MiddlewareMixin):
|
||||
request.META[self._environ_token] = token
|
||||
|
||||
if _DjangoMiddleware._otel_request_hook:
|
||||
_DjangoMiddleware._otel_request_hook( # pylint: disable=not-callable
|
||||
span, request
|
||||
)
|
||||
try:
|
||||
_DjangoMiddleware._otel_request_hook( # pylint: disable=not-callable
|
||||
span, request
|
||||
)
|
||||
except Exception: # pylint: disable=broad-exception-caught
|
||||
# Raising an exception here would leak the request span since process_response
|
||||
# would not be called. Log the exception instead.
|
||||
_logger.exception("Exception raised by request_hook")
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def process_view(self, request, view_func, *args, **kwargs):
|
||||
@ -385,10 +391,14 @@ class _DjangoMiddleware(MiddlewareMixin):
|
||||
|
||||
# record any exceptions raised while processing the request
|
||||
exception = request.META.pop(self._environ_exception_key, None)
|
||||
|
||||
if _DjangoMiddleware._otel_response_hook:
|
||||
_DjangoMiddleware._otel_response_hook( # pylint: disable=not-callable
|
||||
span, request, response
|
||||
)
|
||||
try:
|
||||
_DjangoMiddleware._otel_response_hook( # pylint: disable=not-callable
|
||||
span, request, response
|
||||
)
|
||||
except Exception: # pylint: disable=broad-exception-caught
|
||||
_logger.exception("Exception raised by response_hook")
|
||||
|
||||
if exception:
|
||||
activation.__exit__(
|
||||
|
@ -392,6 +392,32 @@ class TestMiddleware(WsgiTestBase):
|
||||
self.assertIsInstance(response_hook_args[2], HttpResponse)
|
||||
self.assertEqual(response_hook_args[2], response)
|
||||
|
||||
def test_request_hook_exception(self):
|
||||
def request_hook(span, request):
|
||||
# pylint: disable=broad-exception-raised
|
||||
raise Exception("request hook exception")
|
||||
|
||||
_DjangoMiddleware._otel_request_hook = request_hook
|
||||
Client().get("/span_name/1234/")
|
||||
_DjangoMiddleware._otel_request_hook = None
|
||||
|
||||
# ensure that span ended
|
||||
finished_spans = self.memory_exporter.get_finished_spans()
|
||||
self.assertEqual(len(finished_spans), 1)
|
||||
|
||||
def test_response_hook_exception(self):
|
||||
def response_hook(span, request, response):
|
||||
# pylint: disable=broad-exception-raised
|
||||
raise Exception("response hook exception")
|
||||
|
||||
_DjangoMiddleware._otel_response_hook = response_hook
|
||||
Client().get("/span_name/1234/")
|
||||
_DjangoMiddleware._otel_response_hook = None
|
||||
|
||||
# ensure that span ended
|
||||
finished_spans = self.memory_exporter.get_finished_spans()
|
||||
self.assertEqual(len(finished_spans), 1)
|
||||
|
||||
def test_trace_parent(self):
|
||||
id_generator = RandomIdGenerator()
|
||||
trace_id = format_trace_id(id_generator.generate_trace_id())
|
||||
|
Reference in New Issue
Block a user