From 6b8d912e1ad5c1685edd850f66322f5ff4a38702 Mon Sep 17 00:00:00 2001 From: Klaas van Schelven Date: Fri, 25 Jul 2025 20:51:52 +0200 Subject: [PATCH] Store remote_addr on the event Fix #165 --- events/migrations/0023_event_remote_addr.py | 16 ++++++++++++++++ events/models.py | 6 ++++++ ingest/views.py | 6 ++++++ issues/views.py | 1 + 4 files changed, 29 insertions(+) create mode 100644 events/migrations/0023_event_remote_addr.py diff --git a/events/migrations/0023_event_remote_addr.py b/events/migrations/0023_event_remote_addr.py new file mode 100644 index 0000000..ab256bf --- /dev/null +++ b/events/migrations/0023_event_remote_addr.py @@ -0,0 +1,16 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0022_alter_event_project'), + ] + + operations = [ + migrations.AddField( + model_name='event', + name='remote_addr', + field=models.GenericIPAddressField(blank=True, default=None, null=True), + ), + ] diff --git a/events/models.py b/events/models.py index 011971d..e06115c 100644 --- a/events/models.py +++ b/events/models.py @@ -52,6 +52,7 @@ class Event(models.Model): ingested_at = models.DateTimeField(blank=False, null=False) digested_at = models.DateTimeField(db_index=True, blank=False, null=False) + remote_addr = models.GenericIPAddressField(blank=True, null=True, default=None) issue = models.ForeignKey("issues.Issue", blank=False, null=False, on_delete=models.DO_NOTHING) grouping = models.ForeignKey("issues.Grouping", blank=False, null=False, on_delete=models.DO_NOTHING) @@ -237,6 +238,11 @@ class Event(models.Model): debug_info=event_metadata["debug_info"][:255], + # just getting from the dict would be more precise, since we always add this info, but doing the .get() + # allows for backwards compatability (digesting events for which the info was not added on-ingest) so + # we'll take the defensive approach "for now" (until most everyone is on >= 1.7.4) + remote_addr=event_metadata.get("remote_addr"), + digest_order=digest_order, irrelevance_for_retention=irrelevance_for_retention, diff --git a/ingest/views.py b/ingest/views.py index c8d0562..0601208 100644 --- a/ingest/views.py +++ b/ingest/views.py @@ -171,11 +171,17 @@ class BaseIngestAPIView(View): # Meta means: not part of the event data. Basically: information that is available at the time of ingestion, and # that must be passed to digest() in a serializable form. debug_info = request.META.get("HTTP_X_BUGSINK_DEBUGINFO", "") + + # .get(..) -- don't want to crash on this and it's non-trivial to find a source that tells me with certainty + # that the REMOTE_ADDR is always in request.META (it probably is in practice) + remote_addr = request.META.get("REMOTE_ADDR") + return { "event_id": event_id, "project_id": project.id, "ingested_at": format_timestamp(ingested_at), "debug_info": debug_info, + "remote_addr": remote_addr, } @classmethod diff --git a/issues/views.py b/issues/views.py index 5d19031..990793a 100644 --- a/issues/views.py +++ b/issues/views.py @@ -608,6 +608,7 @@ def issue_event_details(request, issue, event_pk=None, digest_order=None, nav=No ("ingested at", _date_with_milis_html(event.ingested_at)), ("digested at", _date_with_milis_html(event.digested_at)), ("digest order", event.digest_order), + ("remote_addr", event.remote_addr), ] logentry_info = []