diff --git a/events/templates/events/event_stacktrace.txt b/events/templates/events/event_stacktrace.txt new file mode 100644 index 0000000..bba8b77 --- /dev/null +++ b/events/templates/events/event_stacktrace.txt @@ -0,0 +1,6 @@ +{% autoescape off %}Traceback (most recent call last):{% for exception in exceptions %}{% for frame in exception.stacktrace.frames %} + File {{ frame.filename }}, line {{ frame.lineno }}{% if frame.function %}, in {{ frame.function }}{% endif %} + {{ frame.context_line.strip }}{% endfor %}{% if not forloop.last %} + +During handling of the above exception another exception occurred or was intentionally reraised:{% endif %} +{% endfor %}{% endautoescape %} diff --git a/events/tests.py b/events/tests.py index b34060e..88feb79 100644 --- a/events/tests.py +++ b/events/tests.py @@ -29,3 +29,8 @@ class ViewTests(TestCase): self.assertEqual(response.status_code, 200) self.assertEqual(response['Content-Type'], 'application/json') self.assertTrue("platform" in response.json()) + + def test_event_plaintext(self): + response = self.client.get(f"/events/event/{self.event.pk}/plain/") + self.assertEqual(response.status_code, 200) + self.assertEqual(response['Content-Type'], 'text/plain') diff --git a/events/urls.py b/events/urls.py index 13f57bc..3d9c169 100644 --- a/events/urls.py +++ b/events/urls.py @@ -1,10 +1,11 @@ from django.urls import path -from .views import event_download +from .views import event_download, event_plaintext urlpatterns = [ # path('event//', event_detail), perhaps should become a redirect to issue/.../event now? path('event//raw/', event_download, kwargs={"as_attachment": False}), path('event//download/', event_download, kwargs={"as_attachment": True}), + path('event//plain/', event_plaintext), ] diff --git a/events/views.py b/events/views.py index cefae91..a9fc466 100644 --- a/events/views.py +++ b/events/views.py @@ -1,5 +1,7 @@ +import json from django.http import HttpResponse from django.utils.http import content_disposition_header +from django.shortcuts import render from bugsink.decorators import event_membership_required @@ -10,3 +12,14 @@ def event_download(request, event, as_attachment=False): result["Content-Disposition"] = content_disposition_header( as_attachment=as_attachment, filename=event.id.hex + ".json") return result + + +@event_membership_required +def event_plaintext(request, event): + parsed_data = json.loads(event.data) + exceptions = parsed_data["exception"]["values"] if "exception" in parsed_data else None + + return render(request, "events/event_stacktrace.txt", { + "event": event, + "exceptions": exceptions, + }, content_type="text/plain") diff --git a/issues/templates/issues/base.html b/issues/templates/issues/base.html index 995f8bf..a06a2b4 100644 --- a/issues/templates/issues/base.html +++ b/issues/templates/issues/base.html @@ -122,7 +122,8 @@ {% if is_event_page %} | Event Admin | Download - | Raw + | JSON + | Plain {% endif %} {# bottom nav bar #}