mirror of
https://github.com/jlengrand/bugsink.git
synced 2026-03-10 08:01:17 +00:00
Show Browser and OS info, and Contexts more generally
This commit is contained in:
45
events/ua_stuff.py
Normal file
45
events/ua_stuff.py
Normal 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
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
|
||||
@@ -12,3 +12,4 @@ python-dateutil
|
||||
whitenoise
|
||||
requests # for sentry-sdk-extensions, which is loaded in non-dev setup too
|
||||
monofy
|
||||
user_agents
|
||||
|
||||
Reference in New Issue
Block a user