from __future__ import annotations import json import time from django.core.management.base import BaseCommand from core.models import ConversationEvent class Command(BaseCommand): help = "Quick non-mutating sanity check for recent canonical event writes." def add_arguments(self, parser): parser.add_argument("--minutes", type=int, default=120) parser.add_argument("--service", default="") parser.add_argument("--user-id", default="") parser.add_argument("--limit", type=int, default=200) parser.add_argument("--json", action="store_true", default=False) def handle(self, *args, **options): minutes = max(1, int(options.get("minutes") or 120)) service = str(options.get("service") or "").strip().lower() user_id = str(options.get("user_id") or "").strip() limit = max(1, int(options.get("limit") or 200)) as_json = bool(options.get("json")) cutoff_ts = int(time.time() * 1000) - (minutes * 60 * 1000) queryset = ConversationEvent.objects.filter(ts__gte=cutoff_ts).order_by("-ts") if service: queryset = queryset.filter(origin_transport=service) if user_id: queryset = queryset.filter(user_id=user_id) rows = list( queryset.values( "id", "user_id", "session_id", "ts", "event_type", "direction", "origin_transport", "trace_id", )[:limit] ) event_type_counts = {} for row in rows: key = str(row.get("event_type") or "") event_type_counts[key] = int(event_type_counts.get(key) or 0) + 1 payload = { "minutes": minutes, "service": service, "user_id": user_id, "count": len(rows), "event_type_counts": event_type_counts, "sample": rows[:25], } if as_json: self.stdout.write(json.dumps(payload, indent=2, sort_keys=True)) return self.stdout.write( f"event-ledger-smoke minutes={minutes} service={service or '-'} user={user_id or '-'} count={len(rows)}" ) self.stdout.write(f"event_type_counts={event_type_counts}")