Show Browser and OS info, and Contexts more generally

This commit is contained in:
Klaas van Schelven
2024-09-16 16:55:34 +02:00
parent 937ffea15c
commit 278630b529
4 changed files with 80 additions and 20 deletions

45
events/ua_stuff.py Normal file
View File

@@ -0,0 +1,45 @@
from user_agents import parse as ua_parse
def enrich_contexts_with_ua(parsed_data):
# GlitchTip has some mechanism to get "synthetic" (i.e. not present in the original, UA-header derived) info into
# first the contexts, which is then propagated (with a whole bunch of other info from contexts) to the tags. Both
# these steps happen on-digest.
#
# I'm not sure what I want myself... on the one hand I'm not a fan of this kind of magic. On the other: if the data
# usually lives in the "context" (e.g. in the JS world), you might as well synthesize it into that location when iit
# is not in that location in the data (but is available through other means).
#
# my set of samples has very little data for contexts, so it's hard to get a feel for it. I imagine that having this
# info available in tags can be useful for searching, or for getting a quick feel of the data (tags show up in the
# RHS of various screens). But again: too little data to tell yet. Add to that that I'm much less inclined than my
# competitors to give OS/browser info the main stage (icons? yuck!). So we'll just parse it, put it "somewhere", and
# look at it again "later".
contexts = parsed_data.get("contexts", {})
ua_string = (parsed_data.get("request", {}).get("headers", {})).get("User-Agent")
if ua_string is None:
return contexts
user_agent = ua_parse(ua_string)
if "browser" not in contexts:
contexts["browser"] = {
"name": user_agent.browser.family,
"version": user_agent.browser.version_string,
}
if "os" not in contexts:
contexts["os"] = {
"name": user_agent.os.family,
"version": user_agent.os.version_string,
}
if "device" not in contexts:
contexts["device"] = {
"family": user_agent.device.family,
"model": user_agent.device.model,
"brand": user_agent.device.brand,
}
return contexts

View File

@@ -73,7 +73,6 @@
{% endif %}
{% if parsed_data.request %}
<h1 class="text-2xl font-bold mt-4"><a name="request">Request</a></h1>
<div class="mb-6">
@@ -91,15 +90,12 @@
{% if parsed_data.request.headers %}
<h3 class="font-bold mt-2">REQUEST HEADERS</h3>
<div>
{# TODO the user's browser and OS can be deduced from the request headers. Perhaps that info should go near the headers #}
{% for key, value in parsed_data.request.headers.items %}
<div class="flex {% if forloop.first %}border-slate-300 border-t-2{% endif %} border-dotted">
<div class="w-1/4 {% if not forloop.last %}border-b-2 border-dotted border-slate-300{% endif %}">{{ key }}</div>
<div class="w-3/4 {% if not forloop.last %} border-b-2 border-dotted border-slate-300{% endif %} font-mono">{{ value }}</div>
</div>
{% endfor %}
</div>
{% endif %} {# end if parsed_data.request.headers #}
@@ -121,6 +117,34 @@
{% endif %}
{% if contexts %}
<h1 class="text-2xl font-bold mt-4"><a name="runtime">Contexts</a></h1>
<div class="mb-6">
{% for context_key, context in contexts|items %}
<h3 class="font-bold mt-2">{{ context_key|upper }}</h3>
{% for key, value in context|items %}
<div class="flex {% if forloop.first %}border-slate-300 border-t-2{% endif %}">
<div class="w-1/4 {% if not forloop.last %}border-b-2 border-dotted border-slate-300{% endif %}">{{ key }}</div>
<div class="w-3/4 {% if not forloop.last %} border-b-2 border-dotted border-slate-300{% endif %} font-mono">{{ value }}</div>
</div>
{% endfor %}
{% endfor %}
</div>
{% endif %}
{% comment %}
earlier I said about "tracing": I don't believe much in this whole business of tracing, so I'm not going to display the associated data either
now that we "just display all contexts" this is no longer true... some of the feeling persists, but I don't think
that I'm so much anti-tracing that I want specifically exclude it from a generic loop. The data's there, let's just
show it (in a non-special way)
{% endcomment %}
{% comment %}
commented-out like it's 1999.
this is now part of the more general "contexts" handling right above this section.
the fact that we commented-out rather than clobbered reveals a small amount of doubt about whether this is the way.
{% if parsed_data.contexts.runtime %}
{# sentry gives this prime location (even a picture)... but why... it's kinda obvious what you're working in right? Maybe I could put it at the top of the modules list instead. And check if there's any other relevant info in that runtime context (RTFM) #}
@@ -135,6 +159,7 @@
{% endfor %}
</div>
{% endif %}
{% endcomment %}
{% if parsed_data.modules %}
<h1 class="text-2xl font-bold mt-4"><a name="modules">Modules</a></h1>
@@ -177,21 +202,5 @@
</div>
{% endif %}
{% comment %}
{# I don't believe much in this whole business of tracing, so I'm not going to display the associated data either #}
{% if parsed_data.contexts.trace %}
<h1 class="text-2xl font-bold mt-4"><a name="trace">Trace</a></h1>
<div class="mb-6">
{% for key, value in parsed_data.contexts.trace|items %}
<div class="flex {% if forloop.first %}border-slate-300 border-t-2{% endif %}">
<div class="w-1/4 {% if not forloop.last %}border-b-2 border-dotted border-slate-300{% endif %}">{{ key }}</div>
<div class="w-3/4 {% if not forloop.last %} border-b-2 border-dotted border-slate-300{% endif %} font-mono">{{ value }}</div>
</div>
{% endfor %}
</div>
{% endif %}
{% endcomment %}
{% endblock %}

View File

@@ -16,6 +16,8 @@ from bugsink.transaction import durable_atomic
from bugsink.period_utils import add_periods_to_datetime
from events.models import Event
from events.ua_stuff import enrich_contexts_with_ua
from compat.timestamp import format_timestamp
from projects.models import ProjectMembership
@@ -409,6 +411,8 @@ def issue_event_details(request, issue, event_pk=None, digest_order=None, nav=No
([("environment", parsed_data["environment"])] if "environment" in parsed_data else []) + \
([("server_name", parsed_data["server_name"])] if "server_name" in parsed_data else [])
contexts = enrich_contexts_with_ua(parsed_data)
return render(request, "issues/event_details.html", {
"tab": "event-details",
"this_view": "event_details",
@@ -419,6 +423,7 @@ def issue_event_details(request, issue, event_pk=None, digest_order=None, nav=No
"parsed_data": parsed_data,
"key_info": key_info,
"deployment_info": deployment_info,
"contexts": contexts,
"mute_options": GLOBAL_MUTE_OPTIONS,
})

View File

@@ -12,3 +12,4 @@ python-dateutil
whitenoise
requests # for sentry-sdk-extensions, which is loaded in non-dev setup too
monofy
user_agents