From 59b2f15df72111b3a97f04859536cdd2dfeaeee2 Mon Sep 17 00:00:00 2001 From: Xevion Date: Wed, 14 Jan 2026 18:25:55 -0600 Subject: [PATCH] fix: use proper standard $pageview event for posthog, enable exception tracking --- web/bun.lock | 3 +++ web/package.json | 1 + web/src/hooks.client.ts | 15 +++++---------- web/src/hooks.server.ts | 17 +++++++++++++++++ web/src/lib/telemetry/client.ts | 3 ++- web/src/lib/telemetry/events.ts | 3 ++- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/web/bun.lock b/web/bun.lock index 7fc833e..d7df901 100644 --- a/web/bun.lock +++ b/web/bun.lock @@ -18,6 +18,7 @@ "overlayscrollbars": "^2.13.0", "overlayscrollbars-svelte": "^0.5.5", "posthog-js": "^1.321.1", + "posthog-node": "^5.21.0", "satori": "^0.18.3", "tailwind-merge": "^3.3.1", }, @@ -691,6 +692,8 @@ "posthog-js": ["posthog-js@1.321.1", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/api-logs": "^0.208.0", "@opentelemetry/exporter-logs-otlp-http": "^0.208.0", "@opentelemetry/resources": "^2.2.0", "@opentelemetry/sdk-logs": "^0.208.0", "@posthog/core": "1.9.1", "@posthog/types": "1.321.1", "core-js": "^3.38.1", "dompurify": "^3.3.1", "fflate": "^0.4.8", "preact": "^10.28.0", "query-selector-shadow-dom": "^1.0.1", "web-vitals": "^4.2.4" } }, "sha512-PsRkY3LvPg3VUKROvc3HwSGUU9/JKHx/cNS4rZ5uHD5tDRACjjguGgFTp9XBLuf/+9YZcfdg1wxidk5bODvc2w=="], + "posthog-node": ["posthog-node@5.21.0", "", { "dependencies": { "@posthog/core": "1.9.1" } }, "sha512-M7v/+Zyz/z3ZDC4u896K2Lb/pLbPA1Czo6Tp/WeQ1vuBsJtJajqWO3vRev3BHFTP92nao5YCrU0aIM+Flwbv1A=="], + "preact": ["preact@10.28.2", "", {}, "sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], diff --git a/web/package.json b/web/package.json index 2341499..0e51a09 100644 --- a/web/package.json +++ b/web/package.json @@ -30,6 +30,7 @@ "overlayscrollbars": "^2.13.0", "overlayscrollbars-svelte": "^0.5.5", "posthog-js": "^1.321.1", + "posthog-node": "^5.21.0", "satori": "^0.18.3", "tailwind-merge": "^3.3.1" }, diff --git a/web/src/hooks.client.ts b/web/src/hooks.client.ts index 462bbad..d64b676 100644 --- a/web/src/hooks.client.ts +++ b/web/src/hooks.client.ts @@ -1,15 +1,10 @@ import type { HandleClientError } from "@sveltejs/kit"; -import { telemetry } from "$lib/telemetry"; +import posthog from "posthog-js"; -export const handleError: HandleClientError = ({ error, status, message }) => { - telemetry.trackError( - status >= 500 ? "runtime_error" : "network_error", - message, - { - stack: error instanceof Error ? error.stack : undefined, - context: { status }, - }, - ); +export const handleError: HandleClientError = ({ error, status }) => { + if (status !== 404) { + posthog.captureException(error); + } return { message: status === 404 ? "Not Found" : "An error occurred", diff --git a/web/src/hooks.server.ts b/web/src/hooks.server.ts index 89a0275..ac39b4b 100644 --- a/web/src/hooks.server.ts +++ b/web/src/hooks.server.ts @@ -1,13 +1,21 @@ import type { Handle, HandleServerError } from "@sveltejs/kit"; import { dev } from "$app/environment"; +import { env } from "$env/dynamic/private"; import { initLogger } from "$lib/logger"; import { requestContext } from "$lib/server/context"; import { preCacheCollections } from "$lib/server/icons"; import { getLogger } from "@logtape/logtape"; import { minify } from "html-minifier-terser"; +import { PostHog } from "posthog-node"; await initLogger(); +// Initialize PostHog for server-side error tracking +const posthog = + env.POSTHOG_KEY && env.POSTHOG_HOST + ? new PostHog(env.POSTHOG_KEY, { host: env.POSTHOG_HOST }) + : null; + // Pre-cache icon collections before handling any requests await preCacheCollections(); @@ -75,6 +83,15 @@ export const handleError: HandleServerError = async ({ error: error instanceof Error ? error.message : String(error), }); + if (posthog && status !== 404) { + const requestId = event.request.headers.get("x-request-id") ?? "unknown"; + posthog.captureException(error, requestId, { + method: event.request.method, + path: event.url.pathname, + status, + }); + } + return { message: status === 404 ? "Not Found" : "Internal Error", }; diff --git a/web/src/lib/telemetry/client.ts b/web/src/lib/telemetry/client.ts index 3160e21..3dc690f 100644 --- a/web/src/lib/telemetry/client.ts +++ b/web/src/lib/telemetry/client.ts @@ -83,10 +83,11 @@ class TelemetryClient { /** * Convenience method for tracking page views + * Uses PostHog's standard $pageview event for Web Analytics compatibility */ trackPageView(route: string): void { this.track({ - name: "page_view", + name: "$pageview", properties: { route, referrer: browser ? document.referrer : undefined, diff --git a/web/src/lib/telemetry/events.ts b/web/src/lib/telemetry/events.ts index 4a7ebb2..e0d4714 100644 --- a/web/src/lib/telemetry/events.ts +++ b/web/src/lib/telemetry/events.ts @@ -5,9 +5,10 @@ /** * Page view tracking event + * Uses PostHog's standard $pageview event name for Web Analytics compatibility */ export type PageViewEvent = { - name: "page_view"; + name: "$pageview"; properties: { route: string; referrer?: string;