Openstatus www.openstatus.dev
at main 48 lines 1.5 kB view raw
1import type { Variables } from "@/types"; 2import { getLogger } from "@logtape/logtape"; 3import { 4 type EventProps, 5 parseInputToProps, 6 setupAnalytics, 7} from "@openstatus/analytics"; 8import type { Context, Next } from "hono"; 9 10const logger = getLogger("api-server"); 11 12export function trackMiddleware(event: EventProps, eventProps?: string[]) { 13 return async (c: Context<{ Variables: Variables }, "/*">, next: Next) => { 14 await next(); 15 16 // REMINDER: only track the event if the request was successful 17 const isValid = c.res.status.toString().startsWith("2") && !c.error; 18 19 if (isValid) { 20 // We have checked the request to be valid already 21 let json: unknown; 22 if (c.req.raw.bodyUsed) { 23 try { 24 json = await c.req.json(); 25 } catch { 26 json = {}; 27 } 28 } 29 const additionalProps = parseInputToProps(json, eventProps); 30 const workspace = c.get("workspace"); 31 32 setupAnalytics({ 33 userId: `api_${workspace.id}`, 34 workspaceId: `${workspace.id}`, 35 plan: workspace.plan, 36 location: c.req.raw.headers.get("x-forwarded-for") ?? undefined, 37 userAgent: c.req.raw.headers.get("user-agent") ?? undefined, 38 }) 39 .then((analytics) => analytics.track({ ...event, additionalProps })) 40 .catch(() => { 41 logger.warn( 42 "Failed to send analytics event {event} for workspace {workspaceId}", 43 { event: event.name, workspaceId: workspace.id }, 44 ); 45 }); 46 } 47 }; 48}