Repository: scoutapp/scout_apm_python
Pull request #384 (2019-11-21 15:09:47)

Tag Django 5XX responses as errors
Ref #383.


Patch:
diff --git a/src/scout_apm/django/middleware.py b/src/scout_apm/django/middleware.py
index e10ef30..02d25f5 100644
--- a/src/scout_apm/django/middleware.py
+++ b/src/scout_apm/django/middleware.py
@@ -179,7 +179,10 @@ class ViewTimingMiddleware(object):
         # process_view
         tracked_request.start_span(operation="Unknown", should_capture_backtrace=False)
         try:
-            return self.get_response(request)
+            response = self.get_response(request)
+            if 500 <= response.status_code <= 599:
+                tracked_request.tag("error", "true")
+            return response
         finally:
             tracked_request.stop_span()
 
@@ -239,6 +242,8 @@ class OldStyleMiddlewareTimingMiddleware(object):
         # i.e. that custom instrumentation within the application is not
         # causing errors
         tracked_request = getattr(request, "_scout_tracked_request", None)
+        if 500 <= response.status_code <= 599:
+            tracked_request.tag("error", "true")
         if tracked_request is not None:
             tracked_request.stop_span()
         return response


Test patch:
diff --git a/tests/integration/django_app.py b/tests/integration/django_app.py
index 728fbf3..577db62 100644
--- a/tests/integration/django_app.py
+++ b/tests/integration/django_app.py
@@ -79,6 +79,10 @@ def crash(request):
     raise ValueError("BØØM!")  # non-ASCII
 
 
+def return_error(request):
+    return HttpResponse("Something went wrong", status=503)
+
+
 class CbvView(View):
     def get(self, request):
         return HttpResponse("Hello getter")
@@ -187,6 +191,7 @@ def urlpatterns():
             path("", home),
             path("hello/", hello),
             path("crash/", crash),
+            path("return-error/", return_error),
             path("cbv/", CbvView.as_view()),
             path("sql/", sql),
             path("sql-kwargs/", sql_kwargs),
@@ -206,6 +211,7 @@ def urlpatterns():
             url(r"^$", home),
             url(r"^hello/$", hello),
             url(r"^crash/$", crash),
+            url(r"^return-error/$", return_error),
             url(r"^cbv/$", CbvView.as_view()),
             url(r"^sql/$", sql),
             url(r"^sql-kwargs/$", sql_kwargs),
diff --git a/tests/integration/test_django.py b/tests/integration/test_django.py
index 657a88c..10cef4a 100644
--- a/tests/integration/test_django.py
+++ b/tests/integration/test_django.py
@@ -213,6 +213,21 @@ def test_server_error(tracked_requests):
     assert operations == expected_operations
 
 
+def test_return_error(tracked_requests):
+    with app_with_scout() as app:
+        response = TestApp(app).get("/return-error/", expect_errors=True)
+
+    assert response.status_int == 503
+    assert len(tracked_requests) == 1
+    tracked_request = tracked_requests[0]
+    assert tracked_request.tags["error"] == "true"
+    spans = tracked_requests[0].complete_spans
+    assert [s.operation for s in spans] == [
+        "Controller/tests.integration.django_app.return_error",
+        "Middleware",
+    ]
+
+
 def test_cbv(tracked_requests):
     with app_with_scout() as app:
         response = TestApp(app).get("/cbv/")