Skip to content

Commit 9642b6d

Browse files
authored
Django: Record status, http.status_code and event on exception (open-telemetry#1257)
1 parent 937863f commit 9642b6d

File tree

3 files changed

+26
-17
lines changed

3 files changed

+26
-17
lines changed

instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class _DjangoMiddleware(MiddlewareMixin):
6060
)
6161
_environ_token = "opentelemetry-instrumentor-django.token"
6262
_environ_span_key = "opentelemetry-instrumentor-django.span_key"
63+
_environ_exception_key = "opentelemetry-instrumentor-django.exception_key"
6364

6465
_excluded_urls = Configuration().DJANGO_EXCLUDED_URLS or []
6566
if _excluded_urls:
@@ -177,22 +178,11 @@ def process_view(self, request, view_func, *args, **kwargs):
177178
span.set_attribute("http.route", route)
178179

179180
def process_exception(self, request, exception):
180-
# Django can call this method and process_response later. In order
181-
# to avoid __exit__ and detach from being called twice then, the
182-
# respective keys are being removed here.
183181
if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
184182
return
185183

186184
if self._environ_activation_key in request.META.keys():
187-
request.META[self._environ_activation_key].__exit__(
188-
type(exception),
189-
exception,
190-
getattr(exception, "__traceback__", None),
191-
)
192-
request.META.pop(self._environ_activation_key)
193-
194-
detach(request.environ[self._environ_token])
195-
request.META.pop(self._environ_token, None)
185+
request.META[self._environ_exception_key] = exception
196186

197187
def process_response(self, request, response):
198188
if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
@@ -213,9 +203,17 @@ def process_response(self, request, response):
213203
)
214204
request.META.pop(self._environ_span_key)
215205

216-
request.META[self._environ_activation_key].__exit__(
217-
None, None, None
218-
)
206+
exception = request.META.pop(self._environ_exception_key, None)
207+
if exception:
208+
request.META[self._environ_activation_key].__exit__(
209+
type(exception),
210+
exception,
211+
getattr(exception, "__traceback__", None),
212+
)
213+
else:
214+
request.META[self._environ_activation_key].__exit__(
215+
None, None, None
216+
)
219217
request.META.pop(self._environ_activation_key)
220218

221219
if self._environ_token in request.META.keys():
@@ -231,5 +229,4 @@ def process_response(self, request, response):
231229
)
232230
except Exception as ex: # pylint: disable=W0703
233231
_logger.warning("Error recording duration metrics: %s", ex)
234-
235232
return response

instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,21 +194,30 @@ def test_error(self):
194194
)
195195
self.assertEqual(span.kind, SpanKind.SERVER)
196196
self.assertEqual(
197-
span.status.canonical_code, StatusCanonicalCode.UNKNOWN
197+
span.status.canonical_code, StatusCanonicalCode.INTERNAL
198198
)
199199
self.assertEqual(span.attributes["http.method"], "GET")
200200
self.assertEqual(
201201
span.attributes["http.url"], "http://testserver/error/"
202202
)
203203
self.assertEqual(span.attributes["http.route"], "^error/")
204204
self.assertEqual(span.attributes["http.scheme"], "http")
205+
self.assertEqual(span.attributes["http.status_code"], 500)
205206
self.assertIsNotNone(_django_instrumentor.meter)
206207
self.assertEqual(len(_django_instrumentor.meter.metrics), 1)
208+
209+
self.assertEqual(len(span.events), 1)
210+
event = span.events[0]
211+
self.assertEqual(event.name, "exception")
212+
self.assertEqual(event.attributes["exception.type"], "ValueError")
213+
self.assertEqual(event.attributes["exception.message"], "error")
214+
207215
recorder = _django_instrumentor.meter.metrics.pop()
208216
match_key = get_dict_as_key(
209217
{
210218
"http.flavor": "1.1",
211219
"http.method": "GET",
220+
"http.status_code": "500",
212221
"http.url": "http://testserver/error/",
213222
}
214223
)

instrumentation/opentelemetry-instrumentation-flask/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Unreleased
44

5+
- Record span status and http.status_code attribute on exception
6+
([#1257](https://github.com/open-telemetry/opentelemetry-python/pull/1257))
7+
58
## Version 0.13b0
69

710
Released 2020-09-17

0 commit comments

Comments
 (0)