Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
3.8 kB ยท 104 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105import { getLogger } from "@logtape/logtape";import { type EventProps, Events, parseInputToProps, setupAnalytics,} from "@openstatus/analytics";import type { Context, Next } from "hono";import { matchedRoutes } from "hono/route";
import { apiAnalyticsIdentity } from "@/libs/analytics-identity";import { apiRequestSampleRate } from "@/libs/api-request-sampling";import { parseCliHeaders, trackCliCommand } from "@/libs/cli-telemetry";import type { Variables } from "@/types";
const logger = getLogger("api-server");
export function trackMiddleware(event: EventProps, eventProps?: string[]) { return async (c: Context<{ Variables: Variables }, "/*">, next: Next) => { await next();
// REMINDER: only track the event if the request was successful const isValid = c.res.status.toString().startsWith("2") && !c.error;
if (isValid) { // We have checked the request to be valid already let json: unknown; if (c.req.raw.bodyUsed) { try { json = await c.req.json(); } catch { json = {}; } } const additionalProps = parseInputToProps(json, eventProps); const workspace = c.get("workspace");
setupAnalytics(apiAnalyticsIdentity(workspace, c.req.raw.headers)) .then((analytics) => analytics.track({ ...additionalProps, ...event })) .catch(() => { logger.warn( "Failed to send analytics event {event} for workspace {workspaceId}", { event: event.name, workspaceId: workspace.id }, ); }); } };}
/** * Fires `api_request` for every authenticated V1 call โ reads included, and * failures too (`success: false`) โ mirroring the RPC tracking interceptor so * API volume is countable across both surfaces. `method` is the matched route * pattern (`GET /v1/monitor/:id`), never the raw URL, to keep it low-cardinality. * * Requests from the openstatus CLI also carry `cliCommand`/`cliVersion`, and * the first request of each CLI run fires one `cli_command`. CLI requests are * always tracked; the rest are sampled (see `apiRequestSampleRate`). * * Mount after `authMiddleware`; requests it rejects carry no workspace and are * skipped, as are requests that match no route. Per-route domain events stay with `trackMiddleware`. */export function apiTrackMiddleware() { return async (c: Context<{ Variables: Variables }, "/*">, next: Next) => { await next();
const workspace = c.get("workspace"); if (!workspace) return;
// `use()` middlewares register as `ALL`; with no handler route matched // (a 404 on an unknown path) the only pattern left is `/*`, which says // nothing about the endpoint, so those aren't counted. const route = matchedRoutes(c).findLast((r) => r.method !== "ALL"); if (!route) return;
const cli = parseCliHeaders(c.req.raw.headers); const sampleRate = apiRequestSampleRate(cli); if (sampleRate === undefined) return;
const success = c.res.status.toString().startsWith("2") && !c.error;
setupAnalytics(apiAnalyticsIdentity(workspace, c.req.raw.headers)) .then((analytics) => Promise.all([ analytics.track({ ...Events.ApiRequest, service: "v1", method: `${c.req.method} ${route.path}`, success, sampleRate, ...(cli ? { cliCommand: cli.command } : {}), ...(cli?.version ? { cliVersion: cli.version } : {}), }), ...(cli ? [trackCliCommand(analytics, workspace.id, cli)] : []), ]), ) .catch(() => { logger.warn( "Failed to send API analytics events for workspace {workspaceId}", { workspaceId: workspace.id }, ); }); };}