[{"data":1,"prerenderedAt":4282},["ShallowReactive",2],{"navigation_docs":3,"-extend-consumer-recipes":451,"-extend-consumer-recipes-surround":4277},[4,30,80,245,365,420],{"title":5,"path":6,"stem":7,"children":8,"page":29},"Start","\u002Fstart","1.start",[9,14,19,24],{"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",false,{"title":31,"path":32,"stem":33,"children":34,"page":29},"Learn","\u002Flearn","2.learn",[35,40,45,50,55,60,65,70,75],{"title":36,"path":37,"stem":38,"icon":39},"Overview","\u002Flearn\u002Foverview","2.learn\u002F0.overview","i-lucide-list",{"title":41,"path":42,"stem":43,"icon":44},"Simple Logging","\u002Flearn\u002Fsimple-logging","2.learn\u002F1.simple-logging","i-lucide-terminal",{"title":46,"path":47,"stem":48,"icon":49},"Wide Events","\u002Flearn\u002Fwide-events","2.learn\u002F2.wide-events","i-lucide-layers",{"title":51,"path":52,"stem":53,"icon":54},"Structured Errors","\u002Flearn\u002Fstructured-errors","2.learn\u002F3.structured-errors","i-lucide-shield-alert",{"title":56,"path":57,"stem":58,"icon":59},"Lifecycle","\u002Flearn\u002Flifecycle","2.learn\u002F4.lifecycle","i-lucide-arrow-right-left",{"title":61,"path":62,"stem":63,"icon":64},"Sampling","\u002Flearn\u002Fsampling","2.learn\u002F5.sampling","i-lucide-filter",{"title":66,"path":67,"stem":68,"icon":69},"Auto-Redaction","\u002Flearn\u002Fredaction","2.learn\u002F6.redaction","i-lucide-eye-off",{"title":71,"path":72,"stem":73,"icon":74},"Typed Fields","\u002Flearn\u002Ftyped-fields","2.learn\u002F7.typed-fields","i-simple-icons-typescript",{"title":76,"path":77,"stem":78,"icon":79},"Catalogs","\u002Flearn\u002Fcatalogs","2.learn\u002F8.catalogs","i-lucide-book-open",{"title":81,"path":82,"stem":83,"children":84,"page":29},"Integrate","\u002Fintegrate","3.integrate",[85,89,157],{"title":36,"path":86,"stem":87,"icon":88},"\u002Fintegrate\u002Foverview","3.integrate\u002F0.overview","i-lucide-plug",{"title":90,"path":91,"stem":92,"children":93,"page":29},"Adapters","\u002Fintegrate\u002Fadapters","3.integrate\u002Fadapters",[94,97,137],{"title":36,"path":95,"stem":96,"icon":39},"\u002Fintegrate\u002Fadapters\u002Foverview","3.integrate\u002Fadapters\u002F01.overview",{"title":98,"path":99,"stem":100,"children":101,"page":29},"Cloud","\u002Fintegrate\u002Fadapters\u002Fcloud","3.integrate\u002Fadapters\u002Fcloud",[102,107,112,117,122,127,132],{"title":103,"path":104,"stem":105,"icon":106},"Axiom","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Faxiom","3.integrate\u002Fadapters\u002Fcloud\u002F01.axiom","i-custom-axiom",{"title":108,"path":109,"stem":110,"icon":111},"OTLP","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fotlp","3.integrate\u002Fadapters\u002Fcloud\u002F02.otlp","i-simple-icons-opentelemetry",{"title":113,"path":114,"stem":115,"icon":116},"PostHog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fposthog","3.integrate\u002Fadapters\u002Fcloud\u002F03.posthog","i-simple-icons-posthog",{"title":118,"path":119,"stem":120,"icon":121},"Sentry","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fsentry","3.integrate\u002Fadapters\u002Fcloud\u002F04.sentry","i-simple-icons-sentry",{"title":123,"path":124,"stem":125,"icon":126},"Better Stack","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fbetter-stack","3.integrate\u002Fadapters\u002Fcloud\u002F05.better-stack","i-simple-icons-betterstack",{"title":128,"path":129,"stem":130,"icon":131},"Datadog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fdatadog","3.integrate\u002Fadapters\u002Fcloud\u002F06.datadog","i-simple-icons-datadog",{"title":133,"path":134,"stem":135,"icon":136},"HyperDX","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fhyperdx","3.integrate\u002Fadapters\u002Fcloud\u002F07.hyperdx","i-custom-hyperdx",{"title":138,"path":139,"stem":140,"children":141,"page":29},"Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fself-hosted","3.integrate\u002Fadapters\u002Fself-hosted",[142,147,152],{"title":143,"path":144,"stem":145,"icon":146},"File System","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Ffs","3.integrate\u002Fadapters\u002Fself-hosted\u002F01.fs","i-lucide-hard-drive",{"title":148,"path":149,"stem":150,"icon":151},"NuxtHub","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fnuxthub","3.integrate\u002Fadapters\u002Fself-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":153,"path":154,"stem":155,"icon":156},"Memory","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fmemory","3.integrate\u002Fadapters\u002Fself-hosted\u002F03.memory","i-lucide-cpu",{"title":158,"path":159,"stem":160,"children":161,"page":29},"Frameworks","\u002Fintegrate\u002Fframeworks","3.integrate\u002Fframeworks",[162,166,171,176,181,186,191,196,201,206,211,216,221,226,230,235,240],{"title":36,"path":163,"stem":164,"icon":165},"\u002Fintegrate\u002Fframeworks\u002Foverview","3.integrate\u002Fframeworks\u002F00.overview","i-lucide-layout-grid",{"title":167,"path":168,"stem":169,"icon":170},"Nuxt","\u002Fintegrate\u002Fframeworks\u002Fnuxt","3.integrate\u002Fframeworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":172,"path":173,"stem":174,"icon":175},"Next.js","\u002Fintegrate\u002Fframeworks\u002Fnextjs","3.integrate\u002Fframeworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":177,"path":178,"stem":179,"icon":180},"SvelteKit","\u002Fintegrate\u002Fframeworks\u002Fsveltekit","3.integrate\u002Fframeworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":182,"path":183,"stem":184,"icon":185},"Nitro","\u002Fintegrate\u002Fframeworks\u002Fnitro","3.integrate\u002Fframeworks\u002F04.nitro","i-custom-nitro",{"title":187,"path":188,"stem":189,"icon":190},"TanStack Start","\u002Fintegrate\u002Fframeworks\u002Ftanstack-start","3.integrate\u002Fframeworks\u002F05.tanstack-start","i-custom-tanstack",{"title":192,"path":193,"stem":194,"icon":195},"NestJS","\u002Fintegrate\u002Fframeworks\u002Fnestjs","3.integrate\u002Fframeworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":197,"path":198,"stem":199,"icon":200},"Express","\u002Fintegrate\u002Fframeworks\u002Fexpress","3.integrate\u002Fframeworks\u002F07.express","i-simple-icons-express",{"title":202,"path":203,"stem":204,"icon":205},"Hono","\u002Fintegrate\u002Fframeworks\u002Fhono","3.integrate\u002Fframeworks\u002F08.hono","i-simple-icons-hono",{"title":207,"path":208,"stem":209,"icon":210},"Fastify","\u002Fintegrate\u002Fframeworks\u002Ffastify","3.integrate\u002Fframeworks\u002F09.fastify","i-simple-icons-fastify",{"title":212,"path":213,"stem":214,"icon":215},"Elysia","\u002Fintegrate\u002Fframeworks\u002Felysia","3.integrate\u002Fframeworks\u002F10.elysia","i-custom-elysia",{"title":217,"path":218,"stem":219,"icon":220},"React Router","\u002Fintegrate\u002Fframeworks\u002Freact-router","3.integrate\u002Fframeworks\u002F11.react-router","i-custom-reactrouter",{"title":222,"path":223,"stem":224,"icon":225},"Cloudflare Workers","\u002Fintegrate\u002Fframeworks\u002Fcloudflare-workers","3.integrate\u002Fframeworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":227,"path":228,"stem":229,"icon":74},"Standalone","\u002Fintegrate\u002Fframeworks\u002Fstandalone","3.integrate\u002Fframeworks\u002F13.standalone",{"title":231,"path":232,"stem":233,"icon":234},"Astro","\u002Fintegrate\u002Fframeworks\u002Fastro","3.integrate\u002Fframeworks\u002F14.astro","i-simple-icons-astro",{"title":236,"path":237,"stem":238,"icon":239},"oRPC","\u002Fintegrate\u002Fframeworks\u002Forpc","3.integrate\u002Fframeworks\u002F15.orpc","i-lucide-network",{"title":241,"path":242,"stem":243,"icon":244},"AWS Lambda","\u002Fintegrate\u002Fframeworks\u002Faws-lambda","3.integrate\u002Fframeworks\u002F16.aws-lambda","i-custom-lambda",{"title":246,"path":247,"stem":248,"children":249,"page":29},"Use Cases","\u002Fuse-cases","4.use-cases",[250,254,259,288,316,348,353,358],{"title":36,"path":251,"stem":252,"icon":253},"\u002Fuse-cases\u002Foverview","4.use-cases\u002F0.overview","i-lucide-list-checks",{"title":255,"path":256,"stem":257,"icon":258},"Client Logging","\u002Fuse-cases\u002Fclient-logging","4.use-cases\u002F1.client-logging","i-lucide-monitor",{"title":260,"icon":261,"path":262,"stem":263,"children":264,"page":29},"AI SDK","i-simple-icons-vercel","\u002Fuse-cases\u002Fai-sdk","4.use-cases\u002F2.ai-sdk",[265,268,273,278,283],{"title":36,"path":266,"stem":267,"icon":39},"\u002Fuse-cases\u002Fai-sdk\u002Foverview","4.use-cases\u002F2.ai-sdk\u002F01.overview",{"title":269,"path":270,"stem":271,"icon":272},"Usage","\u002Fuse-cases\u002Fai-sdk\u002Fusage","4.use-cases\u002F2.ai-sdk\u002F02.usage","i-lucide-code",{"title":274,"path":275,"stem":276,"icon":277},"Options","\u002Fuse-cases\u002Fai-sdk\u002Foptions","4.use-cases\u002F2.ai-sdk\u002F03.options","i-lucide-sliders",{"title":279,"path":280,"stem":281,"icon":282},"Metadata","\u002Fuse-cases\u002Fai-sdk\u002Fmetadata","4.use-cases\u002F2.ai-sdk\u002F04.metadata","i-lucide-database",{"title":284,"path":285,"stem":286,"icon":287},"Telemetry","\u002Fuse-cases\u002Fai-sdk\u002Ftelemetry","4.use-cases\u002F2.ai-sdk\u002F05.telemetry","i-lucide-activity",{"title":289,"icon":290,"path":291,"stem":292,"children":293,"page":29},"Better Auth","i-simple-icons-betterauth","\u002Fuse-cases\u002Fbetter-auth","4.use-cases\u002F3.better-auth",[294,297,302,307,311],{"title":36,"path":295,"stem":296,"icon":39},"\u002Fuse-cases\u002Fbetter-auth\u002Foverview","4.use-cases\u002F3.better-auth\u002F01.overview",{"title":298,"path":299,"stem":300,"icon":301},"Identify User","\u002Fuse-cases\u002Fbetter-auth\u002Fidentify-user","4.use-cases\u002F3.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":303,"path":304,"stem":305,"icon":306},"Middleware","\u002Fuse-cases\u002Fbetter-auth\u002Fmiddleware","4.use-cases\u002F3.better-auth\u002F03.middleware","i-lucide-shield",{"title":308,"path":309,"stem":310,"icon":258},"Client Sync","\u002Fuse-cases\u002Fbetter-auth\u002Fclient-sync","4.use-cases\u002F3.better-auth\u002F04.client-sync",{"title":312,"path":313,"stem":314,"icon":315},"Performance","\u002Fuse-cases\u002Fbetter-auth\u002Fperformance","4.use-cases\u002F3.better-auth\u002F05.performance","i-lucide-gauge",{"title":317,"icon":318,"path":319,"stem":320,"children":321,"page":29},"Audit Logs","i-lucide-shield-check","\u002Fuse-cases\u002Faudit","4.use-cases\u002F4.audit",[322,325,330,335,340,344],{"title":36,"path":323,"stem":324,"icon":39},"\u002Fuse-cases\u002Faudit\u002Foverview","4.use-cases\u002F4.audit\u002F01.overview",{"title":326,"path":327,"stem":328,"icon":329},"Schema","\u002Fuse-cases\u002Faudit\u002Fschema","4.use-cases\u002F4.audit\u002F02.schema","i-lucide-file-text",{"title":331,"path":332,"stem":333,"icon":334},"Recording","\u002Fuse-cases\u002Faudit\u002Frecording","4.use-cases\u002F4.audit\u002F03.recording","i-lucide-pen-line",{"title":336,"path":337,"stem":338,"icon":339},"Drains","\u002Fuse-cases\u002Faudit\u002Fpipeline","4.use-cases\u002F4.audit\u002F04.pipeline","i-lucide-link",{"title":341,"path":342,"stem":343,"icon":318},"Compliance","\u002Fuse-cases\u002Faudit\u002Fcompliance","4.use-cases\u002F4.audit\u002F05.compliance",{"title":345,"path":346,"stem":347,"icon":79},"Recipes","\u002Fuse-cases\u002Faudit\u002Frecipes","4.use-cases\u002F4.audit\u002F06.recipes",{"title":349,"path":350,"stem":351,"icon":352},"Enrichers","\u002Fuse-cases\u002Fenrichers","4.use-cases\u002F5.enrichers","i-lucide-sparkles",{"title":354,"path":355,"stem":356,"icon":357},"eve","\u002Fuse-cases\u002Feve","4.use-cases\u002F5.eve","i-custom-eve",{"title":284,"path":359,"stem":360,"children":361,"page":29},"\u002Fuse-cases\u002Ftelemetry","4.use-cases\u002F6.telemetry",[362],{"title":284,"path":363,"stem":364,"icon":315},"\u002Fuse-cases\u002Ftelemetry\u002Foverview","4.use-cases\u002F6.telemetry\u002F01.overview",{"title":366,"path":367,"stem":368,"children":369,"page":29},"Extend","\u002Fextend","5.extend",[370,374,379,384,389,393,397,401,405,410,415],{"title":36,"path":371,"stem":372,"icon":373},"\u002Fextend\u002Foverview","5.extend\u002F0.overview","i-lucide-blocks",{"title":375,"path":376,"stem":377,"icon":378},"Stream","\u002Fextend\u002Fstream","5.extend\u002F1.stream","i-lucide-radio-tower",{"title":380,"path":381,"stem":382,"icon":383},"Custom framework","\u002Fextend\u002Fcustom-framework","5.extend\u002F10.custom-framework","i-lucide-puzzle",{"title":385,"path":386,"stem":387,"icon":388},"FS reader","\u002Fextend\u002Ffs-reader","5.extend\u002F2.fs-reader","i-lucide-folder-search",{"title":345,"path":390,"stem":391,"icon":392},"\u002Fextend\u002Fconsumer-recipes","5.extend\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":394,"path":395,"stem":396,"icon":373},"Plugins","\u002Fextend\u002Fplugins","5.extend\u002F4.plugins",{"title":398,"path":399,"stem":400,"icon":352},"Custom enrichers","\u002Fextend\u002Fcustom-enrichers","5.extend\u002F5.custom-enrichers",{"title":402,"path":403,"stem":404,"icon":64},"Tail sampling","\u002Fextend\u002Ftail-sampling","5.extend\u002F6.tail-sampling",{"title":406,"path":407,"stem":408,"icon":409},"Identity headers","\u002Fextend\u002Fidentity-headers","5.extend\u002F7.identity-headers","i-lucide-fingerprint",{"title":411,"path":412,"stem":413,"icon":414},"Custom drains","\u002Fextend\u002Fcustom-drains","5.extend\u002F8.custom-drains","i-lucide-share-2",{"title":416,"path":417,"stem":418,"icon":419},"Drain pipeline","\u002Fextend\u002Fdrain-pipeline","5.extend\u002F9.drain-pipeline","i-lucide-workflow",{"title":421,"path":422,"stem":423,"children":424,"page":29},"Reference","\u002Freference","6.reference",[425,430,433,438,442,447],{"title":426,"path":427,"stem":428,"icon":429},"Configuration","\u002Freference\u002Fconfiguration","6.reference\u002F1.configuration","i-lucide-settings",{"title":312,"path":431,"stem":432,"icon":315},"\u002Freference\u002Fperformance","6.reference\u002F2.performance",{"title":434,"path":435,"stem":436,"icon":437},"Vite Plugin","\u002Freference\u002Fvite-plugin","6.reference\u002F3.vite-plugin","i-custom-vite",{"title":439,"path":440,"stem":441,"icon":318},"Best Practices","\u002Freference\u002Fbest-practices","6.reference\u002F4.best-practices",{"title":443,"path":444,"stem":445,"icon":446},"vs Other Loggers","\u002Freference\u002Fvs-other-loggers","6.reference\u002F5.vs-other-loggers","i-lucide-scale",{"title":448,"path":449,"stem":450,"icon":352},"Agent Skills","\u002Freference\u002Fagent-skills","6.reference\u002F6.agent-skills",{"id":452,"title":345,"body":453,"description":4270,"extension":4271,"links":4272,"meta":4273,"navigation":4274,"path":390,"seo":4275,"stem":391,"__hash__":4276},"docs\u002F5.extend\u002F3.consumer-recipes.md",{"type":454,"value":455,"toc":4257},"minimark",[456,469,544,549,570,575,1574,1581,1585,2193,2197,2563,2571,2575,2580,2634,2637,2741,2754,2758,2761,3181,3190,3194,3200,3698,3702,3705,4061,4065,4068,4227,4230,4234,4254],[457,458,459,460,464,465,468],"p",{},"Real-world patterns that combine the ",[461,462,463],"a",{"href":376},"in-process bus and stream server"," with the ",[461,466,467],{"href":386},"filesystem reader",".",[470,471,474,477,536],"prompt",{":actions":472,"description":473,"icon":392},"[\"copy\",\"cursor\",\"windsurf\"]","Build a custom evlog devtool \u002F dashboard",[457,475,476],{},"Bootstrap a local devtool or dashboard that consumes evlog wide events.",[478,479,480,493,504,523,530,533],"ul",{},[481,482,483,484,488,489,492],"li",{},"Pick the source: live (stream server over SSE) or history (",[485,486,487],"code",{},"readFsLogs"," from ",[485,490,491],{},".evlog\u002Flogs",") or both (replay then live tail)",[481,494,495,496,499,500,503],{},"For SSE: discover the URL via ",[485,497,498],{},".evlog\u002Fstream.url"," or ",[485,501,502],{},"GET \u002Fapi\u002F_evlog\u002Fstream-info",", never hard-code the port",[481,505,506,507,510,511,514,515,518,519,522],{},"Open an ",[485,508,509],{},"EventSource"," and decode messages as ",[485,512,513],{},"{ evlog: '1', type, data }"," envelopes (",[485,516,517],{},"type"," is ",[485,520,521],{},"hello | event | replay | ping",")",[481,524,525,526,529],{},"For browser tabs running on a different origin from the dev server, configure CORS via the stream server ",[485,527,528],{},"cors"," option and forward credentials carefully",[481,531,532],{},"Aggregate on the consumer side (counts, latency histograms, error groups) — keep the server simple",[481,534,535],{},"Skip on serverless platforms — the stream is in-process",[457,537,538,539],{},"Docs: ",[461,540,541],{"href":541,"rel":542},"https:\u002F\u002Fwww.evlog.dev\u002Fextend\u002Fconsumer-recipes",[543],"nofollow",[545,546,548],"h2",{"id":547},"_1-build-a-minimal-devtool","1. Build a minimal devtool",[457,550,551,552,554,555,557,558,561,562,564,565,569],{},"A live event panel is essentially ",[485,553,509],{}," + a list. The full wire format and discovery rules — ",[485,556,498],{},", ",[485,559,560],{},"\u002Fapi\u002F_evlog\u002Fstream-info",", the ",[485,563,513],{}," envelope, and auth — are documented on the ",[461,566,568],{"href":567},"\u002Fextend\u002Fstream#wire-format","stream page",". Each recipe below assumes you've grabbed the URL via either of those mechanisms.",[571,572,574],"h3",{"id":573},"vanilla-html-js-drop-into-any-page","Vanilla HTML + JS (drop into any page)",[576,577,582],"pre",{"className":578,"code":579,"language":580,"meta":581,"style":581},"language-html shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!doctype html>\n\u003Chtml>\n\u003Chead>\n  \u003Cmeta charset=\"utf-8\">\n  \u003Ctitle>evlog mini devtool\u003C\u002Ftitle>\n  \u003Cstyle>\n    body { font: 13px ui-sans-serif, system-ui; margin: 0; padding: 0; }\n    table { width: 100%; border-collapse: collapse; }\n    td, th { padding: 6px 10px; border-bottom: 1px solid #eee; text-align: left; }\n    .lvl-error { color: #ef4444 }\n    .lvl-warn  { color: #f59e0b }\n    .lvl-info  { color: #3b82f6 }\n  \u003C\u002Fstyle>\n\u003C\u002Fhead>\n\u003Cbody>\n  \u003Ctable id=\"t\">\n    \u003Cthead>\u003Ctr>\u003Cth>time\u003C\u002Fth>\u003Cth>level\u003C\u002Fth>\u003Cth>service\u003C\u002Fth>\u003Cth>action\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\n    \u003Ctbody>\u003C\u002Ftbody>\n  \u003C\u002Ftable>\n\n  \u003Cscript>\n    \u002F\u002F Replace with the URL printed at startup, or fetch it from \u002Fapi\u002F_evlog\u002Fstream-info\n    const STREAM_URL = 'http:\u002F\u002F127.0.0.1:51203'\n    const tbody = document.querySelector('#t tbody')\n    const es = new EventSource(STREAM_URL)\n\n    es.onmessage = (e) => {\n      const env = JSON.parse(e.data)\n      if (env.evlog !== '1') return\n      if (env.type !== 'event' && env.type !== 'replay') return\n\n      const w = env.data\n      const tr = document.createElement('tr')\n      tr.innerHTML = `\n        \u003Ctd>${new Date(w.timestamp).toLocaleTimeString()}\u003C\u002Ftd>\n        \u003Ctd class=\"lvl-${w.level}\">${w.level}\u003C\u002Ftd>\n        \u003Ctd>${w.service ?? ''}\u003C\u002Ftd>\n        \u003Ctd>${w.action ?? w.message ?? w.path ?? ''}\u003C\u002Ftd>\n      `\n      tbody.prepend(tr)\n      while (tbody.children.length > 200) tbody.lastElementChild.remove()\n    }\n  \u003C\u002Fscript>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html","",[485,583,584,604,614,624,650,672,682,737,767,823,848,870,891,901,910,920,942,1021,1035,1044,1051,1061,1068,1088,1121,1140,1145,1174,1204,1237,1281,1286,1303,1330,1346,1383,1415,1437,1475,1481,1498,1541,1547,1556,1565],{"__ignoreMap":581},[585,586,589,593,597,601],"span",{"class":587,"line":588},"line",1,[585,590,592],{"class":591},"sMK4o","\u003C!",[585,594,596],{"class":595},"swJcz","doctype",[585,598,600],{"class":599},"spNyl"," html",[585,602,603],{"class":591},">\n",[585,605,607,610,612],{"class":587,"line":606},2,[585,608,609],{"class":591},"\u003C",[585,611,580],{"class":595},[585,613,603],{"class":591},[585,615,617,619,622],{"class":587,"line":616},3,[585,618,609],{"class":591},[585,620,621],{"class":595},"head",[585,623,603],{"class":591},[585,625,627,630,633,636,639,642,646,648],{"class":587,"line":626},4,[585,628,629],{"class":591},"  \u003C",[585,631,632],{"class":595},"meta",[585,634,635],{"class":599}," charset",[585,637,638],{"class":591},"=",[585,640,641],{"class":591},"\"",[585,643,645],{"class":644},"sfazB","utf-8",[585,647,641],{"class":591},[585,649,603],{"class":591},[585,651,653,655,658,661,665,668,670],{"class":587,"line":652},5,[585,654,629],{"class":591},[585,656,657],{"class":595},"title",[585,659,660],{"class":591},">",[585,662,664],{"class":663},"sTEyZ","evlog mini devtool",[585,666,667],{"class":591},"\u003C\u002F",[585,669,657],{"class":595},[585,671,603],{"class":591},[585,673,675,677,680],{"class":587,"line":674},6,[585,676,629],{"class":591},[585,678,679],{"class":595},"style",[585,681,603],{"class":591},[585,683,685,689,692,696,699,703,706,709,712,715,718,720,723,725,728,730,732,734],{"class":587,"line":684},7,[585,686,688],{"class":687},"sBMFI","    body",[585,690,691],{"class":591}," {",[585,693,695],{"class":694},"sqsOY"," font",[585,697,698],{"class":591},":",[585,700,702],{"class":701},"sbssI"," 13px",[585,704,705],{"class":663}," ui-sans-serif",[585,707,708],{"class":591},",",[585,710,711],{"class":663}," system-ui",[585,713,714],{"class":591},";",[585,716,717],{"class":694}," margin",[585,719,698],{"class":591},[585,721,722],{"class":701}," 0",[585,724,714],{"class":591},[585,726,727],{"class":694}," padding",[585,729,698],{"class":591},[585,731,722],{"class":701},[585,733,714],{"class":591},[585,735,736],{"class":591}," }\n",[585,738,740,743,745,748,750,753,755,758,760,763,765],{"class":587,"line":739},8,[585,741,742],{"class":687},"    table",[585,744,691],{"class":591},[585,746,747],{"class":694}," width",[585,749,698],{"class":591},[585,751,752],{"class":701}," 100%",[585,754,714],{"class":591},[585,756,757],{"class":694}," border-collapse",[585,759,698],{"class":591},[585,761,762],{"class":663}," collapse",[585,764,714],{"class":591},[585,766,736],{"class":591},[585,768,770,773,775,778,780,782,784,787,790,792,795,797,800,803,806,809,811,814,816,819,821],{"class":587,"line":769},9,[585,771,772],{"class":687},"    td",[585,774,708],{"class":591},[585,776,777],{"class":687}," th",[585,779,691],{"class":591},[585,781,727],{"class":694},[585,783,698],{"class":591},[585,785,786],{"class":701}," 6px",[585,788,789],{"class":701}," 10px",[585,791,714],{"class":591},[585,793,794],{"class":694}," border-bottom",[585,796,698],{"class":591},[585,798,799],{"class":701}," 1px",[585,801,802],{"class":663}," solid ",[585,804,805],{"class":591},"#",[585,807,808],{"class":663},"eee",[585,810,714],{"class":591},[585,812,813],{"class":694}," text-align",[585,815,698],{"class":591},[585,817,818],{"class":663}," left",[585,820,714],{"class":591},[585,822,736],{"class":591},[585,824,826,829,832,834,837,839,842,845],{"class":587,"line":825},10,[585,827,828],{"class":591},"    .",[585,830,831],{"class":687},"lvl-error",[585,833,691],{"class":591},[585,835,836],{"class":694}," color",[585,838,698],{"class":591},[585,840,841],{"class":591}," #",[585,843,844],{"class":663},"ef4444 ",[585,846,847],{"class":591},"}\n",[585,849,851,853,856,859,861,863,865,868],{"class":587,"line":850},11,[585,852,828],{"class":591},[585,854,855],{"class":687},"lvl-warn",[585,857,858],{"class":591},"  {",[585,860,836],{"class":694},[585,862,698],{"class":591},[585,864,841],{"class":591},[585,866,867],{"class":663},"f59e0b ",[585,869,847],{"class":591},[585,871,873,875,878,880,882,884,886,889],{"class":587,"line":872},12,[585,874,828],{"class":591},[585,876,877],{"class":687},"lvl-info",[585,879,858],{"class":591},[585,881,836],{"class":694},[585,883,698],{"class":591},[585,885,841],{"class":591},[585,887,888],{"class":663},"3b82f6 ",[585,890,847],{"class":591},[585,892,894,897,899],{"class":587,"line":893},13,[585,895,896],{"class":591},"  \u003C\u002F",[585,898,679],{"class":595},[585,900,603],{"class":591},[585,902,904,906,908],{"class":587,"line":903},14,[585,905,667],{"class":591},[585,907,621],{"class":595},[585,909,603],{"class":591},[585,911,913,915,918],{"class":587,"line":912},15,[585,914,609],{"class":591},[585,916,917],{"class":595},"body",[585,919,603],{"class":591},[585,921,923,925,928,931,933,935,938,940],{"class":587,"line":922},16,[585,924,629],{"class":591},[585,926,927],{"class":595},"table",[585,929,930],{"class":599}," id",[585,932,638],{"class":591},[585,934,641],{"class":591},[585,936,937],{"class":644},"t",[585,939,641],{"class":591},[585,941,603],{"class":591},[585,943,945,948,951,954,957,959,962,964,967,969,971,973,975,977,980,982,984,986,988,990,993,995,997,999,1001,1003,1006,1008,1010,1013,1015,1017,1019],{"class":587,"line":944},17,[585,946,947],{"class":591},"    \u003C",[585,949,950],{"class":595},"thead",[585,952,953],{"class":591},">\u003C",[585,955,956],{"class":595},"tr",[585,958,953],{"class":591},[585,960,961],{"class":595},"th",[585,963,660],{"class":591},[585,965,966],{"class":663},"time",[585,968,667],{"class":591},[585,970,961],{"class":595},[585,972,953],{"class":591},[585,974,961],{"class":595},[585,976,660],{"class":591},[585,978,979],{"class":663},"level",[585,981,667],{"class":591},[585,983,961],{"class":595},[585,985,953],{"class":591},[585,987,961],{"class":595},[585,989,660],{"class":591},[585,991,992],{"class":663},"service",[585,994,667],{"class":591},[585,996,961],{"class":595},[585,998,953],{"class":591},[585,1000,961],{"class":595},[585,1002,660],{"class":591},[585,1004,1005],{"class":663},"action",[585,1007,667],{"class":591},[585,1009,961],{"class":595},[585,1011,1012],{"class":591},">\u003C\u002F",[585,1014,956],{"class":595},[585,1016,1012],{"class":591},[585,1018,950],{"class":595},[585,1020,603],{"class":591},[585,1022,1024,1026,1029,1031,1033],{"class":587,"line":1023},18,[585,1025,947],{"class":591},[585,1027,1028],{"class":595},"tbody",[585,1030,1012],{"class":591},[585,1032,1028],{"class":595},[585,1034,603],{"class":591},[585,1036,1038,1040,1042],{"class":587,"line":1037},19,[585,1039,896],{"class":591},[585,1041,927],{"class":595},[585,1043,603],{"class":591},[585,1045,1047],{"class":587,"line":1046},20,[585,1048,1050],{"emptyLinePlaceholder":1049},true,"\n",[585,1052,1054,1056,1059],{"class":587,"line":1053},21,[585,1055,629],{"class":591},[585,1057,1058],{"class":595},"script",[585,1060,603],{"class":591},[585,1062,1064],{"class":587,"line":1063},22,[585,1065,1067],{"class":1066},"sHwdD","    \u002F\u002F Replace with the URL printed at startup, or fetch it from \u002Fapi\u002F_evlog\u002Fstream-info\n",[585,1069,1071,1074,1077,1079,1082,1085],{"class":587,"line":1070},23,[585,1072,1073],{"class":599},"    const",[585,1075,1076],{"class":663}," STREAM_URL ",[585,1078,638],{"class":591},[585,1080,1081],{"class":591}," '",[585,1083,1084],{"class":644},"http:\u002F\u002F127.0.0.1:51203",[585,1086,1087],{"class":591},"'\n",[585,1089,1091,1093,1096,1098,1101,1103,1107,1110,1113,1116,1118],{"class":587,"line":1090},24,[585,1092,1073],{"class":599},[585,1094,1095],{"class":663}," tbody ",[585,1097,638],{"class":591},[585,1099,1100],{"class":663}," document",[585,1102,468],{"class":591},[585,1104,1106],{"class":1105},"s2Zo4","querySelector",[585,1108,1109],{"class":663},"(",[585,1111,1112],{"class":591},"'",[585,1114,1115],{"class":644},"#t tbody",[585,1117,1112],{"class":591},[585,1119,1120],{"class":663},")\n",[585,1122,1124,1126,1129,1131,1134,1137],{"class":587,"line":1123},25,[585,1125,1073],{"class":599},[585,1127,1128],{"class":663}," es ",[585,1130,638],{"class":591},[585,1132,1133],{"class":591}," new",[585,1135,1136],{"class":1105}," EventSource",[585,1138,1139],{"class":663},"(STREAM_URL)\n",[585,1141,1143],{"class":587,"line":1142},26,[585,1144,1050],{"emptyLinePlaceholder":1049},[585,1146,1148,1151,1153,1156,1159,1162,1166,1168,1171],{"class":587,"line":1147},27,[585,1149,1150],{"class":663},"    es",[585,1152,468],{"class":591},[585,1154,1155],{"class":1105},"onmessage",[585,1157,1158],{"class":591}," =",[585,1160,1161],{"class":591}," (",[585,1163,1165],{"class":1164},"sHdIc","e",[585,1167,522],{"class":591},[585,1169,1170],{"class":599}," =>",[585,1172,1173],{"class":591}," {\n",[585,1175,1177,1180,1183,1185,1188,1190,1193,1195,1197,1199,1202],{"class":587,"line":1176},28,[585,1178,1179],{"class":599},"      const",[585,1181,1182],{"class":663}," env",[585,1184,1158],{"class":591},[585,1186,1187],{"class":663}," JSON",[585,1189,468],{"class":591},[585,1191,1192],{"class":1105},"parse",[585,1194,1109],{"class":595},[585,1196,1165],{"class":663},[585,1198,468],{"class":591},[585,1200,1201],{"class":663},"data",[585,1203,1120],{"class":595},[585,1205,1207,1211,1213,1216,1218,1221,1224,1226,1229,1231,1234],{"class":587,"line":1206},29,[585,1208,1210],{"class":1209},"s7zQu","      if",[585,1212,1161],{"class":595},[585,1214,1215],{"class":663},"env",[585,1217,468],{"class":591},[585,1219,1220],{"class":663},"evlog",[585,1222,1223],{"class":591}," !==",[585,1225,1081],{"class":591},[585,1227,1228],{"class":644},"1",[585,1230,1112],{"class":591},[585,1232,1233],{"class":595},") ",[585,1235,1236],{"class":1209},"return\n",[585,1238,1240,1242,1244,1246,1248,1250,1252,1254,1257,1259,1262,1264,1266,1268,1270,1272,1275,1277,1279],{"class":587,"line":1239},30,[585,1241,1210],{"class":1209},[585,1243,1161],{"class":595},[585,1245,1215],{"class":663},[585,1247,468],{"class":591},[585,1249,517],{"class":663},[585,1251,1223],{"class":591},[585,1253,1081],{"class":591},[585,1255,1256],{"class":644},"event",[585,1258,1112],{"class":591},[585,1260,1261],{"class":591}," &&",[585,1263,1182],{"class":663},[585,1265,468],{"class":591},[585,1267,517],{"class":663},[585,1269,1223],{"class":591},[585,1271,1081],{"class":591},[585,1273,1274],{"class":644},"replay",[585,1276,1112],{"class":591},[585,1278,1233],{"class":595},[585,1280,1236],{"class":1209},[585,1282,1284],{"class":587,"line":1283},31,[585,1285,1050],{"emptyLinePlaceholder":1049},[585,1287,1289,1291,1294,1296,1298,1300],{"class":587,"line":1288},32,[585,1290,1179],{"class":599},[585,1292,1293],{"class":663}," w",[585,1295,1158],{"class":591},[585,1297,1182],{"class":663},[585,1299,468],{"class":591},[585,1301,1302],{"class":663},"data\n",[585,1304,1306,1308,1311,1313,1315,1317,1320,1322,1324,1326,1328],{"class":587,"line":1305},33,[585,1307,1179],{"class":599},[585,1309,1310],{"class":663}," tr",[585,1312,1158],{"class":591},[585,1314,1100],{"class":663},[585,1316,468],{"class":591},[585,1318,1319],{"class":1105},"createElement",[585,1321,1109],{"class":595},[585,1323,1112],{"class":591},[585,1325,956],{"class":644},[585,1327,1112],{"class":591},[585,1329,1120],{"class":595},[585,1331,1333,1336,1338,1341,1343],{"class":587,"line":1332},34,[585,1334,1335],{"class":663},"      tr",[585,1337,468],{"class":591},[585,1339,1340],{"class":663},"innerHTML",[585,1342,1158],{"class":591},[585,1344,1345],{"class":591}," `\n",[585,1347,1349,1352,1355,1358,1361,1364,1366,1369,1371,1374,1377,1380],{"class":587,"line":1348},35,[585,1350,1351],{"class":644},"        \u003Ctd>",[585,1353,1354],{"class":591},"${",[585,1356,1357],{"class":591},"new",[585,1359,1360],{"class":1105}," Date",[585,1362,1363],{"class":663},"(w",[585,1365,468],{"class":591},[585,1367,1368],{"class":663},"timestamp)",[585,1370,468],{"class":591},[585,1372,1373],{"class":1105},"toLocaleTimeString",[585,1375,1376],{"class":663},"()",[585,1378,1379],{"class":591},"}",[585,1381,1382],{"class":644},"\u003C\u002Ftd>\n",[585,1384,1386,1389,1391,1394,1396,1398,1400,1403,1405,1407,1409,1411,1413],{"class":587,"line":1385},36,[585,1387,1388],{"class":644},"        \u003Ctd class=\"lvl-",[585,1390,1354],{"class":591},[585,1392,1393],{"class":663},"w",[585,1395,468],{"class":591},[585,1397,979],{"class":663},[585,1399,1379],{"class":591},[585,1401,1402],{"class":644},"\">",[585,1404,1354],{"class":591},[585,1406,1393],{"class":663},[585,1408,468],{"class":591},[585,1410,979],{"class":663},[585,1412,1379],{"class":591},[585,1414,1382],{"class":644},[585,1416,1418,1420,1422,1424,1426,1429,1432,1435],{"class":587,"line":1417},37,[585,1419,1351],{"class":644},[585,1421,1354],{"class":591},[585,1423,1393],{"class":663},[585,1425,468],{"class":591},[585,1427,1428],{"class":663},"service ",[585,1430,1431],{"class":591},"??",[585,1433,1434],{"class":591}," ''}",[585,1436,1382],{"class":644},[585,1438,1440,1442,1444,1446,1448,1451,1453,1455,1457,1460,1462,1464,1466,1469,1471,1473],{"class":587,"line":1439},38,[585,1441,1351],{"class":644},[585,1443,1354],{"class":591},[585,1445,1393],{"class":663},[585,1447,468],{"class":591},[585,1449,1450],{"class":663},"action ",[585,1452,1431],{"class":591},[585,1454,1293],{"class":663},[585,1456,468],{"class":591},[585,1458,1459],{"class":663},"message ",[585,1461,1431],{"class":591},[585,1463,1293],{"class":663},[585,1465,468],{"class":591},[585,1467,1468],{"class":663},"path ",[585,1470,1431],{"class":591},[585,1472,1434],{"class":591},[585,1474,1382],{"class":644},[585,1476,1478],{"class":587,"line":1477},39,[585,1479,1480],{"class":591},"      `\n",[585,1482,1484,1487,1489,1492,1494,1496],{"class":587,"line":1483},40,[585,1485,1486],{"class":663},"      tbody",[585,1488,468],{"class":591},[585,1490,1491],{"class":1105},"prepend",[585,1493,1109],{"class":595},[585,1495,956],{"class":663},[585,1497,1120],{"class":595},[585,1499,1501,1504,1506,1508,1510,1513,1515,1518,1521,1524,1526,1528,1530,1533,1535,1538],{"class":587,"line":1500},41,[585,1502,1503],{"class":1209},"      while",[585,1505,1161],{"class":595},[585,1507,1028],{"class":663},[585,1509,468],{"class":591},[585,1511,1512],{"class":663},"children",[585,1514,468],{"class":591},[585,1516,1517],{"class":663},"length",[585,1519,1520],{"class":591}," >",[585,1522,1523],{"class":701}," 200",[585,1525,1233],{"class":595},[585,1527,1028],{"class":663},[585,1529,468],{"class":591},[585,1531,1532],{"class":663},"lastElementChild",[585,1534,468],{"class":591},[585,1536,1537],{"class":1105},"remove",[585,1539,1540],{"class":595},"()\n",[585,1542,1544],{"class":587,"line":1543},42,[585,1545,1546],{"class":591},"    }\n",[585,1548,1550,1552,1554],{"class":587,"line":1549},43,[585,1551,896],{"class":591},[585,1553,1058],{"class":595},[585,1555,603],{"class":591},[585,1557,1559,1561,1563],{"class":587,"line":1558},44,[585,1560,667],{"class":591},[585,1562,917],{"class":595},[585,1564,603],{"class":591},[585,1566,1568,1570,1572],{"class":587,"line":1567},45,[585,1569,667],{"class":591},[585,1571,580],{"class":595},[585,1573,603],{"class":591},[457,1575,1576,1577,1580],{},"Save as ",[485,1578,1579],{},"devtool.html",", open in any browser tab while your evlog-instrumented dev server is running. That's the whole MVP.",[571,1582,1584],{"id":1583},"vue-3-component","Vue 3 component",[576,1586,1590],{"className":1587,"code":1588,"language":1589,"meta":581,"style":581},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref } from 'vue'\nimport type { WideEvent } from 'evlog'\n\nconst events = ref\u003CWideEvent[]>([])\nlet es: EventSource | null = null\n\nonMounted(async () => {\n  \u002F\u002F Discover URL via the same-origin info endpoint (Nuxt)\n  const { url } = await $fetch\u003C{ url: string | null }>('\u002Fapi\u002F_evlog\u002Fstream-info')\n  if (!url) return\n\n  es = new EventSource(url)\n  es.onmessage = (e) => {\n    const env = JSON.parse(e.data)\n    if (env.evlog !== '1') return\n    if (env.type === 'event' || env.type === 'replay') {\n      events.value.unshift(env.data as WideEvent)\n      if (events.value.length > 500) events.value.length = 500\n    }\n  }\n})\n\nonBeforeUnmount(() => es?.close())\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cul>\n    \u003Cli v-for=\"(e, i) in events\" :key=\"`${e.timestamp}-${i}`\">\n      \u003Ccode>{{ e.level }}\u003C\u002Fcode>\n      \u003Cstrong>{{ e.service }}\u003C\u002Fstrong>\n      \u003Cspan>{{ e.action ?? e.message ?? e.path }}\u003C\u002Fspan>\n    \u003C\u002Fli>\n  \u003C\u002Ful>\n\u003C\u002Ftemplate>\n","vue",[485,1591,1592,1615,1647,1669,1673,1698,1721,1725,1742,1747,1794,1811,1815,1832,1852,1876,1901,1944,1974,2013,2017,2022,2028,2032,2054,2062,2066,2075,2083,2115,2133,2151,2168,2177,2185],{"__ignoreMap":581},[585,1593,1594,1596,1598,1601,1604,1606,1608,1611,1613],{"class":587,"line":588},[585,1595,609],{"class":591},[585,1597,1058],{"class":595},[585,1599,1600],{"class":599}," setup",[585,1602,1603],{"class":599}," lang",[585,1605,638],{"class":591},[585,1607,641],{"class":591},[585,1609,1610],{"class":644},"ts",[585,1612,641],{"class":591},[585,1614,603],{"class":591},[585,1616,1617,1620,1622,1625,1627,1630,1632,1635,1638,1641,1643,1645],{"class":587,"line":606},[585,1618,1619],{"class":1209},"import",[585,1621,691],{"class":591},[585,1623,1624],{"class":663}," onBeforeUnmount",[585,1626,708],{"class":591},[585,1628,1629],{"class":663}," onMounted",[585,1631,708],{"class":591},[585,1633,1634],{"class":663}," ref",[585,1636,1637],{"class":591}," }",[585,1639,1640],{"class":1209}," from",[585,1642,1081],{"class":591},[585,1644,1589],{"class":644},[585,1646,1087],{"class":591},[585,1648,1649,1651,1654,1656,1659,1661,1663,1665,1667],{"class":587,"line":616},[585,1650,1619],{"class":1209},[585,1652,1653],{"class":1209}," type",[585,1655,691],{"class":591},[585,1657,1658],{"class":663}," WideEvent",[585,1660,1637],{"class":591},[585,1662,1640],{"class":1209},[585,1664,1081],{"class":591},[585,1666,1220],{"class":644},[585,1668,1087],{"class":591},[585,1670,1671],{"class":587,"line":626},[585,1672,1050],{"emptyLinePlaceholder":1049},[585,1674,1675,1678,1681,1683,1685,1687,1690,1693,1695],{"class":587,"line":652},[585,1676,1677],{"class":599},"const",[585,1679,1680],{"class":663}," events ",[585,1682,638],{"class":591},[585,1684,1634],{"class":1105},[585,1686,609],{"class":591},[585,1688,1689],{"class":687},"WideEvent",[585,1691,1692],{"class":663},"[]",[585,1694,660],{"class":591},[585,1696,1697],{"class":663},"([])\n",[585,1699,1700,1703,1706,1708,1710,1713,1716,1718],{"class":587,"line":674},[585,1701,1702],{"class":599},"let",[585,1704,1705],{"class":663}," es",[585,1707,698],{"class":591},[585,1709,1136],{"class":687},[585,1711,1712],{"class":591}," |",[585,1714,1715],{"class":687}," null",[585,1717,1158],{"class":591},[585,1719,1720],{"class":591}," null\n",[585,1722,1723],{"class":587,"line":684},[585,1724,1050],{"emptyLinePlaceholder":1049},[585,1726,1727,1730,1732,1735,1738,1740],{"class":587,"line":739},[585,1728,1729],{"class":1105},"onMounted",[585,1731,1109],{"class":663},[585,1733,1734],{"class":599},"async",[585,1736,1737],{"class":591}," ()",[585,1739,1170],{"class":599},[585,1741,1173],{"class":591},[585,1743,1744],{"class":587,"line":769},[585,1745,1746],{"class":1066},"  \u002F\u002F Discover URL via the same-origin info endpoint (Nuxt)\n",[585,1748,1749,1752,1754,1757,1759,1761,1764,1767,1770,1772,1774,1777,1779,1781,1784,1786,1788,1790,1792],{"class":587,"line":825},[585,1750,1751],{"class":599},"  const",[585,1753,691],{"class":591},[585,1755,1756],{"class":663}," url",[585,1758,1637],{"class":591},[585,1760,1158],{"class":591},[585,1762,1763],{"class":1209}," await",[585,1765,1766],{"class":1105}," $fetch",[585,1768,1769],{"class":591},"\u003C{",[585,1771,1756],{"class":595},[585,1773,698],{"class":591},[585,1775,1776],{"class":687}," string",[585,1778,1712],{"class":591},[585,1780,1715],{"class":687},[585,1782,1783],{"class":591}," }>",[585,1785,1109],{"class":595},[585,1787,1112],{"class":591},[585,1789,560],{"class":644},[585,1791,1112],{"class":591},[585,1793,1120],{"class":595},[585,1795,1796,1799,1801,1804,1807,1809],{"class":587,"line":850},[585,1797,1798],{"class":1209},"  if",[585,1800,1161],{"class":595},[585,1802,1803],{"class":591},"!",[585,1805,1806],{"class":663},"url",[585,1808,1233],{"class":595},[585,1810,1236],{"class":1209},[585,1812,1813],{"class":587,"line":872},[585,1814,1050],{"emptyLinePlaceholder":1049},[585,1816,1817,1820,1822,1824,1826,1828,1830],{"class":587,"line":893},[585,1818,1819],{"class":663},"  es",[585,1821,1158],{"class":591},[585,1823,1133],{"class":591},[585,1825,1136],{"class":1105},[585,1827,1109],{"class":595},[585,1829,1806],{"class":663},[585,1831,1120],{"class":595},[585,1833,1834,1836,1838,1840,1842,1844,1846,1848,1850],{"class":587,"line":903},[585,1835,1819],{"class":663},[585,1837,468],{"class":591},[585,1839,1155],{"class":1105},[585,1841,1158],{"class":591},[585,1843,1161],{"class":591},[585,1845,1165],{"class":1164},[585,1847,522],{"class":591},[585,1849,1170],{"class":599},[585,1851,1173],{"class":591},[585,1853,1854,1856,1858,1860,1862,1864,1866,1868,1870,1872,1874],{"class":587,"line":912},[585,1855,1073],{"class":599},[585,1857,1182],{"class":663},[585,1859,1158],{"class":591},[585,1861,1187],{"class":663},[585,1863,468],{"class":591},[585,1865,1192],{"class":1105},[585,1867,1109],{"class":595},[585,1869,1165],{"class":663},[585,1871,468],{"class":591},[585,1873,1201],{"class":663},[585,1875,1120],{"class":595},[585,1877,1878,1881,1883,1885,1887,1889,1891,1893,1895,1897,1899],{"class":587,"line":922},[585,1879,1880],{"class":1209},"    if",[585,1882,1161],{"class":595},[585,1884,1215],{"class":663},[585,1886,468],{"class":591},[585,1888,1220],{"class":663},[585,1890,1223],{"class":591},[585,1892,1081],{"class":591},[585,1894,1228],{"class":644},[585,1896,1112],{"class":591},[585,1898,1233],{"class":595},[585,1900,1236],{"class":1209},[585,1902,1903,1905,1907,1909,1911,1913,1916,1918,1920,1922,1925,1927,1929,1931,1933,1935,1937,1939,1941],{"class":587,"line":944},[585,1904,1880],{"class":1209},[585,1906,1161],{"class":595},[585,1908,1215],{"class":663},[585,1910,468],{"class":591},[585,1912,517],{"class":663},[585,1914,1915],{"class":591}," ===",[585,1917,1081],{"class":591},[585,1919,1256],{"class":644},[585,1921,1112],{"class":591},[585,1923,1924],{"class":591}," ||",[585,1926,1182],{"class":663},[585,1928,468],{"class":591},[585,1930,517],{"class":663},[585,1932,1915],{"class":591},[585,1934,1081],{"class":591},[585,1936,1274],{"class":644},[585,1938,1112],{"class":591},[585,1940,1233],{"class":595},[585,1942,1943],{"class":591},"{\n",[585,1945,1946,1949,1951,1954,1956,1959,1961,1963,1965,1967,1970,1972],{"class":587,"line":1023},[585,1947,1948],{"class":663},"      events",[585,1950,468],{"class":591},[585,1952,1953],{"class":663},"value",[585,1955,468],{"class":591},[585,1957,1958],{"class":1105},"unshift",[585,1960,1109],{"class":595},[585,1962,1215],{"class":663},[585,1964,468],{"class":591},[585,1966,1201],{"class":663},[585,1968,1969],{"class":1209}," as",[585,1971,1658],{"class":687},[585,1973,1120],{"class":595},[585,1975,1976,1978,1980,1983,1985,1987,1989,1991,1993,1996,1998,2000,2002,2004,2006,2008,2010],{"class":587,"line":1037},[585,1977,1210],{"class":1209},[585,1979,1161],{"class":595},[585,1981,1982],{"class":663},"events",[585,1984,468],{"class":591},[585,1986,1953],{"class":663},[585,1988,468],{"class":591},[585,1990,1517],{"class":663},[585,1992,1520],{"class":591},[585,1994,1995],{"class":701}," 500",[585,1997,1233],{"class":595},[585,1999,1982],{"class":663},[585,2001,468],{"class":591},[585,2003,1953],{"class":663},[585,2005,468],{"class":591},[585,2007,1517],{"class":663},[585,2009,1158],{"class":591},[585,2011,2012],{"class":701}," 500\n",[585,2014,2015],{"class":587,"line":1046},[585,2016,1546],{"class":591},[585,2018,2019],{"class":587,"line":1053},[585,2020,2021],{"class":591},"  }\n",[585,2023,2024,2026],{"class":587,"line":1063},[585,2025,1379],{"class":591},[585,2027,1120],{"class":663},[585,2029,2030],{"class":587,"line":1070},[585,2031,1050],{"emptyLinePlaceholder":1049},[585,2033,2034,2037,2039,2041,2043,2045,2048,2051],{"class":587,"line":1090},[585,2035,2036],{"class":1105},"onBeforeUnmount",[585,2038,1109],{"class":663},[585,2040,1376],{"class":591},[585,2042,1170],{"class":599},[585,2044,1705],{"class":663},[585,2046,2047],{"class":591},"?.",[585,2049,2050],{"class":1105},"close",[585,2052,2053],{"class":663},"())\n",[585,2055,2056,2058,2060],{"class":587,"line":1123},[585,2057,667],{"class":591},[585,2059,1058],{"class":595},[585,2061,603],{"class":591},[585,2063,2064],{"class":587,"line":1142},[585,2065,1050],{"emptyLinePlaceholder":1049},[585,2067,2068,2070,2073],{"class":587,"line":1147},[585,2069,609],{"class":591},[585,2071,2072],{"class":595},"template",[585,2074,603],{"class":591},[585,2076,2077,2079,2081],{"class":587,"line":1176},[585,2078,629],{"class":591},[585,2080,478],{"class":595},[585,2082,603],{"class":591},[585,2084,2085,2087,2089,2092,2094,2096,2099,2101,2104,2106,2108,2111,2113],{"class":587,"line":1206},[585,2086,947],{"class":591},[585,2088,481],{"class":595},[585,2090,2091],{"class":599}," v-for",[585,2093,638],{"class":591},[585,2095,641],{"class":591},[585,2097,2098],{"class":644},"(e, i) in events",[585,2100,641],{"class":591},[585,2102,2103],{"class":599}," :key",[585,2105,638],{"class":591},[585,2107,641],{"class":591},[585,2109,2110],{"class":644},"`${e.timestamp}-${i}`",[585,2112,641],{"class":591},[585,2114,603],{"class":591},[585,2116,2117,2120,2122,2124,2127,2129,2131],{"class":587,"line":1239},[585,2118,2119],{"class":591},"      \u003C",[585,2121,485],{"class":595},[585,2123,660],{"class":591},[585,2125,2126],{"class":663},"{{ e.level }}",[585,2128,667],{"class":591},[585,2130,485],{"class":595},[585,2132,603],{"class":591},[585,2134,2135,2137,2140,2142,2145,2147,2149],{"class":587,"line":1283},[585,2136,2119],{"class":591},[585,2138,2139],{"class":595},"strong",[585,2141,660],{"class":591},[585,2143,2144],{"class":663},"{{ e.service }}",[585,2146,667],{"class":591},[585,2148,2139],{"class":595},[585,2150,603],{"class":591},[585,2152,2153,2155,2157,2159,2162,2164,2166],{"class":587,"line":1288},[585,2154,2119],{"class":591},[585,2156,585],{"class":595},[585,2158,660],{"class":591},[585,2160,2161],{"class":663},"{{ e.action ?? e.message ?? e.path }}",[585,2163,667],{"class":591},[585,2165,585],{"class":595},[585,2167,603],{"class":591},[585,2169,2170,2173,2175],{"class":587,"line":1305},[585,2171,2172],{"class":591},"    \u003C\u002F",[585,2174,481],{"class":595},[585,2176,603],{"class":591},[585,2178,2179,2181,2183],{"class":587,"line":1332},[585,2180,896],{"class":591},[585,2182,478],{"class":595},[585,2184,603],{"class":591},[585,2186,2187,2189,2191],{"class":587,"line":1348},[585,2188,667],{"class":591},[585,2190,2072],{"class":595},[585,2192,603],{"class":591},[571,2194,2196],{"id":2195},"react-hook","React hook",[576,2198,2201],{"className":2199,"code":2200,"language":1610,"meta":581,"style":581},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { useEffect, useState } from 'react'\nimport type { WideEvent } from 'evlog'\n\nexport function useEvlogStream(url: string) {\n  const [events, setEvents] = useState\u003CWideEvent[]>([])\n\n  useEffect(() => {\n    if (!url) return\n    const es = new EventSource(url)\n    es.onmessage = (e) => {\n      const env = JSON.parse(e.data)\n      if (env.evlog !== '1') return\n      if (env.type === 'event' || env.type === 'replay') {\n        setEvents(prev => [env.data, ...prev].slice(0, 500))\n      }\n    }\n    return () => es.close()\n  }, [url])\n\n  return events\n}\n",[485,2202,2203,2228,2248,2252,2275,2306,2310,2323,2337,2355,2375,2399,2423,2463,2509,2514,2518,2535,2547,2551,2559],{"__ignoreMap":581},[585,2204,2205,2207,2209,2212,2214,2217,2219,2221,2223,2226],{"class":587,"line":588},[585,2206,1619],{"class":1209},[585,2208,691],{"class":591},[585,2210,2211],{"class":663}," useEffect",[585,2213,708],{"class":591},[585,2215,2216],{"class":663}," useState",[585,2218,1637],{"class":591},[585,2220,1640],{"class":1209},[585,2222,1081],{"class":591},[585,2224,2225],{"class":644},"react",[585,2227,1087],{"class":591},[585,2229,2230,2232,2234,2236,2238,2240,2242,2244,2246],{"class":587,"line":606},[585,2231,1619],{"class":1209},[585,2233,1653],{"class":1209},[585,2235,691],{"class":591},[585,2237,1658],{"class":663},[585,2239,1637],{"class":591},[585,2241,1640],{"class":1209},[585,2243,1081],{"class":591},[585,2245,1220],{"class":644},[585,2247,1087],{"class":591},[585,2249,2250],{"class":587,"line":616},[585,2251,1050],{"emptyLinePlaceholder":1049},[585,2253,2254,2257,2260,2263,2265,2267,2269,2271,2273],{"class":587,"line":626},[585,2255,2256],{"class":1209},"export",[585,2258,2259],{"class":599}," function",[585,2261,2262],{"class":1105}," useEvlogStream",[585,2264,1109],{"class":591},[585,2266,1806],{"class":1164},[585,2268,698],{"class":591},[585,2270,1776],{"class":687},[585,2272,522],{"class":591},[585,2274,1173],{"class":591},[585,2276,2277,2279,2282,2284,2286,2289,2292,2294,2296,2298,2300,2302,2304],{"class":587,"line":652},[585,2278,1751],{"class":599},[585,2280,2281],{"class":591}," [",[585,2283,1982],{"class":663},[585,2285,708],{"class":591},[585,2287,2288],{"class":663}," setEvents",[585,2290,2291],{"class":591},"]",[585,2293,1158],{"class":591},[585,2295,2216],{"class":1105},[585,2297,609],{"class":591},[585,2299,1689],{"class":687},[585,2301,1692],{"class":595},[585,2303,660],{"class":591},[585,2305,1697],{"class":595},[585,2307,2308],{"class":587,"line":674},[585,2309,1050],{"emptyLinePlaceholder":1049},[585,2311,2312,2315,2317,2319,2321],{"class":587,"line":684},[585,2313,2314],{"class":1105},"  useEffect",[585,2316,1109],{"class":595},[585,2318,1376],{"class":591},[585,2320,1170],{"class":599},[585,2322,1173],{"class":591},[585,2324,2325,2327,2329,2331,2333,2335],{"class":587,"line":739},[585,2326,1880],{"class":1209},[585,2328,1161],{"class":595},[585,2330,1803],{"class":591},[585,2332,1806],{"class":663},[585,2334,1233],{"class":595},[585,2336,1236],{"class":1209},[585,2338,2339,2341,2343,2345,2347,2349,2351,2353],{"class":587,"line":769},[585,2340,1073],{"class":599},[585,2342,1705],{"class":663},[585,2344,1158],{"class":591},[585,2346,1133],{"class":591},[585,2348,1136],{"class":1105},[585,2350,1109],{"class":595},[585,2352,1806],{"class":663},[585,2354,1120],{"class":595},[585,2356,2357,2359,2361,2363,2365,2367,2369,2371,2373],{"class":587,"line":825},[585,2358,1150],{"class":663},[585,2360,468],{"class":591},[585,2362,1155],{"class":1105},[585,2364,1158],{"class":591},[585,2366,1161],{"class":591},[585,2368,1165],{"class":1164},[585,2370,522],{"class":591},[585,2372,1170],{"class":599},[585,2374,1173],{"class":591},[585,2376,2377,2379,2381,2383,2385,2387,2389,2391,2393,2395,2397],{"class":587,"line":850},[585,2378,1179],{"class":599},[585,2380,1182],{"class":663},[585,2382,1158],{"class":591},[585,2384,1187],{"class":663},[585,2386,468],{"class":591},[585,2388,1192],{"class":1105},[585,2390,1109],{"class":595},[585,2392,1165],{"class":663},[585,2394,468],{"class":591},[585,2396,1201],{"class":663},[585,2398,1120],{"class":595},[585,2400,2401,2403,2405,2407,2409,2411,2413,2415,2417,2419,2421],{"class":587,"line":872},[585,2402,1210],{"class":1209},[585,2404,1161],{"class":595},[585,2406,1215],{"class":663},[585,2408,468],{"class":591},[585,2410,1220],{"class":663},[585,2412,1223],{"class":591},[585,2414,1081],{"class":591},[585,2416,1228],{"class":644},[585,2418,1112],{"class":591},[585,2420,1233],{"class":595},[585,2422,1236],{"class":1209},[585,2424,2425,2427,2429,2431,2433,2435,2437,2439,2441,2443,2445,2447,2449,2451,2453,2455,2457,2459,2461],{"class":587,"line":893},[585,2426,1210],{"class":1209},[585,2428,1161],{"class":595},[585,2430,1215],{"class":663},[585,2432,468],{"class":591},[585,2434,517],{"class":663},[585,2436,1915],{"class":591},[585,2438,1081],{"class":591},[585,2440,1256],{"class":644},[585,2442,1112],{"class":591},[585,2444,1924],{"class":591},[585,2446,1182],{"class":663},[585,2448,468],{"class":591},[585,2450,517],{"class":663},[585,2452,1915],{"class":591},[585,2454,1081],{"class":591},[585,2456,1274],{"class":644},[585,2458,1112],{"class":591},[585,2460,1233],{"class":595},[585,2462,1943],{"class":591},[585,2464,2465,2468,2470,2473,2475,2477,2479,2481,2483,2485,2488,2490,2492,2494,2497,2499,2502,2504,2506],{"class":587,"line":903},[585,2466,2467],{"class":1105},"        setEvents",[585,2469,1109],{"class":595},[585,2471,2472],{"class":1164},"prev",[585,2474,1170],{"class":599},[585,2476,2281],{"class":595},[585,2478,1215],{"class":663},[585,2480,468],{"class":591},[585,2482,1201],{"class":663},[585,2484,708],{"class":591},[585,2486,2487],{"class":591}," ...",[585,2489,2472],{"class":663},[585,2491,2291],{"class":595},[585,2493,468],{"class":591},[585,2495,2496],{"class":1105},"slice",[585,2498,1109],{"class":595},[585,2500,2501],{"class":701},"0",[585,2503,708],{"class":591},[585,2505,1995],{"class":701},[585,2507,2508],{"class":595},"))\n",[585,2510,2511],{"class":587,"line":912},[585,2512,2513],{"class":591},"      }\n",[585,2515,2516],{"class":587,"line":922},[585,2517,1546],{"class":591},[585,2519,2520,2523,2525,2527,2529,2531,2533],{"class":587,"line":944},[585,2521,2522],{"class":1209},"    return",[585,2524,1737],{"class":591},[585,2526,1170],{"class":599},[585,2528,1705],{"class":663},[585,2530,468],{"class":591},[585,2532,2050],{"class":1105},[585,2534,1540],{"class":595},[585,2536,2537,2540,2542,2544],{"class":587,"line":1023},[585,2538,2539],{"class":591},"  },",[585,2541,2281],{"class":595},[585,2543,1806],{"class":663},[585,2545,2546],{"class":595},"])\n",[585,2548,2549],{"class":587,"line":1037},[585,2550,1050],{"emptyLinePlaceholder":1049},[585,2552,2553,2556],{"class":587,"line":1046},[585,2554,2555],{"class":1209},"  return",[585,2557,2558],{"class":663}," events\n",[585,2560,2561],{"class":587,"line":1053},[585,2562,847],{"class":591},[457,2564,2565,2566,2568,2569,468],{},"That's the entire integration surface. No SDK, no special types beyond ",[485,2567,1689],{}," exported from ",[485,2570,1220],{},[545,2572,2574],{"id":2573},"_2-quick-cli-inspection-with-curl-jq","2. Quick CLI inspection with curl + jq",[457,2576,2577,2578,698],{},"The URL is in ",[485,2579,498],{},[576,2581,2585],{"className":2582,"code":2583,"language":2584,"meta":581,"style":581},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","URL=$(cat .evlog\u002Fstream.url)\ncurl -N \"$URL\" | jq -c 'select(.type == \"event\") | .data'\n","bash",[485,2586,2587,2603],{"__ignoreMap":581},[585,2588,2589,2592,2595,2598,2601],{"class":587,"line":588},[585,2590,2591],{"class":663},"URL",[585,2593,2594],{"class":591},"=$(",[585,2596,2597],{"class":687},"cat",[585,2599,2600],{"class":644}," .evlog\u002Fstream.url",[585,2602,1120],{"class":591},[585,2604,2605,2608,2611,2614,2617,2619,2621,2624,2627,2629,2632],{"class":587,"line":606},[585,2606,2607],{"class":687},"curl",[585,2609,2610],{"class":644}," -N",[585,2612,2613],{"class":591}," \"",[585,2615,2616],{"class":663},"$URL",[585,2618,641],{"class":591},[585,2620,1712],{"class":591},[585,2622,2623],{"class":687}," jq",[585,2625,2626],{"class":644}," -c",[585,2628,1081],{"class":591},[585,2630,2631],{"class":644},"select(.type == \"event\") | .data",[585,2633,1087],{"class":591},[457,2635,2636],{},"Filter on the client side as needed:",[576,2638,2640],{"className":2582,"code":2639,"language":2584,"meta":581,"style":581},"# Only errors\ncurl -sN \"$URL\" | jq -c 'select(.type == \"event\" and .data.level == \"error\") | .data'\n\n# Only one service\ncurl -sN \"$URL\" | jq -c 'select(.type == \"event\" and .data.service == \"checkout\") | .data'\n\n# Slow requests\ncurl -sN \"$URL\" | jq -c 'select(.type == \"event\" and .data.duration > 500) | .data'\n",[485,2641,2642,2647,2673,2677,2682,2707,2711,2716],{"__ignoreMap":581},[585,2643,2644],{"class":587,"line":588},[585,2645,2646],{"class":1066},"# Only errors\n",[585,2648,2649,2651,2654,2656,2658,2660,2662,2664,2666,2668,2671],{"class":587,"line":606},[585,2650,2607],{"class":687},[585,2652,2653],{"class":644}," -sN",[585,2655,2613],{"class":591},[585,2657,2616],{"class":663},[585,2659,641],{"class":591},[585,2661,1712],{"class":591},[585,2663,2623],{"class":687},[585,2665,2626],{"class":644},[585,2667,1081],{"class":591},[585,2669,2670],{"class":644},"select(.type == \"event\" and .data.level == \"error\") | .data",[585,2672,1087],{"class":591},[585,2674,2675],{"class":587,"line":616},[585,2676,1050],{"emptyLinePlaceholder":1049},[585,2678,2679],{"class":587,"line":626},[585,2680,2681],{"class":1066},"# Only one service\n",[585,2683,2684,2686,2688,2690,2692,2694,2696,2698,2700,2702,2705],{"class":587,"line":652},[585,2685,2607],{"class":687},[585,2687,2653],{"class":644},[585,2689,2613],{"class":591},[585,2691,2616],{"class":663},[585,2693,641],{"class":591},[585,2695,1712],{"class":591},[585,2697,2623],{"class":687},[585,2699,2626],{"class":644},[585,2701,1081],{"class":591},[585,2703,2704],{"class":644},"select(.type == \"event\" and .data.service == \"checkout\") | .data",[585,2706,1087],{"class":591},[585,2708,2709],{"class":587,"line":674},[585,2710,1050],{"emptyLinePlaceholder":1049},[585,2712,2713],{"class":587,"line":684},[585,2714,2715],{"class":1066},"# Slow requests\n",[585,2717,2718,2720,2722,2724,2726,2728,2730,2732,2734,2736,2739],{"class":587,"line":739},[585,2719,2607],{"class":687},[585,2721,2653],{"class":644},[585,2723,2613],{"class":591},[585,2725,2616],{"class":663},[585,2727,641],{"class":591},[585,2729,1712],{"class":591},[585,2731,2623],{"class":687},[585,2733,2626],{"class":644},[585,2735,1081],{"class":591},[585,2737,2738],{"class":644},"select(.type == \"event\" and .data.duration > 500) | .data",[585,2740,1087],{"class":591},[457,2742,2743,2746,2747,2749,2750,2753],{},[485,2744,2745],{},"-N"," keeps ",[485,2748,2607],{}," in streaming mode (no buffering). ",[485,2751,2752],{},"-s"," is silent.",[545,2755,2757],{"id":2756},"_3-replay-history-then-go-live","3. Replay history then go live",[457,2759,2760],{},"History on disk (filesystem drain) + live updates from the stream server = a full picture from any point in time.",[576,2762,2764],{"className":2199,"code":2763,"language":1610,"meta":581,"style":581},"import { readFsLogs } from 'evlog\u002Ffs'\nimport { readFile } from 'node:fs\u002Fpromises'\nimport type { WideEvent } from 'evlog'\n\nasync function bootstrap(handle: (e: WideEvent) => void) {\n  \u002F\u002F 1. Replay the last hour from `.evlog\u002Flogs\u002F`\n  const since = new Date(Date.now() - 60 * 60 * 1000)\n  for await (const event of readFsLogs({ since })) {\n    handle(event)\n  }\n\n  \u002F\u002F 2. Switch to the live SSE stream\n  const url = (await readFile('.evlog\u002Fstream.url', 'utf-8')).trim()\n  const es = new EventSource(url)\n  es.onmessage = (e) => {\n    const env = JSON.parse(e.data)\n    if (env.evlog !== '1') return\n    if (env.type === 'event' || env.type === 'replay') {\n      handle(env.data)\n    }\n  }\n  return () => es.close()\n}\n",[485,2765,2766,2786,2806,2826,2830,2865,2870,2914,2947,2958,2962,2966,2971,3012,3030,3050,3074,3098,3138,3153,3157,3161,3177],{"__ignoreMap":581},[585,2767,2768,2770,2772,2775,2777,2779,2781,2784],{"class":587,"line":588},[585,2769,1619],{"class":1209},[585,2771,691],{"class":591},[585,2773,2774],{"class":663}," readFsLogs",[585,2776,1637],{"class":591},[585,2778,1640],{"class":1209},[585,2780,1081],{"class":591},[585,2782,2783],{"class":644},"evlog\u002Ffs",[585,2785,1087],{"class":591},[585,2787,2788,2790,2792,2795,2797,2799,2801,2804],{"class":587,"line":606},[585,2789,1619],{"class":1209},[585,2791,691],{"class":591},[585,2793,2794],{"class":663}," readFile",[585,2796,1637],{"class":591},[585,2798,1640],{"class":1209},[585,2800,1081],{"class":591},[585,2802,2803],{"class":644},"node:fs\u002Fpromises",[585,2805,1087],{"class":591},[585,2807,2808,2810,2812,2814,2816,2818,2820,2822,2824],{"class":587,"line":616},[585,2809,1619],{"class":1209},[585,2811,1653],{"class":1209},[585,2813,691],{"class":591},[585,2815,1658],{"class":663},[585,2817,1637],{"class":591},[585,2819,1640],{"class":1209},[585,2821,1081],{"class":591},[585,2823,1220],{"class":644},[585,2825,1087],{"class":591},[585,2827,2828],{"class":587,"line":626},[585,2829,1050],{"emptyLinePlaceholder":1049},[585,2831,2832,2834,2836,2839,2841,2844,2846,2848,2850,2852,2854,2856,2858,2861,2863],{"class":587,"line":652},[585,2833,1734],{"class":599},[585,2835,2259],{"class":599},[585,2837,2838],{"class":1105}," bootstrap",[585,2840,1109],{"class":591},[585,2842,2843],{"class":1105},"handle",[585,2845,698],{"class":591},[585,2847,1161],{"class":591},[585,2849,1165],{"class":1164},[585,2851,698],{"class":591},[585,2853,1658],{"class":687},[585,2855,522],{"class":591},[585,2857,1170],{"class":599},[585,2859,2860],{"class":687}," void",[585,2862,522],{"class":591},[585,2864,1173],{"class":591},[585,2866,2867],{"class":587,"line":674},[585,2868,2869],{"class":1066},"  \u002F\u002F 1. Replay the last hour from `.evlog\u002Flogs\u002F`\n",[585,2871,2872,2874,2877,2879,2881,2883,2885,2888,2890,2893,2896,2899,2902,2905,2907,2909,2912],{"class":587,"line":684},[585,2873,1751],{"class":599},[585,2875,2876],{"class":663}," since",[585,2878,1158],{"class":591},[585,2880,1133],{"class":591},[585,2882,1360],{"class":1105},[585,2884,1109],{"class":595},[585,2886,2887],{"class":663},"Date",[585,2889,468],{"class":591},[585,2891,2892],{"class":1105},"now",[585,2894,2895],{"class":595},"() ",[585,2897,2898],{"class":591},"-",[585,2900,2901],{"class":701}," 60",[585,2903,2904],{"class":591}," *",[585,2906,2901],{"class":701},[585,2908,2904],{"class":591},[585,2910,2911],{"class":701}," 1000",[585,2913,1120],{"class":595},[585,2915,2916,2919,2921,2923,2925,2928,2931,2933,2935,2938,2940,2942,2945],{"class":587,"line":739},[585,2917,2918],{"class":1209},"  for",[585,2920,1763],{"class":1209},[585,2922,1161],{"class":595},[585,2924,1677],{"class":599},[585,2926,2927],{"class":663}," event",[585,2929,2930],{"class":591}," of",[585,2932,2774],{"class":1105},[585,2934,1109],{"class":595},[585,2936,2937],{"class":591},"{",[585,2939,2876],{"class":663},[585,2941,1637],{"class":591},[585,2943,2944],{"class":595},")) ",[585,2946,1943],{"class":591},[585,2948,2949,2952,2954,2956],{"class":587,"line":769},[585,2950,2951],{"class":1105},"    handle",[585,2953,1109],{"class":595},[585,2955,1256],{"class":663},[585,2957,1120],{"class":595},[585,2959,2960],{"class":587,"line":825},[585,2961,2021],{"class":591},[585,2963,2964],{"class":587,"line":850},[585,2965,1050],{"emptyLinePlaceholder":1049},[585,2967,2968],{"class":587,"line":872},[585,2969,2970],{"class":1066},"  \u002F\u002F 2. Switch to the live SSE stream\n",[585,2972,2973,2975,2977,2979,2981,2984,2986,2988,2990,2992,2994,2996,2998,3000,3002,3005,3007,3010],{"class":587,"line":893},[585,2974,1751],{"class":599},[585,2976,1756],{"class":663},[585,2978,1158],{"class":591},[585,2980,1161],{"class":595},[585,2982,2983],{"class":1209},"await",[585,2985,2794],{"class":1105},[585,2987,1109],{"class":595},[585,2989,1112],{"class":591},[585,2991,498],{"class":644},[585,2993,1112],{"class":591},[585,2995,708],{"class":591},[585,2997,1081],{"class":591},[585,2999,645],{"class":644},[585,3001,1112],{"class":591},[585,3003,3004],{"class":595},"))",[585,3006,468],{"class":591},[585,3008,3009],{"class":1105},"trim",[585,3011,1540],{"class":595},[585,3013,3014,3016,3018,3020,3022,3024,3026,3028],{"class":587,"line":903},[585,3015,1751],{"class":599},[585,3017,1705],{"class":663},[585,3019,1158],{"class":591},[585,3021,1133],{"class":591},[585,3023,1136],{"class":1105},[585,3025,1109],{"class":595},[585,3027,1806],{"class":663},[585,3029,1120],{"class":595},[585,3031,3032,3034,3036,3038,3040,3042,3044,3046,3048],{"class":587,"line":912},[585,3033,1819],{"class":663},[585,3035,468],{"class":591},[585,3037,1155],{"class":1105},[585,3039,1158],{"class":591},[585,3041,1161],{"class":591},[585,3043,1165],{"class":1164},[585,3045,522],{"class":591},[585,3047,1170],{"class":599},[585,3049,1173],{"class":591},[585,3051,3052,3054,3056,3058,3060,3062,3064,3066,3068,3070,3072],{"class":587,"line":922},[585,3053,1073],{"class":599},[585,3055,1182],{"class":663},[585,3057,1158],{"class":591},[585,3059,1187],{"class":663},[585,3061,468],{"class":591},[585,3063,1192],{"class":1105},[585,3065,1109],{"class":595},[585,3067,1165],{"class":663},[585,3069,468],{"class":591},[585,3071,1201],{"class":663},[585,3073,1120],{"class":595},[585,3075,3076,3078,3080,3082,3084,3086,3088,3090,3092,3094,3096],{"class":587,"line":944},[585,3077,1880],{"class":1209},[585,3079,1161],{"class":595},[585,3081,1215],{"class":663},[585,3083,468],{"class":591},[585,3085,1220],{"class":663},[585,3087,1223],{"class":591},[585,3089,1081],{"class":591},[585,3091,1228],{"class":644},[585,3093,1112],{"class":591},[585,3095,1233],{"class":595},[585,3097,1236],{"class":1209},[585,3099,3100,3102,3104,3106,3108,3110,3112,3114,3116,3118,3120,3122,3124,3126,3128,3130,3132,3134,3136],{"class":587,"line":1023},[585,3101,1880],{"class":1209},[585,3103,1161],{"class":595},[585,3105,1215],{"class":663},[585,3107,468],{"class":591},[585,3109,517],{"class":663},[585,3111,1915],{"class":591},[585,3113,1081],{"class":591},[585,3115,1256],{"class":644},[585,3117,1112],{"class":591},[585,3119,1924],{"class":591},[585,3121,1182],{"class":663},[585,3123,468],{"class":591},[585,3125,517],{"class":663},[585,3127,1915],{"class":591},[585,3129,1081],{"class":591},[585,3131,1274],{"class":644},[585,3133,1112],{"class":591},[585,3135,1233],{"class":595},[585,3137,1943],{"class":591},[585,3139,3140,3143,3145,3147,3149,3151],{"class":587,"line":1037},[585,3141,3142],{"class":1105},"      handle",[585,3144,1109],{"class":595},[585,3146,1215],{"class":663},[585,3148,468],{"class":591},[585,3150,1201],{"class":663},[585,3152,1120],{"class":595},[585,3154,3155],{"class":587,"line":1046},[585,3156,1546],{"class":591},[585,3158,3159],{"class":587,"line":1053},[585,3160,2021],{"class":591},[585,3162,3163,3165,3167,3169,3171,3173,3175],{"class":587,"line":1063},[585,3164,2555],{"class":1209},[585,3166,1737],{"class":591},[585,3168,1170],{"class":599},[585,3170,1705],{"class":663},[585,3172,468],{"class":591},[585,3174,2050],{"class":1105},[585,3176,1540],{"class":595},[585,3178,3179],{"class":587,"line":1070},[585,3180,847],{"class":591},[457,3182,3183,3185,3186,3189],{},[485,3184,487],{}," skips files outside the date range, so the replay step is fast even if you keep weeks of history. For a tail-only mode without on-disk replay, hit the stream server with ",[485,3187,3188],{},"?since=\u003Ciso>"," to reuse the in-process ring buffer instead.",[545,3191,3193],{"id":3192},"_4-node-bun-client-fetch-readablestream","4. Node \u002F Bun client (fetch + ReadableStream)",[457,3195,3196,3197,3199],{},"Same protocol, no ",[485,3198,509],{}," polyfill needed:",[576,3201,3203],{"className":2199,"code":3202,"language":1610,"meta":581,"style":581},"import { readFile } from 'node:fs\u002Fpromises'\n\nconst url = (await readFile('.evlog\u002Fstream.url', 'utf-8')).trim()\nconst res = await fetch(url)\nconst reader = res.body!.getReader()\nconst decoder = new TextDecoder()\nlet buffer = ''\n\nwhile (true) {\n  const { value, done } = await reader.read()\n  if (done) break\n  buffer += decoder.decode(value, { stream: true })\n\n  let idx\n  while ((idx = buffer.indexOf('\\n\\n')) !== -1) {\n    const frame = buffer.slice(0, idx)\n    buffer = buffer.slice(idx + 2)\n    const dataLine = frame.split('\\n').find(l => l.startsWith('data:'))\n    if (!dataLine) continue\n    const env = JSON.parse(dataLine.slice(5).trim())\n    if (env.type === 'event') console.log(env.data)\n  }\n}\n",[485,3204,3205,3223,3227,3266,3283,3307,3323,3335,3339,3354,3384,3398,3434,3438,3446,3490,3516,3541,3599,3615,3650,3690,3694],{"__ignoreMap":581},[585,3206,3207,3209,3211,3213,3215,3217,3219,3221],{"class":587,"line":588},[585,3208,1619],{"class":1209},[585,3210,691],{"class":591},[585,3212,2794],{"class":663},[585,3214,1637],{"class":591},[585,3216,1640],{"class":1209},[585,3218,1081],{"class":591},[585,3220,2803],{"class":644},[585,3222,1087],{"class":591},[585,3224,3225],{"class":587,"line":606},[585,3226,1050],{"emptyLinePlaceholder":1049},[585,3228,3229,3231,3234,3236,3238,3240,3242,3244,3246,3248,3250,3252,3254,3256,3258,3260,3262,3264],{"class":587,"line":616},[585,3230,1677],{"class":599},[585,3232,3233],{"class":663}," url ",[585,3235,638],{"class":591},[585,3237,1161],{"class":663},[585,3239,2983],{"class":1209},[585,3241,2794],{"class":1105},[585,3243,1109],{"class":663},[585,3245,1112],{"class":591},[585,3247,498],{"class":644},[585,3249,1112],{"class":591},[585,3251,708],{"class":591},[585,3253,1081],{"class":591},[585,3255,645],{"class":644},[585,3257,1112],{"class":591},[585,3259,3004],{"class":663},[585,3261,468],{"class":591},[585,3263,3009],{"class":1105},[585,3265,1540],{"class":663},[585,3267,3268,3270,3273,3275,3277,3280],{"class":587,"line":626},[585,3269,1677],{"class":599},[585,3271,3272],{"class":663}," res ",[585,3274,638],{"class":591},[585,3276,1763],{"class":1209},[585,3278,3279],{"class":1105}," fetch",[585,3281,3282],{"class":663},"(url)\n",[585,3284,3285,3287,3290,3292,3295,3297,3299,3302,3305],{"class":587,"line":652},[585,3286,1677],{"class":599},[585,3288,3289],{"class":663}," reader ",[585,3291,638],{"class":591},[585,3293,3294],{"class":663}," res",[585,3296,468],{"class":591},[585,3298,917],{"class":663},[585,3300,3301],{"class":591},"!.",[585,3303,3304],{"class":1105},"getReader",[585,3306,1540],{"class":663},[585,3308,3309,3311,3314,3316,3318,3321],{"class":587,"line":674},[585,3310,1677],{"class":599},[585,3312,3313],{"class":663}," decoder ",[585,3315,638],{"class":591},[585,3317,1133],{"class":591},[585,3319,3320],{"class":1105}," TextDecoder",[585,3322,1540],{"class":663},[585,3324,3325,3327,3330,3332],{"class":587,"line":684},[585,3326,1702],{"class":599},[585,3328,3329],{"class":663}," buffer ",[585,3331,638],{"class":591},[585,3333,3334],{"class":591}," ''\n",[585,3336,3337],{"class":587,"line":739},[585,3338,1050],{"emptyLinePlaceholder":1049},[585,3340,3341,3344,3346,3350,3352],{"class":587,"line":769},[585,3342,3343],{"class":1209},"while",[585,3345,1161],{"class":663},[585,3347,3349],{"class":3348},"sfNiH","true",[585,3351,1233],{"class":663},[585,3353,1943],{"class":591},[585,3355,3356,3358,3360,3363,3365,3368,3370,3372,3374,3377,3379,3382],{"class":587,"line":825},[585,3357,1751],{"class":599},[585,3359,691],{"class":591},[585,3361,3362],{"class":663}," value",[585,3364,708],{"class":591},[585,3366,3367],{"class":663}," done",[585,3369,1637],{"class":591},[585,3371,1158],{"class":591},[585,3373,1763],{"class":1209},[585,3375,3376],{"class":663}," reader",[585,3378,468],{"class":591},[585,3380,3381],{"class":1105},"read",[585,3383,1540],{"class":595},[585,3385,3386,3388,3390,3393,3395],{"class":587,"line":850},[585,3387,1798],{"class":1209},[585,3389,1161],{"class":595},[585,3391,3392],{"class":663},"done",[585,3394,1233],{"class":595},[585,3396,3397],{"class":1209},"break\n",[585,3399,3400,3403,3406,3409,3411,3414,3416,3418,3420,3422,3425,3427,3430,3432],{"class":587,"line":872},[585,3401,3402],{"class":663},"  buffer",[585,3404,3405],{"class":591}," +=",[585,3407,3408],{"class":663}," decoder",[585,3410,468],{"class":591},[585,3412,3413],{"class":1105},"decode",[585,3415,1109],{"class":595},[585,3417,1953],{"class":663},[585,3419,708],{"class":591},[585,3421,691],{"class":591},[585,3423,3424],{"class":595}," stream",[585,3426,698],{"class":591},[585,3428,3429],{"class":3348}," true",[585,3431,1637],{"class":591},[585,3433,1120],{"class":595},[585,3435,3436],{"class":587,"line":893},[585,3437,1050],{"emptyLinePlaceholder":1049},[585,3439,3440,3443],{"class":587,"line":903},[585,3441,3442],{"class":599},"  let",[585,3444,3445],{"class":663}," idx\n",[585,3447,3448,3451,3454,3457,3459,3462,3464,3467,3469,3471,3474,3476,3478,3481,3484,3486,3488],{"class":587,"line":912},[585,3449,3450],{"class":1209},"  while",[585,3452,3453],{"class":595}," ((",[585,3455,3456],{"class":663},"idx",[585,3458,1158],{"class":591},[585,3460,3461],{"class":663}," buffer",[585,3463,468],{"class":591},[585,3465,3466],{"class":1105},"indexOf",[585,3468,1109],{"class":595},[585,3470,1112],{"class":591},[585,3472,3473],{"class":663},"\\n\\n",[585,3475,1112],{"class":591},[585,3477,2944],{"class":595},[585,3479,3480],{"class":591},"!==",[585,3482,3483],{"class":591}," -",[585,3485,1228],{"class":701},[585,3487,1233],{"class":595},[585,3489,1943],{"class":591},[585,3491,3492,3494,3497,3499,3501,3503,3505,3507,3509,3511,3514],{"class":587,"line":922},[585,3493,1073],{"class":599},[585,3495,3496],{"class":663}," frame",[585,3498,1158],{"class":591},[585,3500,3461],{"class":663},[585,3502,468],{"class":591},[585,3504,2496],{"class":1105},[585,3506,1109],{"class":595},[585,3508,2501],{"class":701},[585,3510,708],{"class":591},[585,3512,3513],{"class":663}," idx",[585,3515,1120],{"class":595},[585,3517,3518,3521,3523,3525,3527,3529,3531,3533,3536,3539],{"class":587,"line":944},[585,3519,3520],{"class":663},"    buffer",[585,3522,1158],{"class":591},[585,3524,3461],{"class":663},[585,3526,468],{"class":591},[585,3528,2496],{"class":1105},[585,3530,1109],{"class":595},[585,3532,3456],{"class":663},[585,3534,3535],{"class":591}," +",[585,3537,3538],{"class":701}," 2",[585,3540,1120],{"class":595},[585,3542,3543,3545,3548,3550,3552,3554,3557,3559,3561,3564,3566,3568,3570,3573,3575,3578,3580,3583,3585,3588,3590,3592,3595,3597],{"class":587,"line":1023},[585,3544,1073],{"class":599},[585,3546,3547],{"class":663}," dataLine",[585,3549,1158],{"class":591},[585,3551,3496],{"class":663},[585,3553,468],{"class":591},[585,3555,3556],{"class":1105},"split",[585,3558,1109],{"class":595},[585,3560,1112],{"class":591},[585,3562,3563],{"class":663},"\\n",[585,3565,1112],{"class":591},[585,3567,522],{"class":595},[585,3569,468],{"class":591},[585,3571,3572],{"class":1105},"find",[585,3574,1109],{"class":595},[585,3576,3577],{"class":1164},"l",[585,3579,1170],{"class":599},[585,3581,3582],{"class":663}," l",[585,3584,468],{"class":591},[585,3586,3587],{"class":1105},"startsWith",[585,3589,1109],{"class":595},[585,3591,1112],{"class":591},[585,3593,3594],{"class":644},"data:",[585,3596,1112],{"class":591},[585,3598,2508],{"class":595},[585,3600,3601,3603,3605,3607,3610,3612],{"class":587,"line":1037},[585,3602,1880],{"class":1209},[585,3604,1161],{"class":595},[585,3606,1803],{"class":591},[585,3608,3609],{"class":663},"dataLine",[585,3611,1233],{"class":595},[585,3613,3614],{"class":1209},"continue\n",[585,3616,3617,3619,3621,3623,3625,3627,3629,3631,3633,3635,3637,3639,3642,3644,3646,3648],{"class":587,"line":1046},[585,3618,1073],{"class":599},[585,3620,1182],{"class":663},[585,3622,1158],{"class":591},[585,3624,1187],{"class":663},[585,3626,468],{"class":591},[585,3628,1192],{"class":1105},[585,3630,1109],{"class":595},[585,3632,3609],{"class":663},[585,3634,468],{"class":591},[585,3636,2496],{"class":1105},[585,3638,1109],{"class":595},[585,3640,3641],{"class":701},"5",[585,3643,522],{"class":595},[585,3645,468],{"class":591},[585,3647,3009],{"class":1105},[585,3649,2053],{"class":595},[585,3651,3652,3654,3656,3658,3660,3662,3664,3666,3668,3670,3672,3675,3677,3680,3682,3684,3686,3688],{"class":587,"line":1053},[585,3653,1880],{"class":1209},[585,3655,1161],{"class":595},[585,3657,1215],{"class":663},[585,3659,468],{"class":591},[585,3661,517],{"class":663},[585,3663,1915],{"class":591},[585,3665,1081],{"class":591},[585,3667,1256],{"class":644},[585,3669,1112],{"class":591},[585,3671,1233],{"class":595},[585,3673,3674],{"class":663},"console",[585,3676,468],{"class":591},[585,3678,3679],{"class":1105},"log",[585,3681,1109],{"class":595},[585,3683,1215],{"class":663},[585,3685,468],{"class":591},[585,3687,1201],{"class":663},[585,3689,1120],{"class":595},[585,3691,3692],{"class":587,"line":1063},[585,3693,2021],{"class":591},[585,3695,3696],{"class":587,"line":1070},[585,3697,847],{"class":591},[545,3699,3701],{"id":3700},"_5-filter-transform-aggregate-on-the-consumer","5. Filter, transform, aggregate on the consumer",[457,3703,3704],{},"Keep the server dumb — every consumer picks what it cares about:",[576,3706,3708],{"className":2199,"code":3707,"language":1610,"meta":581,"style":581},"\u002F\u002F Just errors\nconst errors = events.filter(e => e.level === 'error')\n\n\u002F\u002F Slow requests\nconst slowReqs = events.filter(e => typeof e.duration === 'number' && e.duration > 500)\n\n\u002F\u002F Group by service\nconst byService = Object.groupBy(events, e => e.service)\n\n\u002F\u002F Rolling error rate (last 100 events)\nconst last100 = events.slice(0, 100)\nconst errorRate = last100.filter(e => e.level === 'error').length \u002F last100.length\n\n\u002F\u002F Ad-hoc cost analytics — works because evlog\u002Fai writes ai.* fields on every AI call\nconst totalCost = events\n  .filter(e => typeof e.ai?.estimatedCost === 'number')\n  .reduce((sum, e) => sum + (e.ai?.estimatedCost as number), 0)\n",[485,3709,3710,3715,3758,3762,3767,3821,3825,3830,3863,3867,3872,3898,3951,3955,3960,3971,4008],{"__ignoreMap":581},[585,3711,3712],{"class":587,"line":588},[585,3713,3714],{"class":1066},"\u002F\u002F Just errors\n",[585,3716,3717,3719,3722,3724,3727,3729,3732,3734,3736,3738,3741,3743,3746,3749,3751,3754,3756],{"class":587,"line":606},[585,3718,1677],{"class":599},[585,3720,3721],{"class":663}," errors ",[585,3723,638],{"class":591},[585,3725,3726],{"class":663}," events",[585,3728,468],{"class":591},[585,3730,3731],{"class":1105},"filter",[585,3733,1109],{"class":663},[585,3735,1165],{"class":1164},[585,3737,1170],{"class":599},[585,3739,3740],{"class":663}," e",[585,3742,468],{"class":591},[585,3744,3745],{"class":663},"level ",[585,3747,3748],{"class":591},"===",[585,3750,1081],{"class":591},[585,3752,3753],{"class":644},"error",[585,3755,1112],{"class":591},[585,3757,1120],{"class":663},[585,3759,3760],{"class":587,"line":616},[585,3761,1050],{"emptyLinePlaceholder":1049},[585,3763,3764],{"class":587,"line":626},[585,3765,3766],{"class":1066},"\u002F\u002F Slow requests\n",[585,3768,3769,3771,3774,3776,3778,3780,3782,3784,3786,3788,3791,3793,3795,3798,3800,3802,3805,3807,3809,3811,3813,3815,3817,3819],{"class":587,"line":652},[585,3770,1677],{"class":599},[585,3772,3773],{"class":663}," slowReqs ",[585,3775,638],{"class":591},[585,3777,3726],{"class":663},[585,3779,468],{"class":591},[585,3781,3731],{"class":1105},[585,3783,1109],{"class":663},[585,3785,1165],{"class":1164},[585,3787,1170],{"class":599},[585,3789,3790],{"class":591}," typeof",[585,3792,3740],{"class":663},[585,3794,468],{"class":591},[585,3796,3797],{"class":663},"duration ",[585,3799,3748],{"class":591},[585,3801,1081],{"class":591},[585,3803,3804],{"class":644},"number",[585,3806,1112],{"class":591},[585,3808,1261],{"class":591},[585,3810,3740],{"class":663},[585,3812,468],{"class":591},[585,3814,3797],{"class":663},[585,3816,660],{"class":591},[585,3818,1995],{"class":701},[585,3820,1120],{"class":663},[585,3822,3823],{"class":587,"line":674},[585,3824,1050],{"emptyLinePlaceholder":1049},[585,3826,3827],{"class":587,"line":684},[585,3828,3829],{"class":1066},"\u002F\u002F Group by service\n",[585,3831,3832,3834,3837,3839,3842,3844,3847,3850,3852,3854,3856,3858,3860],{"class":587,"line":739},[585,3833,1677],{"class":599},[585,3835,3836],{"class":663}," byService ",[585,3838,638],{"class":591},[585,3840,3841],{"class":663}," Object",[585,3843,468],{"class":591},[585,3845,3846],{"class":1105},"groupBy",[585,3848,3849],{"class":663},"(events",[585,3851,708],{"class":591},[585,3853,3740],{"class":1164},[585,3855,1170],{"class":599},[585,3857,3740],{"class":663},[585,3859,468],{"class":591},[585,3861,3862],{"class":663},"service)\n",[585,3864,3865],{"class":587,"line":769},[585,3866,1050],{"emptyLinePlaceholder":1049},[585,3868,3869],{"class":587,"line":825},[585,3870,3871],{"class":1066},"\u002F\u002F Rolling error rate (last 100 events)\n",[585,3873,3874,3876,3879,3881,3883,3885,3887,3889,3891,3893,3896],{"class":587,"line":850},[585,3875,1677],{"class":599},[585,3877,3878],{"class":663}," last100 ",[585,3880,638],{"class":591},[585,3882,3726],{"class":663},[585,3884,468],{"class":591},[585,3886,2496],{"class":1105},[585,3888,1109],{"class":663},[585,3890,2501],{"class":701},[585,3892,708],{"class":591},[585,3894,3895],{"class":701}," 100",[585,3897,1120],{"class":663},[585,3899,3900,3902,3905,3907,3910,3912,3914,3916,3918,3920,3922,3924,3926,3928,3930,3932,3934,3936,3938,3941,3944,3946,3948],{"class":587,"line":872},[585,3901,1677],{"class":599},[585,3903,3904],{"class":663}," errorRate ",[585,3906,638],{"class":591},[585,3908,3909],{"class":663}," last100",[585,3911,468],{"class":591},[585,3913,3731],{"class":1105},[585,3915,1109],{"class":663},[585,3917,1165],{"class":1164},[585,3919,1170],{"class":599},[585,3921,3740],{"class":663},[585,3923,468],{"class":591},[585,3925,3745],{"class":663},[585,3927,3748],{"class":591},[585,3929,1081],{"class":591},[585,3931,3753],{"class":644},[585,3933,1112],{"class":591},[585,3935,522],{"class":663},[585,3937,468],{"class":591},[585,3939,3940],{"class":663},"length ",[585,3942,3943],{"class":591},"\u002F",[585,3945,3909],{"class":663},[585,3947,468],{"class":591},[585,3949,3950],{"class":663},"length\n",[585,3952,3953],{"class":587,"line":893},[585,3954,1050],{"emptyLinePlaceholder":1049},[585,3956,3957],{"class":587,"line":903},[585,3958,3959],{"class":1066},"\u002F\u002F Ad-hoc cost analytics — works because evlog\u002Fai writes ai.* fields on every AI call\n",[585,3961,3962,3964,3967,3969],{"class":587,"line":912},[585,3963,1677],{"class":599},[585,3965,3966],{"class":663}," totalCost ",[585,3968,638],{"class":591},[585,3970,2558],{"class":663},[585,3972,3973,3976,3978,3980,3982,3984,3986,3988,3990,3993,3995,3998,4000,4002,4004,4006],{"class":587,"line":922},[585,3974,3975],{"class":591},"  .",[585,3977,3731],{"class":1105},[585,3979,1109],{"class":663},[585,3981,1165],{"class":1164},[585,3983,1170],{"class":599},[585,3985,3790],{"class":591},[585,3987,3740],{"class":663},[585,3989,468],{"class":591},[585,3991,3992],{"class":663},"ai",[585,3994,2047],{"class":591},[585,3996,3997],{"class":663},"estimatedCost ",[585,3999,3748],{"class":591},[585,4001,1081],{"class":591},[585,4003,3804],{"class":644},[585,4005,1112],{"class":591},[585,4007,1120],{"class":663},[585,4009,4010,4012,4015,4017,4019,4022,4024,4026,4028,4030,4033,4036,4039,4041,4043,4045,4047,4050,4053,4055,4057,4059],{"class":587,"line":944},[585,4011,3975],{"class":591},[585,4013,4014],{"class":1105},"reduce",[585,4016,1109],{"class":663},[585,4018,1109],{"class":591},[585,4020,4021],{"class":1164},"sum",[585,4023,708],{"class":591},[585,4025,3740],{"class":1164},[585,4027,522],{"class":591},[585,4029,1170],{"class":599},[585,4031,4032],{"class":663}," sum ",[585,4034,4035],{"class":591},"+",[585,4037,4038],{"class":663}," (e",[585,4040,468],{"class":591},[585,4042,3992],{"class":663},[585,4044,2047],{"class":591},[585,4046,3997],{"class":663},[585,4048,4049],{"class":1209},"as",[585,4051,4052],{"class":687}," number",[585,4054,522],{"class":663},[585,4056,708],{"class":591},[585,4058,722],{"class":701},[585,4060,1120],{"class":663},[545,4062,4064],{"id":4063},"_6-self-hosted-tail-f-replacement","6. Self-hosted \"tail -f\" replacement",[457,4066,4067],{},"Skip the network entirely if the consumer runs on the same machine:",[576,4069,4071],{"className":2199,"code":4070,"language":1610,"meta":581,"style":581},"import { tailFsLogs } from 'evlog\u002Ffs'\n\nconst ac = new AbortController()\nprocess.on('SIGINT', () => ac.abort())\n\nfor await (const event of tailFsLogs({ signal: ac.signal })) {\n  if (event.level === 'error') notifyOps(event)\n}\n",[485,4072,4073,4092,4096,4112,4147,4151,4192,4223],{"__ignoreMap":581},[585,4074,4075,4077,4079,4082,4084,4086,4088,4090],{"class":587,"line":588},[585,4076,1619],{"class":1209},[585,4078,691],{"class":591},[585,4080,4081],{"class":663}," tailFsLogs",[585,4083,1637],{"class":591},[585,4085,1640],{"class":1209},[585,4087,1081],{"class":591},[585,4089,2783],{"class":644},[585,4091,1087],{"class":591},[585,4093,4094],{"class":587,"line":606},[585,4095,1050],{"emptyLinePlaceholder":1049},[585,4097,4098,4100,4103,4105,4107,4110],{"class":587,"line":616},[585,4099,1677],{"class":599},[585,4101,4102],{"class":663}," ac ",[585,4104,638],{"class":591},[585,4106,1133],{"class":591},[585,4108,4109],{"class":1105}," AbortController",[585,4111,1540],{"class":663},[585,4113,4114,4117,4119,4122,4124,4126,4129,4131,4133,4135,4137,4140,4142,4145],{"class":587,"line":626},[585,4115,4116],{"class":663},"process",[585,4118,468],{"class":591},[585,4120,4121],{"class":1105},"on",[585,4123,1109],{"class":663},[585,4125,1112],{"class":591},[585,4127,4128],{"class":644},"SIGINT",[585,4130,1112],{"class":591},[585,4132,708],{"class":591},[585,4134,1737],{"class":591},[585,4136,1170],{"class":599},[585,4138,4139],{"class":663}," ac",[585,4141,468],{"class":591},[585,4143,4144],{"class":1105},"abort",[585,4146,2053],{"class":663},[585,4148,4149],{"class":587,"line":652},[585,4150,1050],{"emptyLinePlaceholder":1049},[585,4152,4153,4156,4158,4160,4162,4165,4168,4170,4172,4174,4177,4179,4181,4183,4186,4188,4190],{"class":587,"line":674},[585,4154,4155],{"class":1209},"for",[585,4157,1763],{"class":1209},[585,4159,1161],{"class":663},[585,4161,1677],{"class":599},[585,4163,4164],{"class":663}," event ",[585,4166,4167],{"class":591},"of",[585,4169,4081],{"class":1105},[585,4171,1109],{"class":663},[585,4173,2937],{"class":591},[585,4175,4176],{"class":595}," signal",[585,4178,698],{"class":591},[585,4180,4139],{"class":663},[585,4182,468],{"class":591},[585,4184,4185],{"class":663},"signal ",[585,4187,1379],{"class":591},[585,4189,2944],{"class":663},[585,4191,1943],{"class":591},[585,4193,4194,4196,4198,4200,4202,4204,4206,4208,4210,4212,4214,4217,4219,4221],{"class":587,"line":684},[585,4195,1798],{"class":1209},[585,4197,1161],{"class":595},[585,4199,1256],{"class":663},[585,4201,468],{"class":591},[585,4203,979],{"class":663},[585,4205,1915],{"class":591},[585,4207,1081],{"class":591},[585,4209,3753],{"class":644},[585,4211,1112],{"class":591},[585,4213,1233],{"class":595},[585,4215,4216],{"class":1105},"notifyOps",[585,4218,1109],{"class":595},[585,4220,1256],{"class":663},[585,4222,1120],{"class":595},[585,4224,4225],{"class":587,"line":739},[585,4226,847],{"class":591},[457,4228,4229],{},"Works without instrumenting the running app — useful for sidecar \u002F observer processes that watch a directory.",[545,4231,4233],{"id":4232},"what-not-to-do","What not to do",[478,4235,4236,4242,4248],{},[481,4237,4238,4241],{},[2139,4239,4240],{},"Don't run the stream server on Vercel Functions \u002F Cloudflare Workers \u002F Lambda."," Each invocation is a separate isolate; subscribers in one isolate never see events emitted by other isolates. Use a real broker (Redis Streams, NATS, Pub\u002FSub) for cross-instance fan-out.",[481,4243,4244,4247],{},[2139,4245,4246],{},"Don't put auth-sensitive data in wide events"," unless your evlog config redacts them. The server relays exactly what your app emitted — including any unredacted PII.",[481,4249,4250,4253],{},[2139,4251,4252],{},"Don't filter at the server"," (\"only error events please\"). The server is purpose-built to be transparent. Filter on the consumer side; that way one filter doesn't starve another consumer.",[679,4255,4256],{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sqsOY, html code.shiki .sqsOY{--shiki-light:#8796B0;--shiki-default:#B2CCD6;--shiki-dark:#B2CCD6}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}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 .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 .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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":581,"searchDepth":606,"depth":606,"links":4258},[4259,4264,4265,4266,4267,4268,4269],{"id":547,"depth":606,"text":548,"children":4260},[4261,4262,4263],{"id":573,"depth":616,"text":574},{"id":1583,"depth":616,"text":1584},{"id":2195,"depth":616,"text":2196},{"id":2573,"depth":606,"text":2574},{"id":2756,"depth":606,"text":2757},{"id":3192,"depth":606,"text":3193},{"id":3700,"depth":606,"text":3701},{"id":4063,"depth":606,"text":4064},{"id":4232,"depth":606,"text":4233},"Concrete copy-paste recipes — build your own minimal devtool, pipe to curl + jq, replay history then go live, and aggregate on the consumer side.","md",null,{},{"title":345,"icon":392},{"title":345,"description":4270},"UWlQ6YkbWVRkxFsBAgUV9TJT-nyWLOCTF6AlvHZW0w0",[4278,4280],{"title":385,"path":386,"stem":387,"description":4279,"icon":388,"children":-1},"Replay and tail the local NDJSON drain with readFsLogs and tailFsLogs — works in-process or from any external Node tool, survives restarts.",{"title":394,"path":395,"stem":396,"description":4281,"icon":373,"children":-1},"definePlugin is the canonical extension point for evlog — opt into any subset of setup, onRequestStart, enrich, keep, drain, onRequestFinish, onClientLog, extendLogger from a single cohesive object.",1784142042730]