Repository navigation
feat(error_tracking): add native alert, destination, and thread models - #90533
Conversation
🤖 CI report
|
| File | Patch | Uncovered changed lines |
|---|---|---|
products/error_tracking/backend/logic/lifecycle_events.py |
90.0% | 49–50, 69, 136, 139 |
products/error_tracking/backend/models.py |
98.0% | 939 |
🤖 Agents: add a test covering the lines above, or note why under "How did you test this code?". Machine-readable gap list: the patch-coverage artifact on this run (gh run download 33572026404 -n patch-coverage), or the coverage-data block at the end of this comment.
Per-product line coverage (touched products)
| Product | Coverage | Lines |
|---|---|---|
platform_features |
██░░░░░░░░░░░░░░░░░░ 12.1% |
7 / 58 |
warehouse_sources_queue |
██████░░░░░░░░░░░░░░ 29.4% |
91 / 309 |
demo |
███████████░░░░░░░░░ 56.9% |
1,518 / 2,666 |
autoresearch |
████████████░░░░░░░░ 62.5% |
5 / 8 |
data_tools |
█████████████░░░░░░░ 66.2% |
90 / 136 |
ai_gateway |
███████████████░░░░░ 75.0% |
9 / 12 |
batch_exports |
████████████████░░░░ 79.8% |
19,679 / 24,669 |
apm |
█████████████████░░░ 83.3% |
1,234 / 1,481 |
signals |
█████████████████░░░ 84.6% |
33,335 / 39,413 |
cdp |
█████████████████░░░ 85.2% |
4,310 / 5,056 |
wizard |
█████████████████░░░ 86.7% |
1,090 / 1,257 |
data_modeling |
█████████████████░░░ 86.7% |
9,654 / 11,133 |
notebooks |
██████████████████░░ 87.7% |
11,202 / 12,770 |
product_tours |
██████████████████░░ 87.9% |
1,303 / 1,482 |
data_warehouse |
██████████████████░░ 88.6% |
12,782 / 14,425 |
engineering_analytics |
██████████████████░░ 89.0% |
7,707 / 8,656 |
cohorts |
██████████████████░░ 89.1% |
7,370 / 8,273 |
business_knowledge |
██████████████████░░ 89.1% |
4,440 / 4,984 |
dashboards |
██████████████████░░ 89.6% |
6,807 / 7,598 |
tasks |
██████████████████░░ 90.0% |
63,212 / 70,240 |
streamlit_apps |
██████████████████░░ 90.2% |
2,500 / 2,773 |
exports |
██████████████████░░ 90.5% |
8,717 / 9,637 |
links |
██████████████████░░ 90.6% |
183 / 202 |
managed_warehouse |
██████████████████░░ 90.7% |
8,563 / 9,436 |
alerts |
██████████████████░░ 90.9% |
5,182 / 5,700 |
visual_review |
██████████████████░░ 90.9% |
6,880 / 7,567 |
conversations |
██████████████████░░ 91.0% |
20,910 / 22,973 |
canvas |
██████████████████░░ 91.0% |
4,913 / 5,397 |
mcp_analytics |
██████████████████░░ 91.2% |
4,374 / 4,795 |
error_tracking |
██████████████████░░ 91.6% |
12,905 / 14,090 |
notifications |
██████████████████░░ 92.2% |
1,101 / 1,194 |
early_access_features |
███████████████████░ 92.5% |
1,323 / 1,430 |
managed_migrations |
███████████████████░ 92.6% |
1,556 / 1,681 |
slack_app |
███████████████████░ 92.8% |
12,354 / 13,315 |
stamphog |
███████████████████░ 92.9% |
5,775 / 6,216 |
web_analytics |
███████████████████░ 93.1% |
18,597 / 19,966 |
context_layer |
███████████████████░ 93.3% |
2,573 / 2,758 |
surveys |
███████████████████░ 93.4% |
6,051 / 6,482 |
reminders |
███████████████████░ 93.4% |
468 / 501 |
mcp_store |
███████████████████░ 93.4% |
7,609 / 8,144 |
posthog_ai |
███████████████████░ 93.5% |
1,372 / 1,468 |
marketing_analytics |
███████████████████░ 93.5% |
17,322 / 18,526 |
ai_observability |
███████████████████░ 93.7% |
17,988 / 19,194 |
approvals |
███████████████████░ 93.7% |
3,492 / 3,725 |
billing_alerts |
███████████████████░ 93.9% |
2,078 / 2,212 |
workflows |
███████████████████░ 94.1% |
11,042 / 11,739 |
legal_documents |
███████████████████░ 94.1% |
1,970 / 2,093 |
review_hog |
███████████████████░ 94.3% |
9,982 / 10,583 |
endpoints |
███████████████████░ 94.4% |
8,866 / 9,396 |
tracing |
███████████████████░ 94.4% |
2,678 / 2,837 |
access_control |
███████████████████░ 94.9% |
5,828 / 6,139 |
customer_analytics |
███████████████████░ 95.0% |
17,702 / 18,639 |
annotations |
███████████████████░ 95.2% |
795 / 835 |
product_analytics |
███████████████████░ 95.3% |
19,292 / 20,252 |
replay_vision |
███████████████████░ 95.4% |
26,086 / 27,355 |
experiments |
███████████████████░ 95.5% |
29,271 / 30,660 |
actions |
███████████████████░ 95.5% |
706 / 739 |
skills |
███████████████████░ 95.6% |
5,403 / 5,651 |
messaging |
███████████████████░ 95.8% |
3,636 / 3,795 |
logs |
███████████████████░ 95.9% |
13,495 / 14,077 |
growth |
███████████████████░ 95.9% |
7,644 / 7,969 |
feature_flags |
███████████████████░ 96.1% |
19,585 / 20,382 |
revenue_analytics |
███████████████████░ 96.3% |
1,841 / 1,911 |
user_interviews |
███████████████████░ 96.5% |
2,639 / 2,735 |
warehouse_sources |
███████████████████░ 97.2% |
406,037 / 417,835 |
data_quality |
███████████████████░ 97.5% |
4,103 / 4,209 |
analytics_platform |
████████████████████ 98.1% |
2,286 / 2,330 |
data_catalog |
████████████████████ 98.3% |
3,234 / 3,289 |
metrics |
████████████████████ 98.3% |
3,505 / 3,564 |
pulse |
████████████████████ 98.4% |
2,017 / 2,049 |
live_debugger |
████████████████████ 99.2% |
613 / 618 |
field_notes |
████████████████████ 99.4% |
158 / 159 |
Report-only. Patch coverage = changed backend lines covered vs origin/master. Sorted lowest first.
Known gaps: lines covered only by Temporal tests show as uncovered; core line numbers may drift if master changed the same file.
⚠️ Django migration SQL — 1 new migration to review
We've detected new migrations on this PR. Review the SQL output for each migration:
products/error_tracking/backend/migrations/0031_errortrackingalert_errortrackingalertdestination_and_more.py
BEGIN;
--
-- Create model ErrorTrackingAlert
--
CREATE TABLE "posthog_errortrackingalert" ("id" uuid NOT NULL PRIMARY KEY, "name" text NOT NULL, "enabled" boolean NOT NULL, "triggers" jsonb NOT NULL, "filters" jsonb NOT NULL, "throttle_seconds" integer NOT NULL CHECK ("throttle_seconds" >= 0), "created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL, "created_by_id" integer NULL, "team_id" integer NOT NULL);
--
-- Create model ErrorTrackingAlertDestination
--
CREATE TABLE "posthog_errortrackingalertdestination" ("id" uuid NOT NULL PRIMARY KEY, "channel_type" text NOT NULL, "config" jsonb NOT NULL, "created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL, "alert_id" uuid NOT NULL, "integration_id" integer NULL, "team_id" integer NOT NULL);
--
-- Create model ErrorTrackingAlertThread
--
CREATE TABLE "posthog_errortrackingalertthread" ("id" uuid NOT NULL PRIMARY KEY, "external_ref" jsonb NOT NULL, "root_headline" text NOT NULL, "delivered_notification_ids" jsonb NOT NULL, "created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL, "alert_id" uuid NOT NULL, "destination_id" uuid NOT NULL, "issue_id" uuid NOT NULL, "team_id" integer NOT NULL);
--
-- Create index idx_et_alert_team_enabled on field(s) team, enabled of model errortrackingalert
--
CREATE INDEX "idx_et_alert_team_enabled" ON "posthog_errortrackingalert" ("team_id", "enabled");
--
-- Create constraint unique_error_tracking_alert_thread on model errortrackingalertthread
--
ALTER TABLE "posthog_errortrackingalertthread" ADD CONSTRAINT "unique_error_tracking_alert_thread" UNIQUE ("alert_id", "issue_id", "destination_id");
CREATE INDEX "posthog_errortrackingalert_created_by_id_f9169e7e" ON "posthog_errortrackingalert" ("created_by_id");
CREATE INDEX "posthog_errortrackingalert_team_id_237990b2" ON "posthog_errortrackingalert" ("team_id");
ALTER TABLE "posthog_errortrackingalertdestination" ADD CONSTRAINT "posthog_errortrackin_alert_id_dad2e16d_fk_posthog_e" FOREIGN KEY ("alert_id") REFERENCES "posthog_errortrackingalert" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "posthog_errortrackingalertdestination" ADD CONSTRAINT "posthog_errortrackin_integration_id_bf6616c9_fk_posthog_i" FOREIGN KEY ("integration_id") REFERENCES "posthog_integration" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "posthog_errortrackingalertdestination_alert_id_dad2e16d" ON "posthog_errortrackingalertdestination" ("alert_id");
CREATE INDEX "posthog_errortrackingalertdestination_integration_id_bf6616c9" ON "posthog_errortrackingalertdestination" ("integration_id");
CREATE INDEX "posthog_errortrackingalertdestination_team_id_03f2a5ee" ON "posthog_errortrackingalertdestination" ("team_id");
ALTER TABLE "posthog_errortrackingalertthread" ADD CONSTRAINT "posthog_errortrackin_alert_id_94f1ed46_fk_posthog_e" FOREIGN KEY ("alert_id") REFERENCES "posthog_errortrackingalert" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "posthog_errortrackingalertthread" ADD CONSTRAINT "posthog_errortrackin_destination_id_98175bc9_fk_posthog_e" FOREIGN KEY ("destination_id") REFERENCES "posthog_errortrackingalertdestination" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "posthog_errortrackingalertthread" ADD CONSTRAINT "posthog_errortrackin_issue_id_4e6ea270_fk_posthog_e" FOREIGN KEY ("issue_id") REFERENCES "posthog_errortrackingissue" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "posthog_errortrackingalertthread_alert_id_94f1ed46" ON "posthog_errortrackingalertthread" ("alert_id");
CREATE INDEX "posthog_errortrackingalertthread_destination_id_98175bc9" ON "posthog_errortrackingalertthread" ("destination_id");
CREATE INDEX "posthog_errortrackingalertthread_issue_id_4e6ea270" ON "posthog_errortrackingalertthread" ("issue_id");
CREATE INDEX "posthog_errortrackingalertthread_team_id_dd7e50a8" ON "posthog_errortrackingalertthread" ("team_id");
COMMIT;Last updated: 2026-09-01 23:42 UTC (7bf3f70)
✅ Django migration risk — migration analysis complete
We've analyzed your migrations for potential risks.
Summary: 1 Safe | 0 Needs Review | 0 Blocked
✅ Safe
Brief or no lock, backwards compatible
error_tracking.0031_errortrackingalert_errortrackingalertdestination_and_more
└─ #1 ✅ CreateModel
Creating new table is safe
model: ErrorTrackingAlert
└─ #2 ✅ CreateModel
Creating new table is safe
model: ErrorTrackingAlertDestination
└─ #3 ✅ CreateModel
Creating new table is safe
model: ErrorTrackingAlertThread
│
└──> ℹ️ INFO:
ℹ️ Skipped operations on newly created tables (empty tables
don't cause lock contention).
Last updated: 2026-09-01 23:43 UTC (7bf3f70)
5aec700 to
244c3c1
Compare
244c3c1 to
3b493a1
Compare
|
Reviews (1): Last reviewed commit: "fix(error_tracking): suppress tuple-retu..." | Re-trigger Greptile |
2a2bbb8 to
5a458ff
Compare
| ("name", models.TextField()), | ||
| ("enabled", models.BooleanField(default=True)), | ||
| ("triggers", models.JSONField(default=list)), | ||
| ("filters", models.JSONField(blank=True, default=dict)), |
There was a problem hiding this comment.
I am wondering if we should split issue filters from event filters
There was a problem hiding this comment.
hmmmmm good q, it's technically the same shape as the hog function filter, I was thinking it's simpler initially, we can discuss this maybe with the actual filter implementation in the later PR (we can also present them as split in the UI since it's a json field)
There was a problem hiding this comment.
y I think we can just split them on the UI
| external_ref = models.JSONField(default=dict, blank=True) | ||
| # The root message's headline. It is the thread's identity: status transitions | ||
| # edit the root in place but never change the headline. | ||
| root_headline = models.TextField(blank=True, default="") |
There was a problem hiding this comment.
Any reason we need to store this ? 🤔
There was a problem hiding this comment.
this is technically just extra safety, for dedup, since slack messages can't really be deduplicated, if we post the message but the workflow dies, it'll double post
5a458ff to
c5e5042
Compare
The alert, destination, and thread models add reverse accessors to Team, User, and Integration; the cross-boundary reverse-accessor ratchet forbids new ones. Nothing reads them, so related_name='+' seals all five. The unmerged 0031 migration is updated in place.
|
😎 Stack merged successfully - details. |
Problem
An error tracking "alert" today is a
HogFunctionwith special filter strings: there is no entity to hold state, throttling, delivery history, or destinations. The native stateful alerting RFC introduces a first-class alert configuration; this layer adds its storage.Stacked on #90532. No behavior changes — nothing reads or writes these tables yet.
Changes
ErrorTrackingAlertmodel: name, enabled,triggerslist (thread openers), hog-function-shapedfilterswith embedded bytecode, per-issue openerthrottle_seconds, creator.ErrorTrackingAlertDestinationmodel: one delivery target per row (channel type via callable choices — onlyslackexists today — integration FK, config).ErrorTrackingAlertThreadmodel: runtime state for one (alert, issue, destination) conversation — provider message ref, root headline, delivered notification ids — with a unique constraint as the delivery concurrency primitive.posthog_team,posthog_user) usedb_constraint=Falseso creates stay lock-free.How did you test this code?
sqlmigrateoutput verified: threeCREATE TABLEs plus indexes/constraints, no hot-tableALTERs;makemigrations --checkreports no drift.Automatic notifications
Docs update
None — schema only, behind later layers.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
cat/alerting-v2-poc) into the RFC's three-table shape: destinations split from the alert so filters evaluate once and fan out, and the thread row gained the destination FK plus root headline per RFC review.