[{"data":1,"prerenderedAt":2399},["ShallowReactive",2],{"navigation_docs":3,"-use-cases-telemetry-ingest":612,"-use-cases-telemetry-ingest-surround":2394},[4,35,85,148,328,489,548,587],{"title":5,"path":6,"stem":7,"children":8,"page":34},"Start","\u002Fstart","1.start",[9,14,19,24,29],{"title":10,"path":11,"stem":12,"icon":13},"Introduction","\u002Fstart\u002Fintroduction","1.start\u002F1.introduction","i-lucide-info",{"title":15,"path":16,"stem":17,"icon":18},"Why start with evlog","\u002Fstart\u002Fwhy-evlog","1.start\u002F2.why-evlog","i-lucide-rocket",{"title":20,"path":21,"stem":22,"icon":23},"Installation","\u002Fstart\u002Finstallation","1.start\u002F3.installation","i-lucide-download",{"title":25,"path":26,"stem":27,"icon":28},"Quick Start","\u002Fstart\u002Fquick-start","1.start\u002F4.quick-start","i-lucide-zap",{"title":30,"path":31,"stem":32,"icon":33},"Choose your logger","\u002Fstart\u002Ftypescript-logging-library","1.start\u002F5.typescript-logging-library","i-lucide-file-code",false,{"title":36,"path":37,"stem":38,"children":39,"page":34},"Learn","\u002Flearn","2.learn",[40,45,50,55,60,65,70,75,80],{"title":41,"path":42,"stem":43,"icon":44},"Overview","\u002Flearn\u002Foverview","2.learn\u002F0.overview","i-lucide-list",{"title":46,"path":47,"stem":48,"icon":49},"Simple Logging","\u002Flearn\u002Fsimple-logging","2.learn\u002F1.simple-logging","i-lucide-terminal",{"title":51,"path":52,"stem":53,"icon":54},"Wide Events","\u002Flearn\u002Fwide-events","2.learn\u002F2.wide-events","i-lucide-layers",{"title":56,"path":57,"stem":58,"icon":59},"Structured Errors","\u002Flearn\u002Fstructured-errors","2.learn\u002F3.structured-errors","i-lucide-shield-alert",{"title":61,"path":62,"stem":63,"icon":64},"Lifecycle","\u002Flearn\u002Flifecycle","2.learn\u002F4.lifecycle","i-lucide-arrow-right-left",{"title":66,"path":67,"stem":68,"icon":69},"Sampling","\u002Flearn\u002Fsampling","2.learn\u002F5.sampling","i-lucide-filter",{"title":71,"path":72,"stem":73,"icon":74},"Auto-Redaction","\u002Flearn\u002Fredaction","2.learn\u002F6.redaction","i-lucide-eye-off",{"title":76,"path":77,"stem":78,"icon":79},"Typed Fields","\u002Flearn\u002Ftyped-fields","2.learn\u002F7.typed-fields","i-simple-icons-typescript",{"title":81,"path":82,"stem":83,"icon":84},"Catalogs","\u002Flearn\u002Fcatalogs","2.learn\u002F8.catalogs","i-lucide-book-open",{"title":86,"path":87,"stem":88,"children":89,"page":34},"CLI","\u002Fcli","3.cli",[90,93,98,103,108,113,118,123,128,133,138,143],{"title":41,"path":91,"stem":92,"icon":49},"\u002Fcli\u002Foverview","3.cli\u002F0.overview",{"title":94,"path":95,"stem":96,"icon":97},"init","\u002Fcli\u002Finit","3.cli\u002F1.init","i-lucide-wand-sparkles",{"title":99,"path":100,"stem":101,"icon":102},"logs","\u002Fcli\u002Flogs","3.cli\u002F10.logs","i-lucide-scroll-text",{"title":104,"path":105,"stem":106,"icon":107},"config","\u002Fcli\u002Fconfig","3.cli\u002F11.config","i-lucide-settings-2",{"title":109,"path":110,"stem":111,"icon":112},"map","\u002Fcli\u002Fmap","3.cli\u002F2.map","i-lucide-radar",{"title":114,"path":115,"stem":116,"icon":117},"Rules","\u002Fcli\u002Frules","3.cli\u002F3.rules","i-lucide-list-checks",{"title":119,"path":120,"stem":121,"icon":122},"Scoring","\u002Fcli\u002Fscoring","3.cli\u002F4.scoring","i-lucide-gauge",{"title":124,"path":125,"stem":126,"icon":127},"CI","\u002Fcli\u002Fci","3.cli\u002F5.ci","i-lucide-git-pull-request",{"title":129,"path":130,"stem":131,"icon":132},"doctor","\u002Fcli\u002Fdoctor","3.cli\u002F6.doctor","i-lucide-stethoscope",{"title":134,"path":135,"stem":136,"icon":137},"telemetry","\u002Fcli\u002Ftelemetry","3.cli\u002F7.telemetry","i-lucide-bar-chart-3",{"title":139,"path":140,"stem":141,"icon":142},"agents","\u002Fcli\u002Fagents","3.cli\u002F8.agents","i-lucide-bot",{"title":144,"path":145,"stem":146,"icon":147},"Observability Score","\u002Fcli\u002Fobservability-score","3.cli\u002F9.observability-score","i-lucide-activity",{"title":149,"path":150,"stem":151,"children":152,"page":34},"Integrate","\u002Fintegrate","4.integrate",[153,157,240],{"title":41,"path":154,"stem":155,"icon":156},"\u002Fintegrate\u002Foverview","4.integrate\u002F0.overview","i-lucide-plug",{"title":158,"path":159,"stem":160,"children":161,"page":34},"Adapters","\u002Fintegrate\u002Fadapters","4.integrate\u002Fadapters",[162,165,195,220],{"title":41,"path":163,"stem":164,"icon":44},"\u002Fintegrate\u002Fadapters\u002Foverview","4.integrate\u002Fadapters\u002F01.overview",{"title":166,"path":167,"stem":168,"children":169,"page":34},"Cloud","\u002Fintegrate\u002Fadapters\u002Fcloud","4.integrate\u002Fadapters\u002Fcloud",[170,175,180,185,190],{"title":171,"path":172,"stem":173,"icon":174},"Axiom","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Faxiom","4.integrate\u002Fadapters\u002Fcloud\u002F01.axiom","i-custom-axiom",{"title":176,"path":177,"stem":178,"icon":179},"PostHog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fposthog","4.integrate\u002Fadapters\u002Fcloud\u002F02.posthog","i-simple-icons-posthog",{"title":181,"path":182,"stem":183,"icon":184},"Sentry","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fsentry","4.integrate\u002Fadapters\u002Fcloud\u002F03.sentry","i-simple-icons-sentry",{"title":186,"path":187,"stem":188,"icon":189},"Better Stack","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fbetter-stack","4.integrate\u002Fadapters\u002Fcloud\u002F04.better-stack","i-simple-icons-betterstack",{"title":191,"path":192,"stem":193,"icon":194},"Datadog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fdatadog","4.integrate\u002Fadapters\u002Fcloud\u002F05.datadog","i-simple-icons-datadog",{"title":196,"path":197,"stem":198,"children":199,"page":34},"Cloud or Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fhybrid","4.integrate\u002Fadapters\u002Fhybrid",[200,205,210,215],{"title":201,"path":202,"stem":203,"icon":204},"Grafana Loki","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Floki","4.integrate\u002Fadapters\u002Fhybrid\u002F01.loki","i-simple-icons-grafana",{"title":206,"path":207,"stem":208,"icon":209},"ClickHouse","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fclickhouse","4.integrate\u002Fadapters\u002Fhybrid\u002F02.clickhouse","i-simple-icons-clickhouse",{"title":211,"path":212,"stem":213,"icon":214},"OTLP","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fotlp","4.integrate\u002Fadapters\u002Fhybrid\u002F03.otlp","i-simple-icons-opentelemetry",{"title":216,"path":217,"stem":218,"icon":219},"HyperDX","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fhyperdx","4.integrate\u002Fadapters\u002Fhybrid\u002F04.hyperdx","i-custom-hyperdx",{"title":221,"path":222,"stem":223,"children":224,"page":34},"Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fself-hosted","4.integrate\u002Fadapters\u002Fself-hosted",[225,230,235],{"title":226,"path":227,"stem":228,"icon":229},"File System","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Ffs","4.integrate\u002Fadapters\u002Fself-hosted\u002F01.fs","i-lucide-hard-drive",{"title":231,"path":232,"stem":233,"icon":234},"NuxtHub","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fnuxthub","4.integrate\u002Fadapters\u002Fself-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":236,"path":237,"stem":238,"icon":239},"Memory","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fmemory","4.integrate\u002Fadapters\u002Fself-hosted\u002F03.memory","i-lucide-cpu",{"title":241,"path":242,"stem":243,"children":244,"page":34},"Frameworks","\u002Fintegrate\u002Fframeworks","4.integrate\u002Fframeworks",[245,249,254,259,264,269,274,279,284,289,294,299,304,309,313,318,323],{"title":41,"path":246,"stem":247,"icon":248},"\u002Fintegrate\u002Fframeworks\u002Foverview","4.integrate\u002Fframeworks\u002F00.overview","i-lucide-layout-grid",{"title":250,"path":251,"stem":252,"icon":253},"Nuxt","\u002Fintegrate\u002Fframeworks\u002Fnuxt","4.integrate\u002Fframeworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":255,"path":256,"stem":257,"icon":258},"Next.js","\u002Fintegrate\u002Fframeworks\u002Fnextjs","4.integrate\u002Fframeworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":260,"path":261,"stem":262,"icon":263},"SvelteKit","\u002Fintegrate\u002Fframeworks\u002Fsveltekit","4.integrate\u002Fframeworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":265,"path":266,"stem":267,"icon":268},"Nitro","\u002Fintegrate\u002Fframeworks\u002Fnitro","4.integrate\u002Fframeworks\u002F04.nitro","i-custom-nitro",{"title":270,"path":271,"stem":272,"icon":273},"TanStack Start","\u002Fintegrate\u002Fframeworks\u002Ftanstack-start","4.integrate\u002Fframeworks\u002F05.tanstack-start","i-custom-tanstack",{"title":275,"path":276,"stem":277,"icon":278},"NestJS","\u002Fintegrate\u002Fframeworks\u002Fnestjs","4.integrate\u002Fframeworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":280,"path":281,"stem":282,"icon":283},"Express","\u002Fintegrate\u002Fframeworks\u002Fexpress","4.integrate\u002Fframeworks\u002F07.express","i-simple-icons-express",{"title":285,"path":286,"stem":287,"icon":288},"Hono","\u002Fintegrate\u002Fframeworks\u002Fhono","4.integrate\u002Fframeworks\u002F08.hono","i-simple-icons-hono",{"title":290,"path":291,"stem":292,"icon":293},"Fastify","\u002Fintegrate\u002Fframeworks\u002Ffastify","4.integrate\u002Fframeworks\u002F09.fastify","i-simple-icons-fastify",{"title":295,"path":296,"stem":297,"icon":298},"Elysia","\u002Fintegrate\u002Fframeworks\u002Felysia","4.integrate\u002Fframeworks\u002F10.elysia","i-custom-elysia",{"title":300,"path":301,"stem":302,"icon":303},"React Router","\u002Fintegrate\u002Fframeworks\u002Freact-router","4.integrate\u002Fframeworks\u002F11.react-router","i-custom-reactrouter",{"title":305,"path":306,"stem":307,"icon":308},"Cloudflare Workers","\u002Fintegrate\u002Fframeworks\u002Fcloudflare-workers","4.integrate\u002Fframeworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":310,"path":311,"stem":312,"icon":79},"Standalone","\u002Fintegrate\u002Fframeworks\u002Fstandalone","4.integrate\u002Fframeworks\u002F13.standalone",{"title":314,"path":315,"stem":316,"icon":317},"Astro","\u002Fintegrate\u002Fframeworks\u002Fastro","4.integrate\u002Fframeworks\u002F14.astro","i-simple-icons-astro",{"title":319,"path":320,"stem":321,"icon":322},"oRPC","\u002Fintegrate\u002Fframeworks\u002Forpc","4.integrate\u002Fframeworks\u002F15.orpc","i-lucide-network",{"title":324,"path":325,"stem":326,"icon":327},"AWS Lambda","\u002Fintegrate\u002Fframeworks\u002Faws-lambda","4.integrate\u002Fframeworks\u002F16.aws-lambda","i-custom-lambda",{"title":329,"path":330,"stem":331,"children":332,"page":34},"Use Cases","\u002Fuse-cases","5.use-cases",[333,336,341,369,396,428,449,454,459,463],{"title":41,"path":334,"stem":335,"icon":117},"\u002Fuse-cases\u002Foverview","5.use-cases\u002F0.overview",{"title":337,"path":338,"stem":339,"icon":340},"Client Logging","\u002Fuse-cases\u002Fclient-logging","5.use-cases\u002F1.client-logging","i-lucide-monitor",{"title":342,"icon":343,"path":344,"stem":345,"children":346,"page":34},"AI SDK","i-simple-icons-vercel","\u002Fuse-cases\u002Fai-sdk","5.use-cases\u002F2.ai-sdk",[347,350,355,360,365],{"title":41,"path":348,"stem":349,"icon":44},"\u002Fuse-cases\u002Fai-sdk\u002Foverview","5.use-cases\u002F2.ai-sdk\u002F01.overview",{"title":351,"path":352,"stem":353,"icon":354},"Usage","\u002Fuse-cases\u002Fai-sdk\u002Fusage","5.use-cases\u002F2.ai-sdk\u002F02.usage","i-lucide-code",{"title":356,"path":357,"stem":358,"icon":359},"Options","\u002Fuse-cases\u002Fai-sdk\u002Foptions","5.use-cases\u002F2.ai-sdk\u002F03.options","i-lucide-sliders",{"title":361,"path":362,"stem":363,"icon":364},"Metadata","\u002Fuse-cases\u002Fai-sdk\u002Fmetadata","5.use-cases\u002F2.ai-sdk\u002F04.metadata","i-lucide-database",{"title":366,"path":367,"stem":368,"icon":147},"Telemetry","\u002Fuse-cases\u002Fai-sdk\u002Ftelemetry","5.use-cases\u002F2.ai-sdk\u002F05.telemetry",{"title":370,"icon":371,"path":372,"stem":373,"children":374,"page":34},"Better Auth","i-simple-icons-betterauth","\u002Fuse-cases\u002Fbetter-auth","5.use-cases\u002F3.better-auth",[375,378,383,388,392],{"title":41,"path":376,"stem":377,"icon":44},"\u002Fuse-cases\u002Fbetter-auth\u002Foverview","5.use-cases\u002F3.better-auth\u002F01.overview",{"title":379,"path":380,"stem":381,"icon":382},"Identify User","\u002Fuse-cases\u002Fbetter-auth\u002Fidentify-user","5.use-cases\u002F3.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":384,"path":385,"stem":386,"icon":387},"Middleware","\u002Fuse-cases\u002Fbetter-auth\u002Fmiddleware","5.use-cases\u002F3.better-auth\u002F03.middleware","i-lucide-shield",{"title":389,"path":390,"stem":391,"icon":340},"Client Sync","\u002Fuse-cases\u002Fbetter-auth\u002Fclient-sync","5.use-cases\u002F3.better-auth\u002F04.client-sync",{"title":393,"path":394,"stem":395,"icon":122},"Performance","\u002Fuse-cases\u002Fbetter-auth\u002Fperformance","5.use-cases\u002F3.better-auth\u002F05.performance",{"title":397,"icon":398,"path":399,"stem":400,"children":401,"page":34},"Audit Logs","i-lucide-shield-check","\u002Fuse-cases\u002Faudit","5.use-cases\u002F4.audit",[402,405,410,415,420,424],{"title":41,"path":403,"stem":404,"icon":44},"\u002Fuse-cases\u002Faudit\u002Foverview","5.use-cases\u002F4.audit\u002F01.overview",{"title":406,"path":407,"stem":408,"icon":409},"Schema","\u002Fuse-cases\u002Faudit\u002Fschema","5.use-cases\u002F4.audit\u002F02.schema","i-lucide-file-text",{"title":411,"path":412,"stem":413,"icon":414},"Recording","\u002Fuse-cases\u002Faudit\u002Frecording","5.use-cases\u002F4.audit\u002F03.recording","i-lucide-pen-line",{"title":416,"path":417,"stem":418,"icon":419},"Drains","\u002Fuse-cases\u002Faudit\u002Fpipeline","5.use-cases\u002F4.audit\u002F04.pipeline","i-lucide-link",{"title":421,"path":422,"stem":423,"icon":398},"Compliance","\u002Fuse-cases\u002Faudit\u002Fcompliance","5.use-cases\u002F4.audit\u002F05.compliance",{"title":425,"path":426,"stem":427,"icon":84},"Recipes","\u002Fuse-cases\u002Faudit\u002Frecipes","5.use-cases\u002F4.audit\u002F06.recipes",{"title":366,"icon":122,"path":429,"stem":430,"children":431,"page":34},"\u002Fuse-cases\u002Ftelemetry","5.use-cases\u002F4.telemetry",[432,435,440,445],{"title":41,"path":433,"stem":434,"icon":44},"\u002Fuse-cases\u002Ftelemetry\u002Foverview","5.use-cases\u002F4.telemetry\u002F01.overview",{"title":436,"path":437,"stem":438,"icon":439},"Setup","\u002Fuse-cases\u002Ftelemetry\u002Fsetup","5.use-cases\u002F4.telemetry\u002F02.setup","i-lucide-wrench",{"title":441,"path":442,"stem":443,"icon":444},"Ingest","\u002Fuse-cases\u002Ftelemetry\u002Fingest","5.use-cases\u002F4.telemetry\u002F03.ingest","i-lucide-server",{"title":446,"path":447,"stem":448,"icon":84},"Reference","\u002Fuse-cases\u002Ftelemetry\u002Freference","5.use-cases\u002F4.telemetry\u002F04.reference",{"title":450,"path":451,"stem":452,"icon":453},"Enrichers","\u002Fuse-cases\u002Fenrichers","5.use-cases\u002F5.enrichers","i-lucide-sparkles",{"title":455,"path":456,"stem":457,"icon":458},"eve","\u002Fuse-cases\u002Feve","5.use-cases\u002F5.eve","i-custom-eve",{"title":460,"path":461,"stem":462,"icon":444},"Node.js request logging","\u002Fuse-cases\u002Fstructured-logging-nodejs","5.use-cases\u002F6.structured-logging-nodejs",{"title":464,"icon":465,"path":466,"stem":467,"children":468,"page":34},"Signals","i-lucide-scan-search","\u002Fuse-cases\u002Fsignals","5.use-cases\u002F7.signals",[469,472,477,482,485],{"title":41,"path":470,"stem":471,"icon":44},"\u002Fuse-cases\u002Fsignals\u002Foverview","5.use-cases\u002F7.signals\u002F01.overview",{"title":473,"path":474,"stem":475,"icon":476},"What You Can Ask","\u002Fuse-cases\u002Fsignals\u002Fask","5.use-cases\u002F7.signals\u002F02.ask","i-lucide-message-circle-question",{"title":478,"path":479,"stem":480,"icon":481},"What It Costs","\u002Fuse-cases\u002Fsignals\u002Fcost","5.use-cases\u002F7.signals\u002F03.cost","i-lucide-coins",{"title":446,"path":483,"stem":484,"icon":84},"\u002Fuse-cases\u002Fsignals\u002Freference","5.use-cases\u002F7.signals\u002F04.reference",{"title":425,"path":486,"stem":487,"icon":488},"\u002Fuse-cases\u002Fsignals\u002Frecipes","5.use-cases\u002F7.signals\u002F05.recipes","i-lucide-lightbulb",{"title":490,"path":491,"stem":492,"children":493,"page":34},"Extend","\u002Fextend","6.extend",[494,498,503,508,512,517,521,525,529,533,538,543],{"title":41,"path":495,"stem":496,"icon":497},"\u002Fextend\u002Foverview","6.extend\u002F0.overview","i-lucide-blocks",{"title":499,"path":500,"stem":501,"icon":502},"Stream","\u002Fextend\u002Fstream","6.extend\u002F1.stream","i-lucide-radio-tower",{"title":504,"path":505,"stem":506,"icon":507},"Custom framework","\u002Fextend\u002Fcustom-framework","6.extend\u002F10.custom-framework","i-lucide-puzzle",{"title":509,"path":510,"stem":511,"icon":502},"Diagnostics channel","\u002Fextend\u002Fdiagnostics-channel","6.extend\u002F11.diagnostics-channel",{"title":513,"path":514,"stem":515,"icon":516},"FS reader","\u002Fextend\u002Ffs-reader","6.extend\u002F2.fs-reader","i-lucide-folder-search",{"title":425,"path":518,"stem":519,"icon":520},"\u002Fextend\u002Fconsumer-recipes","6.extend\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":522,"path":523,"stem":524,"icon":497},"Plugins","\u002Fextend\u002Fplugins","6.extend\u002F4.plugins",{"title":526,"path":527,"stem":528,"icon":453},"Custom enrichers","\u002Fextend\u002Fcustom-enrichers","6.extend\u002F5.custom-enrichers",{"title":530,"path":531,"stem":532,"icon":69},"Tail sampling","\u002Fextend\u002Ftail-sampling","6.extend\u002F6.tail-sampling",{"title":534,"path":535,"stem":536,"icon":537},"Identity headers","\u002Fextend\u002Fidentity-headers","6.extend\u002F7.identity-headers","i-lucide-fingerprint",{"title":539,"path":540,"stem":541,"icon":542},"Custom drains","\u002Fextend\u002Fcustom-drains","6.extend\u002F8.custom-drains","i-lucide-share-2",{"title":544,"path":545,"stem":546,"icon":547},"Drain pipeline","\u002Fextend\u002Fdrain-pipeline","6.extend\u002F9.drain-pipeline","i-lucide-workflow",{"title":446,"path":549,"stem":550,"children":551,"page":34},"\u002Freference","7.reference",[552,556,561,564,569,573,578,582],{"title":41,"path":553,"stem":554,"icon":555},"\u002Freference\u002Foverview","7.reference\u002F0.overview","i-lucide-book-marked",{"title":557,"path":558,"stem":559,"icon":560},"Configuration","\u002Freference\u002Fconfiguration","7.reference\u002F1.configuration","i-lucide-settings",{"title":393,"path":562,"stem":563,"icon":122},"\u002Freference\u002Fperformance","7.reference\u002F2.performance",{"title":565,"path":566,"stem":567,"icon":568},"Vite Plugin","\u002Freference\u002Fvite-plugin","7.reference\u002F3.vite-plugin","i-custom-vite",{"title":570,"path":571,"stem":572,"icon":398},"Best Practices","\u002Freference\u002Fbest-practices","7.reference\u002F4.best-practices",{"title":574,"path":575,"stem":576,"icon":577},"vs Other Loggers","\u002Freference\u002Fvs-other-loggers","7.reference\u002F5.vs-other-loggers","i-lucide-scale",{"title":579,"path":580,"stem":581,"icon":453},"Agent Skills","\u002Freference\u002Fagent-skills","7.reference\u002F6.agent-skills",{"title":583,"path":584,"stem":585,"icon":586},"Cost","\u002Freference\u002Fcost","7.reference\u002F7.cost","i-lucide-receipt",{"title":588,"path":589,"stem":590,"children":591,"page":34},"Compare","\u002Fcompare","8.compare",[592,596,600,604,608],{"title":593,"path":594,"stem":595,"icon":577},"evlog vs Pino","\u002Fcompare\u002Fpino","8.compare\u002F1.pino",{"title":597,"path":598,"stem":599,"icon":214},"evlog vs OpenTelemetry","\u002Fcompare\u002Fopentelemetry","8.compare\u002F2.opentelemetry",{"title":601,"path":602,"stem":603,"icon":577},"evlog vs LogTape","\u002Fcompare\u002Flogtape","8.compare\u002F3.logtape",{"title":605,"path":606,"stem":607,"icon":577},"evlog vs Winston: formats and request events","\u002Fcompare\u002Fwinston","8.compare\u002F4.winston",{"title":609,"path":610,"stem":611,"icon":577},"evlog vs Consola: reporters and request context","\u002Fcompare\u002Fconsola","8.compare\u002F5.consola",{"id":613,"title":614,"body":615,"description":2382,"extension":2383,"links":2384,"meta":2390,"navigation":2391,"path":442,"seo":2392,"stem":443,"__hash__":2393},"docs\u002F5.use-cases\u002F4.telemetry\u002F03.ingest.md","Telemetry Ingest",{"type":616,"value":617,"toc":2374},"minimark",[618,632,640,645,652,657,668,673,684,779,785,799,805,817,1046,1065,1069,1076,2029,2033,2039,2347,2351,2360,2370],[619,620,621,622,626,627,631],"p",{},"You ship a CLI. Users run it on their machines. You want to know ",[623,624,625],"em",{},"which commands run, how often they fail, and which versions are out there",", without building a separate analytics SDK or reading raw ",[628,629,630],"code",{},"argv",".",[619,633,634,635,639],{},"That means a ",[636,637,638],"strong",{},"server endpoint"," your CLI POSTs to. The local outbox is only there so short CI jobs and offline runs do not lose data before the POST succeeds.",[641,642,644],"h2",{"id":643},"the-security-question-read-this-first","The security question (read this first)",[646,647,648,651],"tip",{},[636,649,650],{},"CLI telemetry is not a vault."," You are collecting anonymous usage counters (command name, duration, outcome, a few numbers), not passwords, not file paths, not tokens. Design for that threat model and you do not need impossible client-side secrets.",[619,653,654],{},[636,655,656],{},"\"I put the ingest URL in my CLI. Isn't that a secret?\"",[619,658,659,660,663,664,667],{},"No. The URL lives in your npm package or binary. Anyone can read it with ",[628,661,662],{},"strings",", by installing the package, or by watching network traffic. The same applies to an API key or ",[628,665,666],{},"Authorization"," header baked into the CLI is extractable, not a real barrier.",[619,669,670],{},[636,671,672],{},"\"So can't anyone send fake events?\"",[619,674,675,676,679,680,683],{},"In theory, yes: someone could ",[628,677,678],{},"curl"," your endpoint with forged JSON. That is why you treat the endpoint as ",[636,681,682],{},"semi-public"," (like a browser analytics key) and defend on the server:",[685,686,687,700],"table",{},[688,689,690],"thead",{},[691,692,693,697],"tr",{},[694,695,696],"th",{},"What you might worry about",[694,698,699],{},"Practical answer",[701,702,703,715,726,737,752,764],"tbody",{},[691,704,705,709],{},[706,707,708],"td",{},"Random internet bots",[706,710,711,712],{},"Validate the payload shape; reject garbage with ",[628,713,714],{},"400",[691,716,717,723],{},[706,718,719,720,722],{},"Someone spamming fake ",[628,721,129],{}," runs",[706,724,725],{},"Rate-limit by IP; data is low-value counters, not money",[691,727,728,734],{},[706,729,730,731],{},"Forged ",[628,732,733],{},"tool.name",[706,735,736],{},"Allowlist only your published tool names server-side",[691,738,739,745],{},[706,740,741,742],{},"Unexpected fields in ",[628,743,744],{},"custom",[706,746,747,748,751],{},"Filter to the keys you declared — same list as ",[628,749,750],{},"collect"," on the CLI",[691,753,754,757],{},[706,755,756],{},"Double-counting on retry",[706,758,759,760,763],{},"Dedupe on ",[628,761,762],{},"idempotencyKey"," when storing",[691,765,766,769],{},[706,767,768],{},"Leaking user secrets",[706,770,771,772,774,775,778],{},"CLI never reads raw ",[628,773,630],{},"; you only allowlisted flags and ",[628,776,777],{},"telemetry.set()"," counters",[619,780,781,784],{},[636,782,783],{},"What \"good enough\" looks like:"," validate every POST, store idempotently, rate-limit at the edge (CDN, API gateway, or middleware), and keep the payload boring (no PII by design). That is the same playbook as client-side analytics: not banking-grade auth, but reliable product insight.",[786,787,789,792,793,798],"callout",{"color":788,"icon":398},"info",[628,790,791],{},"@evlog\u002Ftelemetry"," ships ",[636,794,795],{},[628,796,797],{},"parseIngestBody()"," for your server, with the same validation rules documented here, so you do not copy-paste a validator from the docs. Pair it with your framework route and your database or evlog drain.",[641,800,802,803],{"id":801},"step-1-validate-with-parseingestbody","Step 1: Validate with ",[628,804,797],{},[619,806,807,808,811,812,814,815,631],{},"Mirror the CLI config on the server: same ",[628,809,810],{},"name",", same custom keys you allow via ",[628,813,750],{}," \u002F ",[628,816,777],{},[818,819,825],"pre",{"className":820,"code":821,"filename":822,"language":823,"meta":824,"style":824},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { parseIngestBody } from '@evlog\u002Ftelemetry\u002Fingest'\n\nexport const ingestOptions = {\n  allowedTools: ['my-tool'],\n  allowedCustomKeys: {\n    'my-tool': ['checksFailed', 'checksWarn', 'itemsSynced'],\n  },\n} as const\n\nexport function parseTelemetryBody(raw: string) {\n  return parseIngestBody(raw, ingestOptions)\n}\n","lib\u002Ftelemetry-ingest.ts","ts","",[628,826,827,860,867,886,913,923,967,973,985,990,1020,1040],{"__ignoreMap":824},[828,829,832,836,840,844,847,850,853,857],"span",{"class":830,"line":831},"line",1,[828,833,835],{"class":834},"s7zQu","import",[828,837,839],{"class":838},"sMK4o"," {",[828,841,843],{"class":842},"sTEyZ"," parseIngestBody",[828,845,846],{"class":838}," }",[828,848,849],{"class":834}," from",[828,851,852],{"class":838}," '",[828,854,856],{"class":855},"sfazB","@evlog\u002Ftelemetry\u002Fingest",[828,858,859],{"class":838},"'\n",[828,861,863],{"class":830,"line":862},2,[828,864,866],{"emptyLinePlaceholder":865},true,"\n",[828,868,870,873,877,880,883],{"class":830,"line":869},3,[828,871,872],{"class":834},"export",[828,874,876],{"class":875},"spNyl"," const",[828,878,879],{"class":842}," ingestOptions ",[828,881,882],{"class":838},"=",[828,884,885],{"class":838}," {\n",[828,887,889,893,896,899,902,905,907,910],{"class":830,"line":888},4,[828,890,892],{"class":891},"swJcz","  allowedTools",[828,894,895],{"class":838},":",[828,897,898],{"class":842}," [",[828,900,901],{"class":838},"'",[828,903,904],{"class":855},"my-tool",[828,906,901],{"class":838},[828,908,909],{"class":842},"]",[828,911,912],{"class":838},",\n",[828,914,916,919,921],{"class":830,"line":915},5,[828,917,918],{"class":891},"  allowedCustomKeys",[828,920,895],{"class":838},[828,922,885],{"class":838},[828,924,926,929,931,933,935,937,939,942,944,947,949,952,954,956,958,961,963,965],{"class":830,"line":925},6,[828,927,928],{"class":838},"    '",[828,930,904],{"class":891},[828,932,901],{"class":838},[828,934,895],{"class":838},[828,936,898],{"class":842},[828,938,901],{"class":838},[828,940,941],{"class":855},"checksFailed",[828,943,901],{"class":838},[828,945,946],{"class":838},",",[828,948,852],{"class":838},[828,950,951],{"class":855},"checksWarn",[828,953,901],{"class":838},[828,955,946],{"class":838},[828,957,852],{"class":838},[828,959,960],{"class":855},"itemsSynced",[828,962,901],{"class":838},[828,964,909],{"class":842},[828,966,912],{"class":838},[828,968,970],{"class":830,"line":969},7,[828,971,972],{"class":838},"  },\n",[828,974,976,979,982],{"class":830,"line":975},8,[828,977,978],{"class":838},"}",[828,980,981],{"class":834}," as",[828,983,984],{"class":875}," const\n",[828,986,988],{"class":830,"line":987},9,[828,989,866],{"emptyLinePlaceholder":865},[828,991,993,995,998,1002,1005,1009,1011,1015,1018],{"class":830,"line":992},10,[828,994,872],{"class":834},[828,996,997],{"class":875}," function",[828,999,1001],{"class":1000},"s2Zo4"," parseTelemetryBody",[828,1003,1004],{"class":838},"(",[828,1006,1008],{"class":1007},"sHdIc","raw",[828,1010,895],{"class":838},[828,1012,1014],{"class":1013},"sBMFI"," string",[828,1016,1017],{"class":838},")",[828,1019,885],{"class":838},[828,1021,1023,1026,1028,1030,1032,1034,1037],{"class":830,"line":1022},11,[828,1024,1025],{"class":834},"  return",[828,1027,843],{"class":1000},[828,1029,1004],{"class":891},[828,1031,1008],{"class":842},[828,1033,946],{"class":838},[828,1035,1036],{"class":842}," ingestOptions",[828,1038,1039],{"class":891},")\n",[828,1041,1043],{"class":830,"line":1042},12,[828,1044,1045],{"class":838},"}\n",[619,1047,1048,1050,1051,1054,1055,1057,1058,1061,1062,1064],{},[628,1049,797],{}," checks batch size, JSON shape, ",[628,1052,1053],{},"event: 'run'",", tool allowlist, envelope types, ISO timestamp, and strips ",[628,1056,744],{}," keys you did not declare. Throws ",[628,1059,1060],{},"IngestValidationError"," on failure, so return ",[628,1063,714],{}," from your route.",[641,1066,1068],{"id":1067},"step-2-wire-your-route","Step 2: Wire your route",[619,1070,1071,1072,1075],{},"Same contract for any framework: read the raw body, validate, store, return ",[636,1073,1074],{},"204"," so the CLI clears its outbox:",[1077,1078,1079,1465,1723],"framework-tabs",{},[818,1080,1083],{"className":820,"code":1081,"filename":265,"language":823,"meta":1082,"style":824},"import { defineHandler } from 'nitro\u002Fh3'\nimport { readRawBody, setResponseStatus } from 'h3'\nimport { IngestValidationError } from '@evlog\u002Ftelemetry\u002Fingest'\nimport { parseTelemetryBody } from '~\u002Flib\u002Ftelemetry-ingest'\nimport { storeRunEvents } from '~\u002Flib\u002Ftelemetry-store'\n\nexport default defineHandler(async (event) => {\n  const raw = await readRawBody(event, 'utf8')\n  if (!raw) {\n    setResponseStatus(event, 400)\n    return { error: 'empty body' }\n  }\n\n  try {\n    const events = parseTelemetryBody(raw)\n    await storeRunEvents(events)\n    setResponseStatus(event, 204)\n    return null\n  } catch (err) {\n    setResponseStatus(event, err instanceof IngestValidationError ? 400 : 500)\n    return { error: 'invalid payload' }\n  }\n})\n","server\u002Fapi\u002Ftelemetry\u002Fingest.post.ts",[628,1084,1085,1105,1130,1149,1168,1188,1192,1219,1250,1268,1285,1307,1312,1317,1325,1344,1359,1375,1383,1401,1433,1453,1458],{"__ignoreMap":824},[828,1086,1087,1089,1091,1094,1096,1098,1100,1103],{"class":830,"line":831},[828,1088,835],{"class":834},[828,1090,839],{"class":838},[828,1092,1093],{"class":842}," defineHandler",[828,1095,846],{"class":838},[828,1097,849],{"class":834},[828,1099,852],{"class":838},[828,1101,1102],{"class":855},"nitro\u002Fh3",[828,1104,859],{"class":838},[828,1106,1107,1109,1111,1114,1116,1119,1121,1123,1125,1128],{"class":830,"line":862},[828,1108,835],{"class":834},[828,1110,839],{"class":838},[828,1112,1113],{"class":842}," readRawBody",[828,1115,946],{"class":838},[828,1117,1118],{"class":842}," setResponseStatus",[828,1120,846],{"class":838},[828,1122,849],{"class":834},[828,1124,852],{"class":838},[828,1126,1127],{"class":855},"h3",[828,1129,859],{"class":838},[828,1131,1132,1134,1136,1139,1141,1143,1145,1147],{"class":830,"line":869},[828,1133,835],{"class":834},[828,1135,839],{"class":838},[828,1137,1138],{"class":842}," IngestValidationError",[828,1140,846],{"class":838},[828,1142,849],{"class":834},[828,1144,852],{"class":838},[828,1146,856],{"class":855},[828,1148,859],{"class":838},[828,1150,1151,1153,1155,1157,1159,1161,1163,1166],{"class":830,"line":888},[828,1152,835],{"class":834},[828,1154,839],{"class":838},[828,1156,1001],{"class":842},[828,1158,846],{"class":838},[828,1160,849],{"class":834},[828,1162,852],{"class":838},[828,1164,1165],{"class":855},"~\u002Flib\u002Ftelemetry-ingest",[828,1167,859],{"class":838},[828,1169,1170,1172,1174,1177,1179,1181,1183,1186],{"class":830,"line":915},[828,1171,835],{"class":834},[828,1173,839],{"class":838},[828,1175,1176],{"class":842}," storeRunEvents",[828,1178,846],{"class":838},[828,1180,849],{"class":834},[828,1182,852],{"class":838},[828,1184,1185],{"class":855},"~\u002Flib\u002Ftelemetry-store",[828,1187,859],{"class":838},[828,1189,1190],{"class":830,"line":925},[828,1191,866],{"emptyLinePlaceholder":865},[828,1193,1194,1196,1199,1201,1203,1206,1209,1212,1214,1217],{"class":830,"line":969},[828,1195,872],{"class":834},[828,1197,1198],{"class":834}," default",[828,1200,1093],{"class":1000},[828,1202,1004],{"class":842},[828,1204,1205],{"class":875},"async",[828,1207,1208],{"class":838}," (",[828,1210,1211],{"class":1007},"event",[828,1213,1017],{"class":838},[828,1215,1216],{"class":875}," =>",[828,1218,885],{"class":838},[828,1220,1221,1224,1227,1230,1233,1235,1237,1239,1241,1243,1246,1248],{"class":830,"line":975},[828,1222,1223],{"class":875},"  const",[828,1225,1226],{"class":842}," raw",[828,1228,1229],{"class":838}," =",[828,1231,1232],{"class":834}," await",[828,1234,1113],{"class":1000},[828,1236,1004],{"class":891},[828,1238,1211],{"class":842},[828,1240,946],{"class":838},[828,1242,852],{"class":838},[828,1244,1245],{"class":855},"utf8",[828,1247,901],{"class":838},[828,1249,1039],{"class":891},[828,1251,1252,1255,1257,1260,1262,1265],{"class":830,"line":987},[828,1253,1254],{"class":834},"  if",[828,1256,1208],{"class":891},[828,1258,1259],{"class":838},"!",[828,1261,1008],{"class":842},[828,1263,1264],{"class":891},") ",[828,1266,1267],{"class":838},"{\n",[828,1269,1270,1273,1275,1277,1279,1283],{"class":830,"line":992},[828,1271,1272],{"class":1000},"    setResponseStatus",[828,1274,1004],{"class":891},[828,1276,1211],{"class":842},[828,1278,946],{"class":838},[828,1280,1282],{"class":1281},"sbssI"," 400",[828,1284,1039],{"class":891},[828,1286,1287,1290,1292,1295,1297,1299,1302,1304],{"class":830,"line":1022},[828,1288,1289],{"class":834},"    return",[828,1291,839],{"class":838},[828,1293,1294],{"class":891}," error",[828,1296,895],{"class":838},[828,1298,852],{"class":838},[828,1300,1301],{"class":855},"empty body",[828,1303,901],{"class":838},[828,1305,1306],{"class":838}," }\n",[828,1308,1309],{"class":830,"line":1042},[828,1310,1311],{"class":838},"  }\n",[828,1313,1315],{"class":830,"line":1314},13,[828,1316,866],{"emptyLinePlaceholder":865},[828,1318,1320,1323],{"class":830,"line":1319},14,[828,1321,1322],{"class":834},"  try",[828,1324,885],{"class":838},[828,1326,1328,1331,1334,1336,1338,1340,1342],{"class":830,"line":1327},15,[828,1329,1330],{"class":875},"    const",[828,1332,1333],{"class":842}," events",[828,1335,1229],{"class":838},[828,1337,1001],{"class":1000},[828,1339,1004],{"class":891},[828,1341,1008],{"class":842},[828,1343,1039],{"class":891},[828,1345,1347,1350,1352,1354,1357],{"class":830,"line":1346},16,[828,1348,1349],{"class":834},"    await",[828,1351,1176],{"class":1000},[828,1353,1004],{"class":891},[828,1355,1356],{"class":842},"events",[828,1358,1039],{"class":891},[828,1360,1362,1364,1366,1368,1370,1373],{"class":830,"line":1361},17,[828,1363,1272],{"class":1000},[828,1365,1004],{"class":891},[828,1367,1211],{"class":842},[828,1369,946],{"class":838},[828,1371,1372],{"class":1281}," 204",[828,1374,1039],{"class":891},[828,1376,1378,1380],{"class":830,"line":1377},18,[828,1379,1289],{"class":834},[828,1381,1382],{"class":838}," null\n",[828,1384,1386,1389,1392,1394,1397,1399],{"class":830,"line":1385},19,[828,1387,1388],{"class":838},"  }",[828,1390,1391],{"class":834}," catch",[828,1393,1208],{"class":891},[828,1395,1396],{"class":842},"err",[828,1398,1264],{"class":891},[828,1400,1267],{"class":838},[828,1402,1404,1406,1408,1410,1412,1415,1418,1420,1423,1425,1428,1431],{"class":830,"line":1403},20,[828,1405,1272],{"class":1000},[828,1407,1004],{"class":891},[828,1409,1211],{"class":842},[828,1411,946],{"class":838},[828,1413,1414],{"class":842}," err",[828,1416,1417],{"class":838}," instanceof",[828,1419,1138],{"class":1013},[828,1421,1422],{"class":838}," ?",[828,1424,1282],{"class":1281},[828,1426,1427],{"class":838}," :",[828,1429,1430],{"class":1281}," 500",[828,1432,1039],{"class":891},[828,1434,1436,1438,1440,1442,1444,1446,1449,1451],{"class":830,"line":1435},21,[828,1437,1289],{"class":834},[828,1439,839],{"class":838},[828,1441,1294],{"class":891},[828,1443,895],{"class":838},[828,1445,852],{"class":838},[828,1447,1448],{"class":855},"invalid payload",[828,1450,901],{"class":838},[828,1452,1306],{"class":838},[828,1454,1456],{"class":830,"line":1455},22,[828,1457,1311],{"class":838},[828,1459,1461,1463],{"class":830,"line":1460},23,[828,1462,978],{"class":838},[828,1464,1039],{"class":842},[818,1466,1470],{"className":820,"code":1467,"filename":1468,"language":823,"meta":1469,"style":824},"import { IngestValidationError } from '@evlog\u002Ftelemetry\u002Fingest'\nimport { parseTelemetryBody } from '@\u002Flib\u002Ftelemetry-ingest'\nimport { storeRunEvents } from '@\u002Flib\u002Ftelemetry-store'\n\nexport async function POST(request: Request) {\n  const raw = await request.text()\n  try {\n    const events = parseTelemetryBody(raw)\n    await storeRunEvents(events)\n    return new Response(null, { status: 204 })\n  } catch (err) {\n    const status = err instanceof IngestValidationError ? 400 : 500\n    return Response.json({ error: 'invalid payload' }, { status })\n  }\n}\n","Next.js App Router","app\u002Fapi\u002Ftelemetry\u002Fingest\u002Froute.ts",[628,1471,1472,1490,1509,1528,1532,1558,1579,1585,1601,1613,1641,1655,1678,1715,1719],{"__ignoreMap":824},[828,1473,1474,1476,1478,1480,1482,1484,1486,1488],{"class":830,"line":831},[828,1475,835],{"class":834},[828,1477,839],{"class":838},[828,1479,1138],{"class":842},[828,1481,846],{"class":838},[828,1483,849],{"class":834},[828,1485,852],{"class":838},[828,1487,856],{"class":855},[828,1489,859],{"class":838},[828,1491,1492,1494,1496,1498,1500,1502,1504,1507],{"class":830,"line":862},[828,1493,835],{"class":834},[828,1495,839],{"class":838},[828,1497,1001],{"class":842},[828,1499,846],{"class":838},[828,1501,849],{"class":834},[828,1503,852],{"class":838},[828,1505,1506],{"class":855},"@\u002Flib\u002Ftelemetry-ingest",[828,1508,859],{"class":838},[828,1510,1511,1513,1515,1517,1519,1521,1523,1526],{"class":830,"line":869},[828,1512,835],{"class":834},[828,1514,839],{"class":838},[828,1516,1176],{"class":842},[828,1518,846],{"class":838},[828,1520,849],{"class":834},[828,1522,852],{"class":838},[828,1524,1525],{"class":855},"@\u002Flib\u002Ftelemetry-store",[828,1527,859],{"class":838},[828,1529,1530],{"class":830,"line":888},[828,1531,866],{"emptyLinePlaceholder":865},[828,1533,1534,1536,1539,1541,1544,1546,1549,1551,1554,1556],{"class":830,"line":915},[828,1535,872],{"class":834},[828,1537,1538],{"class":875}," async",[828,1540,997],{"class":875},[828,1542,1543],{"class":1000}," POST",[828,1545,1004],{"class":838},[828,1547,1548],{"class":1007},"request",[828,1550,895],{"class":838},[828,1552,1553],{"class":1013}," Request",[828,1555,1017],{"class":838},[828,1557,885],{"class":838},[828,1559,1560,1562,1564,1566,1568,1571,1573,1576],{"class":830,"line":925},[828,1561,1223],{"class":875},[828,1563,1226],{"class":842},[828,1565,1229],{"class":838},[828,1567,1232],{"class":834},[828,1569,1570],{"class":842}," request",[828,1572,631],{"class":838},[828,1574,1575],{"class":1000},"text",[828,1577,1578],{"class":891},"()\n",[828,1580,1581,1583],{"class":830,"line":969},[828,1582,1322],{"class":834},[828,1584,885],{"class":838},[828,1586,1587,1589,1591,1593,1595,1597,1599],{"class":830,"line":975},[828,1588,1330],{"class":875},[828,1590,1333],{"class":842},[828,1592,1229],{"class":838},[828,1594,1001],{"class":1000},[828,1596,1004],{"class":891},[828,1598,1008],{"class":842},[828,1600,1039],{"class":891},[828,1602,1603,1605,1607,1609,1611],{"class":830,"line":987},[828,1604,1349],{"class":834},[828,1606,1176],{"class":1000},[828,1608,1004],{"class":891},[828,1610,1356],{"class":842},[828,1612,1039],{"class":891},[828,1614,1615,1617,1620,1623,1625,1628,1630,1633,1635,1637,1639],{"class":830,"line":992},[828,1616,1289],{"class":834},[828,1618,1619],{"class":838}," new",[828,1621,1622],{"class":1000}," Response",[828,1624,1004],{"class":891},[828,1626,1627],{"class":838},"null,",[828,1629,839],{"class":838},[828,1631,1632],{"class":891}," status",[828,1634,895],{"class":838},[828,1636,1372],{"class":1281},[828,1638,846],{"class":838},[828,1640,1039],{"class":891},[828,1642,1643,1645,1647,1649,1651,1653],{"class":830,"line":1022},[828,1644,1388],{"class":838},[828,1646,1391],{"class":834},[828,1648,1208],{"class":891},[828,1650,1396],{"class":842},[828,1652,1264],{"class":891},[828,1654,1267],{"class":838},[828,1656,1657,1659,1661,1663,1665,1667,1669,1671,1673,1675],{"class":830,"line":1042},[828,1658,1330],{"class":875},[828,1660,1632],{"class":842},[828,1662,1229],{"class":838},[828,1664,1414],{"class":842},[828,1666,1417],{"class":838},[828,1668,1138],{"class":1013},[828,1670,1422],{"class":838},[828,1672,1282],{"class":1281},[828,1674,1427],{"class":838},[828,1676,1677],{"class":1281}," 500\n",[828,1679,1680,1682,1684,1686,1689,1691,1694,1696,1698,1700,1702,1704,1707,1709,1711,1713],{"class":830,"line":1314},[828,1681,1289],{"class":834},[828,1683,1622],{"class":842},[828,1685,631],{"class":838},[828,1687,1688],{"class":1000},"json",[828,1690,1004],{"class":891},[828,1692,1693],{"class":838},"{",[828,1695,1294],{"class":891},[828,1697,895],{"class":838},[828,1699,852],{"class":838},[828,1701,1448],{"class":855},[828,1703,901],{"class":838},[828,1705,1706],{"class":838}," },",[828,1708,839],{"class":838},[828,1710,1632],{"class":842},[828,1712,846],{"class":838},[828,1714,1039],{"class":891},[828,1716,1717],{"class":830,"line":1319},[828,1718,1311],{"class":838},[828,1720,1721],{"class":830,"line":1327},[828,1722,1045],{"class":838},[818,1724,1727],{"className":820,"code":1725,"filename":285,"language":823,"meta":1726,"style":824},"import { Hono } from 'hono'\nimport { IngestValidationError } from '@evlog\u002Ftelemetry\u002Fingest'\nimport { parseTelemetryBody } from '..\u002Flib\u002Ftelemetry-ingest'\nimport { storeRunEvents } from '..\u002Flib\u002Ftelemetry-store'\n\nconst app = new Hono()\n\napp.post('\u002Fapi\u002Ftelemetry\u002Fingest', async (c) => {\n  const raw = await c.req.text()\n  try {\n    const events = parseTelemetryBody(raw)\n    await storeRunEvents(events)\n    return c.body(null, 204)\n  } catch (err) {\n    const status = err instanceof IngestValidationError ? 400 : 500\n    return c.json({ error: 'invalid payload' }, status)\n  }\n})\n\nexport default app\n","src\u002Froutes\u002Ftelemetry.ts",[628,1728,1729,1749,1767,1786,1805,1809,1825,1829,1863,1887,1893,1909,1921,1940,1954,1976,2006,2010,2016,2020],{"__ignoreMap":824},[828,1730,1731,1733,1735,1738,1740,1742,1744,1747],{"class":830,"line":831},[828,1732,835],{"class":834},[828,1734,839],{"class":838},[828,1736,1737],{"class":842}," Hono",[828,1739,846],{"class":838},[828,1741,849],{"class":834},[828,1743,852],{"class":838},[828,1745,1746],{"class":855},"hono",[828,1748,859],{"class":838},[828,1750,1751,1753,1755,1757,1759,1761,1763,1765],{"class":830,"line":862},[828,1752,835],{"class":834},[828,1754,839],{"class":838},[828,1756,1138],{"class":842},[828,1758,846],{"class":838},[828,1760,849],{"class":834},[828,1762,852],{"class":838},[828,1764,856],{"class":855},[828,1766,859],{"class":838},[828,1768,1769,1771,1773,1775,1777,1779,1781,1784],{"class":830,"line":869},[828,1770,835],{"class":834},[828,1772,839],{"class":838},[828,1774,1001],{"class":842},[828,1776,846],{"class":838},[828,1778,849],{"class":834},[828,1780,852],{"class":838},[828,1782,1783],{"class":855},"..\u002Flib\u002Ftelemetry-ingest",[828,1785,859],{"class":838},[828,1787,1788,1790,1792,1794,1796,1798,1800,1803],{"class":830,"line":888},[828,1789,835],{"class":834},[828,1791,839],{"class":838},[828,1793,1176],{"class":842},[828,1795,846],{"class":838},[828,1797,849],{"class":834},[828,1799,852],{"class":838},[828,1801,1802],{"class":855},"..\u002Flib\u002Ftelemetry-store",[828,1804,859],{"class":838},[828,1806,1807],{"class":830,"line":915},[828,1808,866],{"emptyLinePlaceholder":865},[828,1810,1811,1814,1817,1819,1821,1823],{"class":830,"line":925},[828,1812,1813],{"class":875},"const",[828,1815,1816],{"class":842}," app ",[828,1818,882],{"class":838},[828,1820,1619],{"class":838},[828,1822,1737],{"class":1000},[828,1824,1578],{"class":842},[828,1826,1827],{"class":830,"line":969},[828,1828,866],{"emptyLinePlaceholder":865},[828,1830,1831,1834,1836,1839,1841,1843,1846,1848,1850,1852,1854,1857,1859,1861],{"class":830,"line":975},[828,1832,1833],{"class":842},"app",[828,1835,631],{"class":838},[828,1837,1838],{"class":1000},"post",[828,1840,1004],{"class":842},[828,1842,901],{"class":838},[828,1844,1845],{"class":855},"\u002Fapi\u002Ftelemetry\u002Fingest",[828,1847,901],{"class":838},[828,1849,946],{"class":838},[828,1851,1538],{"class":875},[828,1853,1208],{"class":838},[828,1855,1856],{"class":1007},"c",[828,1858,1017],{"class":838},[828,1860,1216],{"class":875},[828,1862,885],{"class":838},[828,1864,1865,1867,1869,1871,1873,1876,1878,1881,1883,1885],{"class":830,"line":987},[828,1866,1223],{"class":875},[828,1868,1226],{"class":842},[828,1870,1229],{"class":838},[828,1872,1232],{"class":834},[828,1874,1875],{"class":842}," c",[828,1877,631],{"class":838},[828,1879,1880],{"class":842},"req",[828,1882,631],{"class":838},[828,1884,1575],{"class":1000},[828,1886,1578],{"class":891},[828,1888,1889,1891],{"class":830,"line":992},[828,1890,1322],{"class":834},[828,1892,885],{"class":838},[828,1894,1895,1897,1899,1901,1903,1905,1907],{"class":830,"line":1022},[828,1896,1330],{"class":875},[828,1898,1333],{"class":842},[828,1900,1229],{"class":838},[828,1902,1001],{"class":1000},[828,1904,1004],{"class":891},[828,1906,1008],{"class":842},[828,1908,1039],{"class":891},[828,1910,1911,1913,1915,1917,1919],{"class":830,"line":1042},[828,1912,1349],{"class":834},[828,1914,1176],{"class":1000},[828,1916,1004],{"class":891},[828,1918,1356],{"class":842},[828,1920,1039],{"class":891},[828,1922,1923,1925,1927,1929,1932,1934,1936,1938],{"class":830,"line":1314},[828,1924,1289],{"class":834},[828,1926,1875],{"class":842},[828,1928,631],{"class":838},[828,1930,1931],{"class":1000},"body",[828,1933,1004],{"class":891},[828,1935,1627],{"class":838},[828,1937,1372],{"class":1281},[828,1939,1039],{"class":891},[828,1941,1942,1944,1946,1948,1950,1952],{"class":830,"line":1319},[828,1943,1388],{"class":838},[828,1945,1391],{"class":834},[828,1947,1208],{"class":891},[828,1949,1396],{"class":842},[828,1951,1264],{"class":891},[828,1953,1267],{"class":838},[828,1955,1956,1958,1960,1962,1964,1966,1968,1970,1972,1974],{"class":830,"line":1327},[828,1957,1330],{"class":875},[828,1959,1632],{"class":842},[828,1961,1229],{"class":838},[828,1963,1414],{"class":842},[828,1965,1417],{"class":838},[828,1967,1138],{"class":1013},[828,1969,1422],{"class":838},[828,1971,1282],{"class":1281},[828,1973,1427],{"class":838},[828,1975,1677],{"class":1281},[828,1977,1978,1980,1982,1984,1986,1988,1990,1992,1994,1996,1998,2000,2002,2004],{"class":830,"line":1346},[828,1979,1289],{"class":834},[828,1981,1875],{"class":842},[828,1983,631],{"class":838},[828,1985,1688],{"class":1000},[828,1987,1004],{"class":891},[828,1989,1693],{"class":838},[828,1991,1294],{"class":891},[828,1993,895],{"class":838},[828,1995,852],{"class":838},[828,1997,1448],{"class":855},[828,1999,901],{"class":838},[828,2001,1706],{"class":838},[828,2003,1632],{"class":842},[828,2005,1039],{"class":891},[828,2007,2008],{"class":830,"line":1361},[828,2009,1311],{"class":838},[828,2011,2012,2014],{"class":830,"line":1377},[828,2013,978],{"class":838},[828,2015,1039],{"class":842},[828,2017,2018],{"class":830,"line":1385},[828,2019,866],{"emptyLinePlaceholder":865},[828,2021,2022,2024,2026],{"class":830,"line":1403},[828,2023,872],{"class":834},[828,2025,1198],{"class":834},[828,2027,2028],{"class":842}," app\n",[641,2030,2032],{"id":2031},"step-3-store-idempotently","Step 3: Store idempotently",[619,2034,2035,2036,2038],{},"Retries and backlog drains can POST the same ",[628,2037,762],{}," twice. Upsert (or skip) so metrics stay correct:",[818,2040,2043],{"className":820,"code":2041,"filename":2042,"language":823,"meta":824,"style":824},"import type { RunEvent } from '@evlog\u002Ftelemetry'\n\nexport async function storeRunEvents(events: RunEvent[]): Promise\u003Cvoid> {\n  for (const run of events) {\n    await db.telemetryRun.upsert({\n      where: { idempotencyKey: run.idempotencyKey },\n      create: {\n        tool: run.tool.name,\n        version: run.tool.version,\n        command: run.command,\n        outcome: run.outcome,\n        durationMs: run.durationMs,\n        custom: run.custom,\n        recordedAt: run.timestamp,\n      },\n      update: {},\n    })\n  }\n\n  \u002F\u002F Or forward into evlog's drain pipeline for Axiom \u002F Datadog \u002F OTLP:\n  \u002F\u002F await ingestWideEvents(events.map(run => ({ source: 'telemetry', ...run })))\n}\n","lib\u002Ftelemetry-store.ts",[628,2044,2045,2067,2071,2109,2130,2151,2174,2183,2203,2223,2239,2255,2271,2286,2302,2307,2317,2324,2328,2332,2338,2343],{"__ignoreMap":824},[828,2046,2047,2049,2052,2054,2057,2059,2061,2063,2065],{"class":830,"line":831},[828,2048,835],{"class":834},[828,2050,2051],{"class":834}," type",[828,2053,839],{"class":838},[828,2055,2056],{"class":842}," RunEvent",[828,2058,846],{"class":838},[828,2060,849],{"class":834},[828,2062,852],{"class":838},[828,2064,791],{"class":855},[828,2066,859],{"class":838},[828,2068,2069],{"class":830,"line":862},[828,2070,866],{"emptyLinePlaceholder":865},[828,2072,2073,2075,2077,2079,2081,2083,2085,2087,2089,2092,2095,2098,2101,2104,2107],{"class":830,"line":869},[828,2074,872],{"class":834},[828,2076,1538],{"class":875},[828,2078,997],{"class":875},[828,2080,1176],{"class":1000},[828,2082,1004],{"class":838},[828,2084,1356],{"class":1007},[828,2086,895],{"class":838},[828,2088,2056],{"class":1013},[828,2090,2091],{"class":842},"[]",[828,2093,2094],{"class":838},"):",[828,2096,2097],{"class":1013}," Promise",[828,2099,2100],{"class":838},"\u003C",[828,2102,2103],{"class":1013},"void",[828,2105,2106],{"class":838},">",[828,2108,885],{"class":838},[828,2110,2111,2114,2116,2118,2121,2124,2126,2128],{"class":830,"line":888},[828,2112,2113],{"class":834},"  for",[828,2115,1208],{"class":891},[828,2117,1813],{"class":875},[828,2119,2120],{"class":842}," run",[828,2122,2123],{"class":838}," of",[828,2125,1333],{"class":842},[828,2127,1264],{"class":891},[828,2129,1267],{"class":838},[828,2131,2132,2134,2137,2139,2142,2144,2147,2149],{"class":830,"line":915},[828,2133,1349],{"class":834},[828,2135,2136],{"class":842}," db",[828,2138,631],{"class":838},[828,2140,2141],{"class":842},"telemetryRun",[828,2143,631],{"class":838},[828,2145,2146],{"class":1000},"upsert",[828,2148,1004],{"class":891},[828,2150,1267],{"class":838},[828,2152,2153,2156,2158,2160,2163,2165,2167,2169,2171],{"class":830,"line":925},[828,2154,2155],{"class":891},"      where",[828,2157,895],{"class":838},[828,2159,839],{"class":838},[828,2161,2162],{"class":891}," idempotencyKey",[828,2164,895],{"class":838},[828,2166,2120],{"class":842},[828,2168,631],{"class":838},[828,2170,762],{"class":842},[828,2172,2173],{"class":838}," },\n",[828,2175,2176,2179,2181],{"class":830,"line":969},[828,2177,2178],{"class":891},"      create",[828,2180,895],{"class":838},[828,2182,885],{"class":838},[828,2184,2185,2188,2190,2192,2194,2197,2199,2201],{"class":830,"line":975},[828,2186,2187],{"class":891},"        tool",[828,2189,895],{"class":838},[828,2191,2120],{"class":842},[828,2193,631],{"class":838},[828,2195,2196],{"class":842},"tool",[828,2198,631],{"class":838},[828,2200,810],{"class":842},[828,2202,912],{"class":838},[828,2204,2205,2208,2210,2212,2214,2216,2218,2221],{"class":830,"line":987},[828,2206,2207],{"class":891},"        version",[828,2209,895],{"class":838},[828,2211,2120],{"class":842},[828,2213,631],{"class":838},[828,2215,2196],{"class":842},[828,2217,631],{"class":838},[828,2219,2220],{"class":842},"version",[828,2222,912],{"class":838},[828,2224,2225,2228,2230,2232,2234,2237],{"class":830,"line":992},[828,2226,2227],{"class":891},"        command",[828,2229,895],{"class":838},[828,2231,2120],{"class":842},[828,2233,631],{"class":838},[828,2235,2236],{"class":842},"command",[828,2238,912],{"class":838},[828,2240,2241,2244,2246,2248,2250,2253],{"class":830,"line":1022},[828,2242,2243],{"class":891},"        outcome",[828,2245,895],{"class":838},[828,2247,2120],{"class":842},[828,2249,631],{"class":838},[828,2251,2252],{"class":842},"outcome",[828,2254,912],{"class":838},[828,2256,2257,2260,2262,2264,2266,2269],{"class":830,"line":1042},[828,2258,2259],{"class":891},"        durationMs",[828,2261,895],{"class":838},[828,2263,2120],{"class":842},[828,2265,631],{"class":838},[828,2267,2268],{"class":842},"durationMs",[828,2270,912],{"class":838},[828,2272,2273,2276,2278,2280,2282,2284],{"class":830,"line":1314},[828,2274,2275],{"class":891},"        custom",[828,2277,895],{"class":838},[828,2279,2120],{"class":842},[828,2281,631],{"class":838},[828,2283,744],{"class":842},[828,2285,912],{"class":838},[828,2287,2288,2291,2293,2295,2297,2300],{"class":830,"line":1319},[828,2289,2290],{"class":891},"        recordedAt",[828,2292,895],{"class":838},[828,2294,2120],{"class":842},[828,2296,631],{"class":838},[828,2298,2299],{"class":842},"timestamp",[828,2301,912],{"class":838},[828,2303,2304],{"class":830,"line":1327},[828,2305,2306],{"class":838},"      },\n",[828,2308,2309,2312,2314],{"class":830,"line":1346},[828,2310,2311],{"class":891},"      update",[828,2313,895],{"class":838},[828,2315,2316],{"class":838}," {},\n",[828,2318,2319,2322],{"class":830,"line":1361},[828,2320,2321],{"class":838},"    }",[828,2323,1039],{"class":891},[828,2325,2326],{"class":830,"line":1377},[828,2327,1311],{"class":838},[828,2329,2330],{"class":830,"line":1385},[828,2331,866],{"emptyLinePlaceholder":865},[828,2333,2334],{"class":830,"line":1403},[828,2335,2337],{"class":2336},"sHwdD","  \u002F\u002F Or forward into evlog's drain pipeline for Axiom \u002F Datadog \u002F OTLP:\n",[828,2339,2340],{"class":830,"line":1435},[828,2341,2342],{"class":2336},"  \u002F\u002F await ingestWideEvents(events.map(run => ({ source: 'telemetry', ...run })))\n",[828,2344,2345],{"class":830,"line":1455},[828,2346,1045],{"class":838},[641,2348,2350],{"id":2349},"step-4-rate-limit-at-the-edge","Step 4: Rate-limit at the edge",[619,2352,2353,2355,2356,2359],{},[628,2354,797],{}," is your last line of schema defense, not your only one. Add rate limits where traffic enters (CDN, API gateway, or middleware), especially per IP. Optional: also bucket by ",[628,2357,2358],{},"machineId"," hash inside the handler if you need tighter control.",[619,2361,2362,2363,2365,2366,2369],{},"Non-2xx responses keep events in the user's outbox; they will retry on the next CLI invocation. Return ",[636,2364,1074],{}," (or any ",[628,2367,2368],{},"2xx",") only when storage succeeded.",[2371,2372,2373],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":824,"searchDepth":862,"depth":862,"links":2375},[2376,2377,2379,2380,2381],{"id":643,"depth":862,"text":644},{"id":801,"depth":862,"text":2378},"Step 1: Validate with parseIngestBody()",{"id":1067,"depth":862,"text":1068},{"id":2031,"depth":862,"text":2032},{"id":2349,"depth":862,"text":2350},"Build the ingestion endpoint for @evlog\u002Ftelemetry: the threat model, parseIngestBody validation, framework routes, storage, and rate limiting.","md",[2385,2388,2389],{"label":41,"icon":44,"to":433,"color":2386,"variant":2387},"neutral","subtle",{"label":436,"icon":439,"to":437,"color":2386,"variant":2387},{"label":446,"icon":84,"to":447,"color":2386,"variant":2387},{},{"title":441,"icon":444},{"title":614,"description":2382},"99esxu3WRJgsdXDuOerVQYtEP45OC6LCjj4wVyRJZHc",[2395,2397],{"title":436,"path":437,"stem":438,"description":2396,"icon":439,"children":-1},"Wire @evlog\u002Ftelemetry into citty CLIs, standalone scripts, and GitHub Actions — delivery config, automatic flag capture, telemetry.set(), and debug mode.",{"title":446,"path":447,"stem":448,"description":2398,"icon":84,"children":-1},"RunEvent envelope, extending the schema with collect and custom fields, privacy rules, TELEMETRY.md disclosure, and consent \u002F outbox reliability.",1791704405623]