Repository navigation
feat(error-tracking): add severity rules API - #86267
Conversation
|
😎 Merged successfully - details. |
🦔 Hogbox preview · ✅ ready▶ Open the preview
commit |
🤖 CI report
|
| File | Size | Δ vs base |
|---|---|---|
posthog-app/src/scenes/experiments/staff/ExperimentsStaffTools.js |
35.1 KiB | 🔺 +35.1 KiB (new) |
posthog-app/src/scenes/instance/QueryPerformance/QueryPerformance.js |
removed | 🟢 -35.1 KiB (-100.0%) |
posthog-app/_parent/products/customer_analytics/frontend/CustomerAnalyticsScene.js |
243.1 KiB | 🔺 +19.3 KiB (+8.6%) |
posthog-app/_parent/products/metrics/frontend/MetricsScene.js |
49.6 KiB | 🔺 +1.1 KiB (+2.3%) |
Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report
✅ Eager graph — within budget
How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.
| Root | Eager (shipped) | Δ vs base | Budget |
|---|---|---|---|
entry (logged-out pages, app bootstrap)src/index.tsx |
1.35 MiB · 22 files | 🔺 +122 B (+0.0%) | ███░░░░░░░ 30.0% of 4.51 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
8.61 MiB · 3,171 files | 🔺 +1.8 KiB (+0.0%) | █████████░ 88.6% of 9.71 MiB |
🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
Largest files eagerly shipped from src/index.tsx
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 789 B | src/scenes/ChunkLoadErrorBoundary.tsx |
| 762 B | src/index.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 304.7 KiB | ../node_modules/.pnpm/posthog-js@1.418.5/node_modules/posthog-js/dist/rrweb.js |
| 267.7 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 250.7 KiB | ../node_modules/.pnpm/posthog-js@1.418.5/node_modules/posthog-js/dist/module.js |
| 246.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 154.2 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 104.2 KiB | src/lib/api.ts |
| 95.1 KiB | ../packages/quill/packages/quill/dist/index.js |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Toolbar bundle — eager 2.24 MiB within budget
What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.
| Metric | Size | Δ vs base | Budget |
|---|---|---|---|
| Eager (shipped) entry + static imports |
2.24 MiB · 17 files | 🔺 +1.3 KiB (+0.1%) | ████░░░░░░ 39.1% of 5.72 MiB |
| Deferred (lazy) | 2.09 MiB · 33 files | no change | n/a — loads on demand |
Loader dist/toolbar.js |
1.1 KiB | no change | █░░░░░░░░░ 5.8% of 19.5 KiB |
Largest eagerly-shipped chunks
| Size | File |
|---|---|
| 742.9 KiB | dist/toolbar/toolbar-app-AH5DY6W6.css |
| 574.5 KiB | dist/toolbar/chunk-chunk-A5VAW5JM.js |
| 484.6 KiB | dist/toolbar/chunk-chunk-DGW5M54M.js |
| 133.6 KiB | dist/toolbar/chunk-chunk-V54TQLLP.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-T5KY5WYR.js |
| 71.2 KiB | dist/toolbar/toolbar-app-GHWCOZJ7.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-27JL52RE.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-DTD25DJR.js |
| 20.9 KiB | dist/toolbar/chunk-chunk-NL5GOESK.js |
| 12.2 KiB | dist/toolbar/chunk-chunk-PIK3PADE.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — 🔺 +565.6 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1456.17 MiB · 🔺 +565.6 KiB (+0.0%)
ℹ️ MCP UI apps size — 33 app(s), 17649.2 KB JS
Built size of each MCP UI app (main.js + styles.css).
| App | JS | CSS |
|---|---|---|
| debug | 599.7 KB | 195.2 KB |
| action | 457.9 KB | 195.2 KB |
| action-list | 564.5 KB | 195.2 KB |
| cohort | 456.9 KB | 195.2 KB |
| cohort-list | 563.5 KB | 195.2 KB |
| email-template | 456.7 KB | 195.2 KB |
| error-details | 472.6 KB | 195.2 KB |
| error-issue | 457.6 KB | 195.2 KB |
| error-issue-list | 564.4 KB | 195.2 KB |
| experiment | 561.6 KB | 195.2 KB |
| experiment-list | 565.3 KB | 195.2 KB |
| experiment-results | 566.8 KB | 195.2 KB |
| feature-flag | 567.3 KB | 195.2 KB |
| feature-flag-list | 571.1 KB | 195.2 KB |
| feature-flag-testing | 461.1 KB | 195.2 KB |
| inline-scan | 457.4 KB | 195.2 KB |
| insight-actors | 562.3 KB | 195.2 KB |
| invite-email-preview | 456.1 KB | 195.2 KB |
| llm-costs | 559.6 KB | 195.2 KB |
| session-recording | 458.7 KB | 195.2 KB |
| survey | 458.5 KB | 195.2 KB |
| survey-global-stats | 562.4 KB | 195.2 KB |
| survey-list | 565.2 KB | 195.2 KB |
| survey-stats | 562.4 KB | 195.2 KB |
| trace-span | 457.3 KB | 195.2 KB |
| trace-span-list | 564.4 KB | 195.2 KB |
| vision-observation-list | 563.6 KB | 195.2 KB |
| workflow | 457.2 KB | 195.2 KB |
| workflow-list | 563.9 KB | 195.2 KB |
| loops-review | 461.5 KB | 195.2 KB |
| query-results | 753.5 KB | 195.2 KB |
| render-ui | 836.3 KB | 195.2 KB |
| visual-review-snapshots | 461.7 KB | 195.2 KB |
⚠️ Backend snapshots — 1 updated (1 modified, 0 added, 0 deleted)
Query snapshots: Backend query snapshots updated
Changes: 1 snapshots (1 modified, 0 added, 0 deleted)
What this means:
- Query snapshots have been automatically updated to match current output
- These changes reflect modifications to database queries or schema
Next steps:
- Review the query changes to ensure they're intentional
- If unexpected, investigate what caused the query to change
⚠️ Backend coverage — 95.0% of changed backend lines covered — 11 uncovered
🧪 Backend test coverage
Patch coverage — changed backend lines (products + core): ███████████████████░ 95.0% (259 / 270)
| File | Patch | Uncovered changed lines |
|---|---|---|
products/error_tracking/backend/presentation/views/severity_rules.py |
91.8% | 27, 126, 136–137, 139, 149, 177–178 |
products/error_tracking/backend/logic/rules.py |
95.7% | 184 |
products/error_tracking/backend/tests/api/test_severity_rules.py |
97.9% | 18–19 |
🤖 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 32379553857 -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 |
batch_exports |
████████░░░░░░░░░░░░ 37.9% |
8,916 / 23,524 |
demo |
███████████░░░░░░░░░ 56.9% |
1,516 / 2,666 |
data_tools |
█████████████░░░░░░░ 66.2% |
90 / 136 |
tasks |
██████████████░░░░░░ 69.7% |
41,278 / 59,213 |
ai_gateway |
███████████████░░░░░ 75.0% |
9 / 12 |
signals |
█████████████████░░░ 83.3% |
29,452 / 35,375 |
apm |
█████████████████░░░ 83.3% |
1,234 / 1,481 |
cdp |
█████████████████░░░ 84.4% |
3,968 / 4,703 |
actions |
█████████████████░░░ 86.6% |
717 / 828 |
wizard |
█████████████████░░░ 86.7% |
1,090 / 1,257 |
data_modeling |
█████████████████░░░ 86.9% |
9,644 / 11,092 |
notebooks |
█████████████████░░░ 87.2% |
8,553 / 9,812 |
cohorts |
██████████████████░░ 87.6% |
6,528 / 7,452 |
product_tours |
██████████████████░░ 87.9% |
1,303 / 1,482 |
data_warehouse |
██████████████████░░ 88.9% |
12,507 / 14,069 |
business_knowledge |
██████████████████░░ 89.0% |
4,385 / 4,929 |
exports |
██████████████████░░ 89.3% |
7,701 / 8,626 |
dashboards |
██████████████████░░ 89.4% |
6,248 / 6,987 |
engineering_analytics |
██████████████████░░ 89.5% |
6,828 / 7,632 |
visual_review |
██████████████████░░ 89.8% |
6,057 / 6,745 |
managed_warehouse |
██████████████████░░ 90.2% |
8,369 / 9,280 |
alerts |
██████████████████░░ 90.4% |
4,699 / 5,199 |
mcp_analytics |
██████████████████░░ 90.4% |
3,968 / 4,388 |
links |
██████████████████░░ 90.6% |
183 / 202 |
streamlit_apps |
██████████████████░░ 90.7% |
2,630 / 2,901 |
conversations |
██████████████████░░ 90.8% |
20,307 / 22,366 |
error_tracking |
██████████████████░░ 91.2% |
11,903 / 13,046 |
stamphog |
██████████████████░░ 91.5% |
5,332 / 5,826 |
canvas |
██████████████████░░ 91.9% |
4,401 / 4,788 |
early_access_features |
███████████████████░ 92.5% |
1,323 / 1,430 |
slack_app |
███████████████████░ 92.6% |
11,871 / 12,826 |
managed_migrations |
███████████████████░ 92.6% |
1,556 / 1,681 |
web_analytics |
███████████████████░ 92.8% |
16,515 / 17,804 |
notifications |
███████████████████░ 92.9% |
1,065 / 1,146 |
mcp_store |
███████████████████░ 93.1% |
7,411 / 7,957 |
surveys |
███████████████████░ 93.3% |
5,943 / 6,373 |
posthog_ai |
███████████████████░ 93.3% |
1,340 / 1,436 |
ai_observability |
███████████████████░ 93.4% |
16,976 / 18,180 |
reminders |
███████████████████░ 93.4% |
468 / 501 |
marketing_analytics |
███████████████████░ 93.4% |
16,638 / 17,806 |
approvals |
███████████████████░ 93.5% |
3,491 / 3,734 |
product_analytics |
███████████████████░ 93.7% |
7,352 / 7,843 |
billing_alerts |
███████████████████░ 93.9% |
2,047 / 2,181 |
legal_documents |
███████████████████░ 94.0% |
1,914 / 2,037 |
workflows |
███████████████████░ 94.1% |
9,425 / 10,019 |
endpoints |
███████████████████░ 94.3% |
8,814 / 9,349 |
review_hog |
███████████████████░ 94.3% |
9,962 / 10,562 |
tracing |
███████████████████░ 94.4% |
2,678 / 2,837 |
annotations |
███████████████████░ 95.1% |
732 / 770 |
skills |
███████████████████░ 95.2% |
4,698 / 4,935 |
experiments |
███████████████████░ 95.5% |
29,064 / 30,432 |
messaging |
███████████████████░ 95.7% |
3,545 / 3,704 |
logs |
███████████████████░ 95.7% |
13,012 / 13,591 |
replay_vision |
███████████████████░ 95.8% |
22,080 / 23,059 |
feature_flags |
███████████████████░ 96.0% |
19,078 / 19,877 |
customer_analytics |
███████████████████░ 96.0% |
14,604 / 15,213 |
revenue_analytics |
███████████████████░ 96.3% |
1,841 / 1,911 |
user_interviews |
███████████████████░ 96.5% |
2,639 / 2,735 |
data_quality |
███████████████████░ 96.5% |
2,688 / 2,785 |
growth |
███████████████████░ 96.7% |
6,505 / 6,729 |
access_control |
███████████████████░ 96.7% |
873 / 903 |
warehouse_sources |
████████████████████ 97.6% |
423,299 / 433,618 |
analytics_platform |
████████████████████ 98.1% |
2,286 / 2,330 |
data_catalog |
████████████████████ 98.2% |
3,181 / 3,240 |
metrics |
████████████████████ 98.3% |
2,542 / 2,587 |
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/0027_add_severity_rules.py
BEGIN;
--
-- Create model ErrorTrackingSeverityRule
--
CREATE TABLE "posthog_errortrackingseverityrule" ("id" uuid NOT NULL PRIMARY KEY, "filters" jsonb NOT NULL, "bytecode" jsonb NOT NULL, "severity" text NOT NULL, "order_key" integer NOT NULL, "disabled_data" jsonb NULL, "created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL, "team_id" integer NOT NULL);
CREATE INDEX "posthog_errortrackingseverityrule_team_id_a2efedac" ON "posthog_errortrackingseverityrule" ("team_id");
COMMIT;Last updated: 2026-08-20 14:24 UTC (6a21c98)
✅ 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.0027_add_severity_rules
└─ #1 ✅ CreateModel
Creating new table is safe
model: ErrorTrackingSeverityRule
│
└──> ℹ️ INFO:
ℹ️ Skipped operations on newly created tables (empty tables
don't cause lock contention).
Last updated: 2026-08-20 14:24 UTC (6a21c98)
ℹ️ ClickHouse migration SQL — 24 migration(s)
ClickHouse migration SQL per cloud environment
- unset
0232_warpstream_ingestion_kafka_engines— operations list is empty under this environment0234_warpstream_ingestion_warnings_kafka_engine— operations list is empty under this environment0238_align_ws_events_kafka_mv_with_msk— operations list is empty under this environment0241_warpstream_ingestion_warnings_kafka_engine— operations list is empty under this environment0242_warpstream_person_distinct_id_overrides_kafka_engine— operations list is empty under this environment0245_warpstream_cohort_membership_kafka_engine— operations list is empty under this environment0246_warpstream_replay_kafka_engines— operations list is empty under this environment0247_warpstream_shared_kafka_engines— operations list is empty under this environment0248_drop_msk_kafka_engines_with_ws_equivalents— operations list is empty under this environment0249_property_values_kafka_named_collection— operations list is empty under this environment0250_property_values_lowercase_text_index— operations list is empty under this environment0253_drop_dead_msk_kafka_tables— operations list is empty under this environment0257_property_values_count_column— operations list is empty under this environment0268_property_values_kafka_num_consumers— operations list is empty under this environment0270_property_values_drop_mv_length_filter— operations list is empty under this environment- all
DROP TABLE IF EXISTS precalculated_events_mv
DROP TABLE IF EXISTS precalculated_events_ws_mv
DROP TABLE IF EXISTS kafka_precalculated_events
DROP TABLE IF EXISTS kafka_precalculated_events_ws
CREATE TABLE IF NOT EXISTS kafka_precalculated_events ( team_id Int64, date Nullable(Date), distinct_id String, person_id UUID, condition String, uuid UUID, source String ) ENGINE = Kafka(msk_cluster, kafka_topic_list = 'clickhouse_prefiltered_events', kafka_group_name = 'clickhouse_prefiltered_events', kafka_format = 'JSONEachRow') SETTINGS kafka_max_block_size = 1000000, kafka_poll_max_batch_size = 100000, kafka_poll_timeout_ms = 1000, kafka_flush_interval_ms = 7500, kafka_skip_broken_messages = 100, kafka_num_consumers = 1
CREATE MATERIALIZED VIEW IF NOT EXISTS precalculated_events_mv TO writable_precalculated_events AS SELECT team_id, ifNull(date, toDate(_timestamp)) AS date, distinct_id, person_id, condition, uuid, source, _timestamp, _offset, _partition FROM kafka_precalculated_events
DROP TABLE IF EXISTS session_replay_features_mv
DROP TABLE IF EXISTS kafka_session_replay_features
DROP TABLE IF EXISTS session_replay_features_ws_mv
DROP TABLE IF EXISTS kafka_session_replay_features_ws
ALTER TABLE sharded_session_replay_features DROP COLUMN IF EXISTS unique_url_count, DROP COLUMN IF EXISTS unique_click_target_count, ADD COLUMN IF NOT EXISTS scroll_to_top_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS backspace_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS long_idle_gap_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS login_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS signup_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS checkout_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS cart_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS billing_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS settings_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS account_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS error_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS not_found_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS admin_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS dashboard_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS onboarding_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS cancel_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS refund_path_visit_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS console_warn_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS network_4xx_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS network_5xx_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS mutation_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS viewport_resize_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS touch_event_count SimpleAggregateFunction(sum, Int64), ADD COLUMN IF NOT EXISTS unique_url_count AggregateFunction(uniqCombined(12), String), ADD COLUMN IF NOT EXISTS unique_click_target_count AggregateFunction(uniqCombined(12), Int64), ADD COLUMN IF NOT EXISTS unique_form_field_count AggregateFunction(uniqCombined(12), Int64), ADD COLUMN IF NOT EXISTS selection_copy_count SimpleAggregateFunction(sum, Int64)
DROP TABLE IF EXISTS session_replay_features
CREATE TABLE IF NOT EXISTS session_replay_features ( session_id VARCHAR, team_id Int64, distinct_id VARCHAR, min_first_timestamp SimpleAggregateFunction(min, DateTime64(6, 'UTC')), max_last_timestamp SimpleAggregateFunction(max, DateTime64(6, 'UTC')), event_count SimpleAggregateFunction(sum, Int64), mouse_position_count SimpleAggregateFunction(sum, Int64), mouse_sum_x SimpleAggregateFunction(sum, Float64), mouse_sum_x_squared SimpleAggregateFunction(sum, Float64), mouse_sum_y SimpleAggregateFunction(sum, Float64), mouse_sum_y_squared SimpleAggregateFunction(sum, Float64), mouse_distance_traveled SimpleAggregateFunction(sum, Float64), mouse_direction_change_count SimpleAggregateFunction(sum, Int64), mouse_velocity_sum SimpleAggregateFunction(sum, Float64), mouse_velocity_sum_of_squares SimpleAggregateFunction(sum, Float64), mouse_velocity_count SimpleAggregateFunction(sum, Int64), scroll_event_count SimpleAggregateFunction(sum, Int64), total_scroll_magnitude SimpleAggregateFunction(sum, Float64), scroll_direction_reversal_count SimpleAggregateFunction(sum, Int64), rapid_scroll_reversal_count SimpleAggregateFunction(sum, Int64), scroll_to_top_count SimpleAggregateFunction(sum, Int64), click_count SimpleAggregateFunction(sum, Int64), keypress_count SimpleAggregateFunction(sum, Int64), mouse_activity_count SimpleAggregateFunction(sum, Int64), rage_click_count SimpleAggregateFunction(sum, Int64), dead_click_count SimpleAggregateFunction(sum, Int64), backspace_count SimpleAggregateFunction(sum, Int64), inter_action_gap_count SimpleAggregateFunction(sum, Int64), inter_action_gap_sum_ms SimpleAggregateFunction(sum, Float64), inter_action_gap_sum_of_squares_ms SimpleAggregateFunction(sum, Float64), max_idle_gap_ms SimpleAggregateFunction(max, Float64), long_idle_gap_count SimpleAggregateFunction(sum, Int64), quick_back_count SimpleAggregateFunction(sum, Int64), page_visit_count SimpleAggregateFunction(sum, Int64), unique_url_count AggregateFunction(uniqCombined(12), String), login_path_visit_count SimpleAggregateFunction(sum, Int64), signup_path_visit_count SimpleAggregateFunction(sum, Int64), checkout_path_visit_count SimpleAggregateFunction(sum, Int64), cart_path_visit_count SimpleAggregateFunction(sum, Int64), billing_path_visit_count SimpleAggregateFunction(sum, Int64), settings_path_visit_count SimpleAggregateFunction(sum, Int64), account_path_visit_count SimpleAggregateFunction(sum, Int64), error_path_visit_count SimpleAggregateFunction(sum, Int64), not_found_path_visit_count SimpleAggregateFunction(sum, Int64), admin_path_visit_count SimpleAggregateFunction(sum, Int64), dashboard_path_visit_count SimpleAggregateFunction(sum, Int64), onboarding_path_visit_count SimpleAggregateFunction(sum, Int64), cancel_path_visit_count SimpleAggregateFunction(sum, Int64), refund_path_visit_count SimpleAggregateFunction(sum, Int64), console_error_count SimpleAggregateFunction(sum, Int64), console_error_after_click_count SimpleAggregateFunction(sum, Int64), console_warn_count SimpleAggregateFunction(sum, Int64), network_request_count SimpleAggregateFunction(sum, Int64), network_failed_request_count SimpleAggregateFunction(sum, Int64), network_4xx_count SimpleAggregateFunction(sum, Int64), network_5xx_count SimpleAggregateFunction(sum, Int64), network_request_duration_sum SimpleAggregateFunction(sum, Float64), network_request_duration_sum_of_squares SimpleAggregateFunction(sum, Float64), network_request_duration_count SimpleAggregateFunction(sum, Int64), mutation_count SimpleAggregateFunction(sum, Int64), viewport_resize_count SimpleAggregateFunction(sum, Int64), touch_event_count SimpleAggregateFunction(sum, Int64), max_scroll_y SimpleAggregateFunction(max, Float64), unique_click_target_count AggregateFunction(uniqCombined(12), Int64), unique_form_field_count AggregateFunction(uniqCombined(12), Int64), text_selection_count SimpleAggregateFunction(sum, Int64), selection_copy_count SimpleAggregateFunction(sum, Int64), is_deleted SimpleAggregateFunction(max, UInt8) DEFAULT 0 ) ENGINE = Distributed('posthog', 'posthog_test', 'sharded_session_replay_features', sipHash64(session_id))
DROP TABLE IF EXISTS writable_session_replay_features
CREATE TABLE IF NOT EXISTS writable_session_replay_features ( session_id VARCHAR, team_id Int64, distinct_id VARCHAR, min_first_timestamp SimpleAggregateFunction(min, DateTime64(6, 'UTC')), max_last_timestamp SimpleAggregateFunction(max, DateTime64(6, 'UTC')), event_count SimpleAggregateFunction(sum, Int64), mouse_position_count SimpleAggregateFunction(sum, Int64), mouse_sum_x SimpleAggregateFunction(sum, Float64), mouse_sum_x_squared SimpleAggregateFunction(sum, Float64), mouse_sum_y SimpleAggregateFunction(sum, Float64), mouse_sum_y_squared SimpleAggregateFunction(sum, Float64), mouse_distance_traveled SimpleAggregateFunction(sum, Float64), mouse_direction_change_count SimpleAggregateFunction(sum, Int64), mouse_velocity_sum SimpleAggregateFunction(sum, Float64), mouse_velocity_sum_of_squares SimpleAggregateFunction(sum, Float64), mouse_velocity_count SimpleAggregateFunction(sum, Int64), scroll_event_count SimpleAggregateFunction(sum, Int64), total_scroll_magnitude SimpleAggregateFunction(sum, Float64), scroll_direction_reversal_count SimpleAggregateFunction(sum, Int64), rapid_scroll_reversal_count SimpleAggregateFunction(sum, Int64), scroll_to_top_count SimpleAggregateFunction(sum, Int64), click_count SimpleAggregateFunction(sum, Int64), keypress_count SimpleAggregateFunction(sum, Int64), mouse_activity_count SimpleAggregateFunction(sum, Int64), rage_click_count SimpleAggregateFunction(sum, Int64), dead_click_count SimpleAggregateFunction(sum, Int64), backspace_count SimpleAggregateFunction(sum, Int64), inter_action_gap_count SimpleAggregateFunction(sum, Int64), inter_action_gap_sum_ms SimpleAggregateFunction(sum, Float64), inter_action_gap_sum_of_squares_ms SimpleAggregateFunction(sum, Float64), max_idle_gap_ms SimpleAggregateFunction(max, Float64), long_idle_gap_count SimpleAggregateFunction(sum, Int64), quick_back_count SimpleAggregateFunction(sum, Int64), page_visit_count SimpleAggregateFunction(sum, Int64), unique_url_count AggregateFunction(uniqCombined(12), String), login_path_visit_count SimpleAggregateFunction(sum, Int64), signup_path_visit_count SimpleAggregateFunction(sum, Int64), checkout_path_visit_count SimpleAggregateFunction(sum, Int64), cart_path_visit_count SimpleAggregateFunction(sum, Int64), billing_path_visit_count SimpleAggregateFunction(sum, Int64), settings_path_visit_count SimpleAggregateFunction(sum, Int64), account_path_visit_count SimpleAggregateFunction(sum, Int64), error_path_visit_count SimpleAggregateFunction(sum, Int64), not_found_path_visit_count SimpleAggregateFunction(sum, Int64), admin_path_visit_count SimpleAggregateFunction(sum, Int64), dashboard_path_visit_count SimpleAggregateFunction(sum, Int64), onboarding_path_visit_count SimpleAggregateFunction(sum, Int64), cancel_path_visit_count SimpleAggregateFunction(sum, Int64), refund_path_visit_count SimpleAggregateFunction(sum, Int64), console_error_count SimpleAggregateFunction(sum, Int64), console_error_after_click_count SimpleAggregateFunction(sum, Int64), console_warn_count SimpleAggregateFunction(sum, Int64), network_request_count SimpleAggregateFunction(sum, Int64), network_failed_request_count SimpleAggregateFunction(sum, Int64), network_4xx_count SimpleAggregateFunction(sum, Int64), network_5xx_count SimpleAggregateFunction(sum, Int64), network_request_duration_sum SimpleAggregateFunction(sum, Float64), network_request_duration_sum_of_squares SimpleAggregateFunction(sum, Float64), network_request_duration_count SimpleAggregateFunction(sum, Int64), mutation_count SimpleAggregateFunction(sum, Int64), viewport_resize_count SimpleAggregateFunction(sum, Int64), touch_event_count SimpleAggregateFunction(sum, Int64), max_scroll_y SimpleAggregateFunction(max, Float64), unique_click_target_count AggregateFunction(uniqCombined(12), Int64), unique_form_field_count AggregateFunction(uniqCombined(12), Int64), text_selection_count SimpleAggregateFunction(sum, Int64), selection_copy_count SimpleAggregateFunction(sum, Int64), is_deleted SimpleAggregateFunction(max, UInt8) DEFAULT 0 ) ENGINE = Distributed('posthog', 'posthog_test', 'sharded_session_replay_features', sipHash64(session_id))
CREATE TABLE IF NOT EXISTS kafka_session_replay_features ( session_id VARCHAR, team_id Int64, distinct_id VARCHAR, batch_id VARCHAR, first_timestamp DateTime64(6, 'UTC'), last_timestamp DateTime64(6, 'UTC'), event_count Int64, mouse_position_count Int64, mouse_sum_x Float64, mouse_sum_x_squared Float64, mouse_sum_y Float64, mouse_sum_y_squared Float64, mouse_distance_traveled Float64, mouse_direction_change_count Int64, mouse_velocity_sum Float64, mouse_velocity_sum_of_squares Float64, mouse_velocity_count Int64, scroll_event_count Int64, total_scroll_magnitude Float64, scroll_direction_reversal_count Int64, rapid_scroll_reversal_count Int64, scroll_to_top_count Int64, click_count Int64, keypress_count Int64, mouse_activity_count Int64, rage_click_count Int64, dead_click_count Int64, backspace_count Int64, inter_action_gap_count Int64, inter_action_gap_sum_ms Float64, inter_action_gap_sum_of_squares_ms Float64, max_idle_gap_ms Float64, long_idle_gap_count Int64, quick_back_count Int64, page_visit_count Int64, visited_urls Array(String), login_path_visit_count Int64, signup_path_visit_count Int64, checkout_path_visit_count Int64, cart_path_visit_count Int64, billing_path_visit_count Int64, settings_path_visit_count Int64, account_path_visit_count Int64, error_path_visit_count Int64, not_found_path_visit_count Int64, admin_path_visit_count Int64, dashboard_path_visit_count Int64, onboarding_path_visit_count Int64, cancel_path_visit_count Int64, refund_path_visit_count Int64, console_error_count Int64, console_error_after_click_count Int64, console_warn_count Int64, network_request_count Int64, network_failed_request_count Int64, network_4xx_count Int64, network_5xx_count Int64, network_request_duration_sum Float64, network_request_duration_sum_of_squares Float64, network_request_duration_count Int64, mutation_count Int64, viewport_resize_count Int64, touch_event_count Int64, max_scroll_y Float64, click_target_ids Array(Int64), form_field_ids Array(Int64), text_selection_count Int64, selection_copy_count Int64, is_deleted UInt8 ) ENGINE = Kafka(msk_cluster, kafka_topic_list = 'clickhouse_session_replay_features_test', kafka_group_name = 'group1', kafka_format = 'JSONEachRow')
CREATE MATERIALIZED VIEW IF NOT EXISTS session_replay_features_mv TO posthog_test.writable_session_replay_features AS SELECT session_id, team_id, any(distinct_id) as distinct_id, min(first_timestamp) AS min_first_timestamp, max(last_timestamp) AS max_last_timestamp, sum(event_count) as event_count, sum(mouse_position_count) as mouse_position_count, sum(mouse_sum_x) as mouse_sum_x, sum(mouse_sum_x_squared) as mouse_sum_x_squared, sum(mouse_sum_y) as mouse_sum_y, sum(mouse_sum_y_squared) as mouse_sum_y_squared, sum(mouse_distance_traveled) as mouse_distance_traveled, sum(mouse_direction_change_count) as mouse_direction_change_count, sum(mouse_velocity_sum) as mouse_velocity_sum, sum(mouse_velocity_sum_of_squares) as mouse_velocity_sum_of_squares, sum(mouse_velocity_count) as mouse_velocity_count, sum(scroll_event_count) as scroll_event_count, sum(total_scroll_magnitude) as total_scroll_magnitude, sum(scroll_direction_reversal_count) as scroll_direction_reversal_count, sum(rapid_scroll_reversal_count) as rapid_scroll_reversal_count, sum(scroll_to_top_count) as scroll_to_top_count, sum(click_count) as click_count, sum(keypress_count) as keypress_count, sum(mouse_activity_count) as mouse_activity_count, sum(rage_click_count) as rage_click_count, sum(dead_click_count) as dead_click_count, sum(backspace_count) as backspace_count, sum(inter_action_gap_count) as inter_action_gap_count, sum(inter_action_gap_sum_ms) as inter_action_gap_sum_ms, sum(inter_action_gap_sum_of_squares_ms) as inter_action_gap_sum_of_squares_ms, max(max_idle_gap_ms) as max_idle_gap_ms, sum(long_idle_gap_count) as long_idle_gap_count, sum(quick_back_count) as quick_back_count, sum(page_visit_count) as page_visit_count, uniqCombinedArrayState(12)(visited_urls) as unique_url_count, sum(login_path_visit_count) as login_path_visit_count, sum(signup_path_visit_count) as signup_path_visit_count, sum(checkout_path_visit_count) as checkout_path_visit_count, sum(cart_path_visit_count) as cart_path_visit_count, sum(billing_path_visit_count) as billing_path_visit_count, sum(settings_path_visit_count) as settings_path_visit_count, sum(account_path_visit_count) as account_path_visit_count, sum(error_path_visit_count) as error_path_visit_count, sum(not_found_path_visit_count) as not_found_path_visit_count, sum(admin_path_visit_count) as admin_path_visit_count, sum(dashboard_path_visit_count) as dashboard_path_visit_count, sum(onboarding_path_visit_count) as onboarding_path_visit_count, sum(cancel_path_visit_count) as cancel_path_visit_count, sum(refund_path_visit_count) as refund_path_visit_count, sum(console_error_count) as console_error_count, sum(console_error_after_click_count) as console_error_after_click_count, sum(console_warn_count) as console_warn_count, sum(network_request_count) as network_request_count, sum(network_failed_request_count) as network_failed_request_count, sum(network_4xx_count) as network_4xx_count, sum(network_5xx_count) as network_5xx_count, sum(network_request_duration_sum) as network_request_duration_sum, sum(network_request_duration_sum_of_squares) as network_request_duration_sum_of_squares, sum(network_request_duration_count) as network_request_duration_count, sum(mutation_count) as mutation_count, sum(viewport_resize_count) as viewport_resize_count, sum(touch_event_count) as touch_event_count, max(max_scroll_y) as max_scroll_y, uniqCombinedArrayState(12)(click_target_ids) as unique_click_target_count, uniqCombinedArrayState(12)(form_field_ids) as unique_form_field_count, sum(text_selection_count) as text_selection_count, sum(selection_copy_count) as selection_copy_count, max(is_deleted) as is_deleted FROM posthog_test.kafka_session_replay_features GROUP BY session_id, team_id
DROP TABLE IF EXISTS session_replay_events_mv
DROP TABLE IF EXISTS kafka_session_replay_events
DROP TABLE IF EXISTS session_replay_events_ws_mv
DROP TABLE IF EXISTS kafka_session_replay_events_ws
ALTER TABLE sharded_session_replay_events ADD COLUMN IF NOT EXISTS surfacing_score SimpleAggregateFunction(max, Nullable(Float32))
ALTER TABLE session_replay_events ADD COLUMN IF NOT EXISTS surfacing_score SimpleAggregateFunction(max, Nullable(Float32))
ALTER TABLE writable_session_replay_events ADD COLUMN IF NOT EXISTS surfacing_score SimpleAggregateFunction(max, Nullable(Float32))
CREATE TABLE IF NOT EXISTS kafka_session_replay_events ( session_id VARCHAR, team_id Int64, distinct_id VARCHAR, first_timestamp DateTime64(6, 'UTC'), last_timestamp DateTime64(6, 'UTC'), block_url Nullable(String), first_url Nullable(VARCHAR), urls Array(String), click_count Int64, keypress_count Int64, mouse_activity_count Int64, active_milliseconds Int64, console_log_count Int64, console_warn_count Int64, console_error_count Int64, size Int64, event_count Int64, message_count Int64, snapshot_source LowCardinality(Nullable(String)), snapshot_library Nullable(String), retention_period_days Nullable(Int64), is_deleted UInt8, ai_tags_fixed Array(String), ai_tags_freeform Array(String), ai_highlighted UInt8, surfacing_score Nullable(Float32), ) ENGINE = Kafka(msk_cluster, kafka_topic_list = 'clickhouse_session_replay_events_test', kafka_group_name = 'group1', kafka_format = 'JSONEachRow')
CREATE MATERIALIZED VIEW IF NOT EXISTS session_replay_events_mv TO posthog_test.writable_session_replay_events ( `session_id` String, `team_id` Int64, `distinct_id` String, `min_first_timestamp` DateTime64(6, 'UTC'), `max_last_timestamp` DateTime64(6, 'UTC'), `block_first_timestamps` SimpleAggregateFunction(groupArrayArray, Array(DateTime64(6, 'UTC'))), `block_last_timestamps` SimpleAggregateFunction(groupArrayArray, Array(DateTime64(6, 'UTC'))), `block_urls` SimpleAggregateFunction(groupArrayArray, Array(String)), `first_url` AggregateFunction(argMin, Nullable(String), DateTime64(6, 'UTC')), `all_urls` SimpleAggregateFunction(groupUniqArrayArray, Array(String)), `click_count` Int64, `keypress_count` Int64, `mouse_activity_count` Int64, `active_milliseconds` Int64, `console_log_count` Int64, `console_warn_count` Int64, `console_error_count` Int64, `size` Int64, `message_count` Int64, `event_count` Int64, `snapshot_source` AggregateFunction(argMin, LowCardinality(Nullable(String)), DateTime64(6, 'UTC')), `snapshot_library` AggregateFunction(argMin, Nullable(String), DateTime64(6, 'UTC')), `_timestamp` Nullable(DateTime) ,`retention_period_days` SimpleAggregateFunction(max, Nullable(Int64)) ,`is_deleted` SimpleAggregateFunction(max, UInt8) ,`ai_tags_fixed` SimpleAggregateFunction(groupUniqArrayArray, Array(String)) ,`ai_tags_freeform` SimpleAggregateFunction(groupUniqArrayArray, Array(String)) ,`ai_highlighted` SimpleAggregateFunction(max, UInt8) ,`surfacing_score` SimpleAggregateFunction(max, Nullable(Float32)) ) AS SELECT session_id, team_id, any(distinct_id) as distinct_id, min(first_timestamp) AS min_first_timestamp, max(last_timestamp) AS max_last_timestamp, groupArray(if(block_url != '', first_timestamp, NULL)) AS block_first_timestamps, groupArray(if(block_url != '', last_timestamp, NULL)) AS block_last_timestamps, groupArray(block_url) AS block_urls, -- TRICKY: ClickHouse will pick a relatively random first_url -- when it collapses the aggregating merge tree -- unless we teach it what we want... -- argMin ignores null values -- so this will get the first non-null value of first_url -- for each group of session_id and team_id -- by min of first_timestamp in the batch -- this is an aggregate function, not a simple aggregate function -- so we have to write to argMinState, and query with argMinMerge argMinState(first_url, first_timestamp) as first_url, groupUniqArrayArray(urls) as all_urls, sum(click_count) as click_count, sum(keypress_count) as keypress_count, sum(mouse_activity_count) as mouse_activity_count, sum(active_milliseconds) as active_milliseconds, sum(console_log_count) as console_log_count, sum(console_warn_count) as console_warn_count, sum(console_error_count) as console_error_count, sum(size) as size, -- we can count the number of kafka messages instead of sending it explicitly sum(message_count) as message_count, sum(event_count) as event_count, argMinState(snapshot_source, first_timestamp) as snapshot_source, argMinState(snapshot_library, first_timestamp) as snapshot_library, max(_timestamp) as _timestamp ,max(retention_period_days) as retention_period_days ,max(is_deleted) as is_deleted ,groupUniqArrayArray(ai_tags_fixed) as ai_tags_fixed ,groupUniqArrayArray(ai_tags_freeform) as ai_tags_freeform ,max(ai_highlighted) as ai_highlighted ,max(surfacing_score) as surfacing_score FROM posthog_test.kafka_session_replay_events group by session_id, team_id
CREATE TABLE IF NOT EXISTS sharded_session_replay_features ( session_id VARCHAR, team_id Int64, distinct_id VARCHAR, min_first_timestamp SimpleAggregateFunction(min, DateTime64(6, 'UTC')), max_last_timestamp SimpleAggregateFunction(max, DateTime64(6, 'UTC')), event_count SimpleAggregateFunction(sum, Int64), mouse_position_count SimpleAggregateFunction(sum, Int64), mouse_sum_x SimpleAggregateFunction(sum, Float64), mouse_sum_x_squared SimpleAggregateFunction(sum, Float64), mouse_sum_y SimpleAggregateFunction(sum, Float64), mouse_sum_y_squared SimpleAggregateFunction(sum, Float64), mouse_distance_traveled SimpleAggregateFunction(sum, Float64), mouse_direction_change_count SimpleAggregateFunction(sum, Int64), mouse_velocity_sum SimpleAggregateFunction(sum, Float64), mouse_velocity_sum_of_squares SimpleAggregateFunction(sum, Float64), mouse_velocity_count SimpleAggregateFunction(sum, Int64), scroll_event_count SimpleAggregateFunction(sum, Int64), total_scroll_magnitude SimpleAggregateFunction(sum, Float64), scroll_direction_reversal_count SimpleAggregateFunction(sum, Int64), rapid_scroll_reversal_count SimpleAggregateFunction(sum, Int64), scroll_to_top_count SimpleAggregateFunction(sum, Int64), click_count SimpleAggregateFunction(sum, Int64), keypress_count SimpleAggregateFunction(sum, Int64), mouse_activity_count SimpleAggregateFunction(sum, Int64), rage_click_count SimpleAggregateFunction(sum, Int64), dead_click_count SimpleAggregateFunction(sum, Int64), backspace_count S
…truncated. See the full SQL in the workflow logs.
Prompt To Fix All With AI### Issue 1
products/error_tracking/backend/presentation/views/severity_rules.py:84-88
**Tied keys break rule precedence**
When multiple creates omit `order_key`, or a reorder assigns duplicate values, the API persists tied keys while rules are sorted only by that field, causing the documented first-match severity precedence to become nondeterministic.
### Issue 2
products/error_tracking/backend/logic/__init__.py:860-861
**Unrelated updates erase disabled state**
When an empty or severity-only update targets a disabled rule, this clears `disabled_data` without replacing its filters or recompiling its bytecode, causing API and HogQL consumers to report the unchanged invalid rule as active and lose its diagnostic reason.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "feat(error-tracking): add severity rules..." | Re-trigger Greptile |
PR overviewAll previously flagged issues have been addressed. No open security concerns remain on this pull request. Security reviewNo open security issues remain on this pull request. Fixed/addressed: 1 · PR risk: 0/10 |
|
Reviews (2): Last reviewed commit: "feat(error-tracking): add severity rules..." | Re-trigger Greptile |
3672947 to
fd29f0a
Compare
|
Reviews (3): Last reviewed commit: "feat(error-tracking): add severity rules..." | Re-trigger Greptile |
fd29f0a to
b163bf9
Compare
|
Reviews (4): Last reviewed commit: "feat(error-tracking): add severity rules..." | Re-trigger Greptile |
b163bf9 to
78263a9
Compare
|
/trunk merge |
|
Reviews (5): Last reviewed commit: "chore: update OpenAPI generated types" | Re-trigger Greptile |
Problem
Error tracking projects cannot define ordered policies for the initial severity of newly created issues. The backend needs a team-scoped contract before ingestion and UI consumers can adopt severity rules.
Changes
system.error_tracking_severity_ruleswith team isolation.PR stack
Merge in this order:
Depends on: none
Followed by: #86268
This PR targets
master. After it is squash-merged, PR 2 must replay only its unique commit onto the updatedmasterbefore being retargeted. Do not retarget descendants blindly.How did you test this code?
hogli test products/error_tracking/backend/tests/api/test_severity_rules.pyhogli test posthog/hogql/database/schema/test/test_system_tables.py -k error_tracking_severity_rulesDEBUG=1 ./manage.py makemigrations error_tracking --check --dry-runhogli build:openapi --yes👉 Stay up-to-date with PostHog coding conventions for a smoother review.
Automatic notifications
Docs update
None for this backend contract layer.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Implemented with pi coding agent. Repo guidance and the OpenSpec apply, Django migrations, DRF endpoint, dataclass, generated API type, testing, and stacked PR skills shaped the implementation and split. The dedicated team-scoped model was chosen over extending unrelated rule actions so ingestion can load one narrow contract.