Repository navigation
feat(metrics): suggest a service and host health dashboard - #118081
turnipdabeets wants to merge 10 commits into
Conversation
Adds a curated bank template for the PostHog Python SDK runtime metrics: CPU, memory, threads and garbage collection.
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
🤖 CI report
|
| File | Size | Δ vs base |
|---|---|---|
render-query/src/render-query/render-query.js |
24.62 MiB | 🔺 +4.2 KiB (+0.0%) |
posthog-app/src/scenes/dashboard/dashboards/Dashboards.js |
38.1 KiB | 🔺 +1.1 KiB (+3.0%) |
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 |
1013.3 KiB · 24 files | 🔺 +42 B (+0.0%) | █████████░ 86.5% of 1.14 MiB |
logged-out boot: index + App + bootApp (preloaded by every page, including /login)src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts |
2.88 MiB · 607 files | 🔺 +240 B (+0.0%) | █████████░ 94.9% of 3.03 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
7.49 MiB · 2,543 files | 🔺 +4.1 KiB (+0.1%) | ██████████ 97.9% of 7.64 MiB |
dashboard scenesrc/scenes/dashboard/Dashboard.tsx |
9.69 MiB · 3,630 files | 🔺 +4.1 KiB (+0.0%) | █████████░ 94.0% of 10.30 MiB |
today home pathsrc/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx |
7.87 MiB · 2,872 files | 🔺 +4.1 KiB (+0.1%) | ██████████ 99.7% of 7.89 MiB |
events scenesrc/scenes/activity/explore/EventsScene.tsx |
9.26 MiB · 3,456 files | 🔺 +4.1 KiB (+0.0%) | █████████░ 93.8% of 9.88 MiB |
replay detail scenesrc/scenes/session-recordings/detail/SessionRecordingDetail.tsx |
11.99 MiB · 4,300 files | 🔺 +4.0 KiB (+0.0%) | ████████░░ 79.6% of 15.05 MiB |
🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/zod/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/billing/billingLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/ProductEmptyState/productSetupPreloadLogic.ts stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/dashboards/frontend/widgets/previews/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 zod/v4/locales/de.js stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/today/TodayReportPage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
Largest files eagerly shipped from src/index.tsx
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/[email protected]/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/[email protected]/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@[email protected]/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/[email protected]/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/[email protected]/node_modules/base64-js/index.js |
| 1.3 KiB | src/index.tsx |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/[email protected]/node_modules/ieee754/index.js |
| 904 B | src/lib/utils/bootTiming.ts |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 319.8 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs |
| 220.2 KiB | ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.9 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
| 69.0 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 38.7 KiB | ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@dnd-kit/core/dist/core.esm.js |
| 33.9 KiB | ../node_modules/.pnpm/[email protected]_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js |
| 28.9 KiB | src/scenes/scenes.ts |
| 27.9 KiB | src/lib/constants.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 319.8 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs |
| 281.1 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.2 KiB | ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 185.5 KiB | ../packages/quill/packages/quill/dist/index.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 139.9 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.9 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js |
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 319.8 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs |
| 281.1 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.2 KiB | ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 185.5 KiB | ../packages/quill/packages/quill/dist/index.js |
| 181.9 KiB | src/queries/validators.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 139.9 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.9 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
| Size | File |
|---|---|
| 319.8 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs |
| 281.1 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.2 KiB | ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 185.5 KiB | ../packages/quill/packages/quill/dist/index.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 139.9 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.9 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/[email protected]/node_modules/prosemirror-view/dist/index.js |
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
| Size | File |
|---|---|
| 319.8 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs |
| 281.1 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.2 KiB | ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 185.5 KiB | ../packages/quill/packages/quill/dist/index.js |
| 181.9 KiB | src/queries/validators.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 139.9 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.9 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
| Size | File |
|---|---|
| 319.8 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/module.mjs |
| 316.0 KiB | ../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/posthog-js/dist/rrweb.js |
| 281.1 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 220.2 KiB | ../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 185.5 KiB | ../packages/quill/packages/quill/dist/index.js |
| 181.9 KiB | src/queries/validators.js |
| 153.7 KiB | ../node_modules/.pnpm/[email protected]/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.9 KiB | src/products.tsx |
| 99.6 KiB | src/lib/api.ts |
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 · 19 files | 🔺 +240 B (+0.0%) | ████░░░░░░ 39.1% of 5.72 MiB |
| Deferred (lazy) | 2.10 MiB · 40 files | no change | n/a — loads on demand |
Loader dist/toolbar.js |
1.2 KiB | no change | █░░░░░░░░░ 6.0% of 19.5 KiB |
Largest eagerly-shipped chunks
| Size | File |
|---|---|
| 877.4 KiB | dist/toolbar/toolbar-app-S3MAZA5Z.css |
| 664.5 KiB | dist/toolbar/chunk-chunk-WBANSWNU.js |
| 257.8 KiB | dist/toolbar/chunk-chunk-7ZYWOYNH.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 129.6 KiB | dist/toolbar/chunk-chunk-KUQ3Z4XJ.js |
| 74.8 KiB | dist/toolbar/toolbar-app-JK46IGL3.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-SXI75RIZ.js |
| 21.7 KiB | dist/toolbar/chunk-chunk-5ZPGLKQZ.js |
| 6.8 KiB | dist/toolbar/chunk-chunk-DV7IWQNF.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — 🔺 +174.8 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1017.79 MiB · 🔺 +174.8 KiB (+0.0%)
There was a problem hiding this comment.
PostHog Review · Standard · reviewed fa8b9ba: 3 Should fix.
This is the only automatic review while this pull request is a draft. Comment @posthog review to review new changes sooner. Otherwise, a review of the new changes runs when you mark it ready for review.
| { | ||
| "name": "a", | ||
| "metricName": "process.cpu.utilization", | ||
| "aggregation": "avg", |
There was a problem hiding this comment.
P2 · Sum CPU utilization across service processes
When two processes of one service each consume 25% of the same host's CPU in one mode, this panel reports 25% instead of 50%. MetricQueryRunner applies avg across process series after selecting their latest samples, so adding workers hides the service's growing CPU consumption. Sum process utilization within each service and CPU mode.
| { | ||
| "name": "a", | ||
| "metricName": "process.memory.utilization", | ||
| "aggregation": "max", |
There was a problem hiding this comment.
P2 · Aggregate memory utilization across service processes
When a service runs multiple workers on one host, max selects only the largest worker's memory fraction. Two workers each using 20% therefore appear as 20%, despite the panel promising the service's share of host memory. MetricQueryRunner applies this maximum across series, not across time; sum the workers' fractions or explicitly label this as the largest process.
| "groupBy": [ | ||
| { | ||
| "key": "service_name" | ||
| }, | ||
| { | ||
| "key": "process.runtime_id" | ||
| } | ||
| ] |
There was a problem hiding this comment.
P2 · Bound the process cardinality of the default dashboard queries
With 250 continuously reporting Python processes over 24 hours, grouping by process.runtime_id produces about 12,000 bucket rows. MetricQueryRunner._raise_on_truncation rejects results at 10,000 rows, so all four per-process panels display errors on this deployment. Default these panels to service grouping or require a bounded process selection.
…ntime dashboard The SDK samples runtime metrics every 10 seconds, and 15 seconds is the finest metrics interval.
15-second buckets split the SDK's 10-second samples unevenly, so counter rates zigzagged; auto picks 1-minute buckets for the last hour.
Dashboard creation already turns a template's text panels into text tiles; the bank test now checks those panels have text instead of requiring every panel to have a query.
Uses OpenTelemetry process metric names so any SDK fills it; CPython GC panels get their own section.
…oard Adds the host sections and keeps the per-runtime GC section, with OpenTelemetry metric names.
…states Available is the sum of the system.memory.usage states minus used, so it works on any OS.
Matches the internal dashboard's tile with the OpenTelemetry metric.
CPU and memory share of host now add up a service's processes instead of averaging or taking the largest, and the Python section gains p95 GC duration.
|
This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, please remove the |
Problem
Teams that send process, host and runtime metrics from PostHog SDKs get no ready-made dashboard for them. The suggested-dashboards bank covers Node.js and Go runtimes through Prometheus client names, but nothing reads the OpenTelemetry process and system metrics that the SDKs are starting to send. These teams have to build CPU, memory, swap and GC charts by hand.
Changes
process.*,system.*,cpython.gc.*). Any SDK, or any app already sending OTel process and system metrics, fills the generic sections.cpython.gc.*,jvm.gc.duration,v8js.gc.duration,go.memory.gc.*,dotnet.gc.*). Python is the first. Panels without data are dropped when the dashboard is created, but section headers stay, so a team removes the runtime sections it doesn't use.(1 - idle) * 100fromsystem.cpu.utilization, so it works whether an SDK reports per mode or per logical CPU.system.memory.usagestates minusused, the same formula the OTel host template uses, so it works on any OS. Memory pressure keeps the SDK'sapp.system.memory.pressure, because OTel has no pressure metric. On hosts that don't send it, those panels are dropped.service.instance.id, the OTel resource attribute.system.paging.operations. The SDK still sendsapp.system.swap.ioin bytes.system.memory.usagestates minusused. The SDK sends onlyfreeandused, so it currently shows free memory. It also needscached(inactive pages).How did you test this code?
products/metrics/backend/tests/test_suggested_dashboards.pypasses locally. Its parameterized bank test checksservice-health: every query validates againstMetricsQuery, every text panel has text, and nothing overlaps on the grid.oxfmt --checkand the pre-push checks passed.Test rationale: The text-panel change updates the existing bank test rather than adding one, since that test is the only place that rejected text panels. The template itself is covered by the parameterized bank test.
Release status
Docs update
None.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Opus 5.5
main.🤖 Generated with Claude Code