[{"data":1,"prerenderedAt":3068},["ShallowReactive",2],{"navigation_docs":3,"-extend-custom-framework":520,"-extend-custom-framework-surround":3063},[4,30,80,123,303,435,490],{"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},"CLI","\u002Fcli","3.cli",[85,88,93,98,103,108,113,118],{"title":36,"path":86,"stem":87,"icon":44},"\u002Fcli\u002Foverview","3.cli\u002F0.overview",{"title":89,"path":90,"stem":91,"icon":92},"init","\u002Fcli\u002Finit","3.cli\u002F1.init","i-lucide-wand-sparkles",{"title":94,"path":95,"stem":96,"icon":97},"map","\u002Fcli\u002Fmap","3.cli\u002F2.map","i-lucide-radar",{"title":99,"path":100,"stem":101,"icon":102},"Rules","\u002Fcli\u002Frules","3.cli\u002F3.rules","i-lucide-list-checks",{"title":104,"path":105,"stem":106,"icon":107},"Scoring","\u002Fcli\u002Fscoring","3.cli\u002F4.scoring","i-lucide-gauge",{"title":109,"path":110,"stem":111,"icon":112},"CI","\u002Fcli\u002Fci","3.cli\u002F5.ci","i-lucide-git-pull-request",{"title":114,"path":115,"stem":116,"icon":117},"doctor","\u002Fcli\u002Fdoctor","3.cli\u002F6.doctor","i-lucide-stethoscope",{"title":119,"path":120,"stem":121,"icon":122},"telemetry","\u002Fcli\u002Ftelemetry","3.cli\u002F7.telemetry","i-lucide-bar-chart-3",{"title":124,"path":125,"stem":126,"children":127,"page":29},"Integrate","\u002Fintegrate","4.integrate",[128,132,215],{"title":36,"path":129,"stem":130,"icon":131},"\u002Fintegrate\u002Foverview","4.integrate\u002F0.overview","i-lucide-plug",{"title":133,"path":134,"stem":135,"children":136,"page":29},"Adapters","\u002Fintegrate\u002Fadapters","4.integrate\u002Fadapters",[137,140,170,195],{"title":36,"path":138,"stem":139,"icon":39},"\u002Fintegrate\u002Fadapters\u002Foverview","4.integrate\u002Fadapters\u002F01.overview",{"title":141,"path":142,"stem":143,"children":144,"page":29},"Cloud","\u002Fintegrate\u002Fadapters\u002Fcloud","4.integrate\u002Fadapters\u002Fcloud",[145,150,155,160,165],{"title":146,"path":147,"stem":148,"icon":149},"Axiom","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Faxiom","4.integrate\u002Fadapters\u002Fcloud\u002F01.axiom","i-custom-axiom",{"title":151,"path":152,"stem":153,"icon":154},"PostHog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fposthog","4.integrate\u002Fadapters\u002Fcloud\u002F02.posthog","i-simple-icons-posthog",{"title":156,"path":157,"stem":158,"icon":159},"Sentry","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fsentry","4.integrate\u002Fadapters\u002Fcloud\u002F03.sentry","i-simple-icons-sentry",{"title":161,"path":162,"stem":163,"icon":164},"Better Stack","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fbetter-stack","4.integrate\u002Fadapters\u002Fcloud\u002F04.better-stack","i-simple-icons-betterstack",{"title":166,"path":167,"stem":168,"icon":169},"Datadog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fdatadog","4.integrate\u002Fadapters\u002Fcloud\u002F05.datadog","i-simple-icons-datadog",{"title":171,"path":172,"stem":173,"children":174,"page":29},"Cloud or Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fhybrid","4.integrate\u002Fadapters\u002Fhybrid",[175,180,185,190],{"title":176,"path":177,"stem":178,"icon":179},"Grafana Loki","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Floki","4.integrate\u002Fadapters\u002Fhybrid\u002F01.loki","i-simple-icons-grafana",{"title":181,"path":182,"stem":183,"icon":184},"ClickHouse","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fclickhouse","4.integrate\u002Fadapters\u002Fhybrid\u002F02.clickhouse","i-simple-icons-clickhouse",{"title":186,"path":187,"stem":188,"icon":189},"OTLP","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fotlp","4.integrate\u002Fadapters\u002Fhybrid\u002F03.otlp","i-simple-icons-opentelemetry",{"title":191,"path":192,"stem":193,"icon":194},"HyperDX","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fhyperdx","4.integrate\u002Fadapters\u002Fhybrid\u002F04.hyperdx","i-custom-hyperdx",{"title":196,"path":197,"stem":198,"children":199,"page":29},"Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fself-hosted","4.integrate\u002Fadapters\u002Fself-hosted",[200,205,210],{"title":201,"path":202,"stem":203,"icon":204},"File System","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Ffs","4.integrate\u002Fadapters\u002Fself-hosted\u002F01.fs","i-lucide-hard-drive",{"title":206,"path":207,"stem":208,"icon":209},"NuxtHub","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fnuxthub","4.integrate\u002Fadapters\u002Fself-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":211,"path":212,"stem":213,"icon":214},"Memory","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fmemory","4.integrate\u002Fadapters\u002Fself-hosted\u002F03.memory","i-lucide-cpu",{"title":216,"path":217,"stem":218,"children":219,"page":29},"Frameworks","\u002Fintegrate\u002Fframeworks","4.integrate\u002Fframeworks",[220,224,229,234,239,244,249,254,259,264,269,274,279,284,288,293,298],{"title":36,"path":221,"stem":222,"icon":223},"\u002Fintegrate\u002Fframeworks\u002Foverview","4.integrate\u002Fframeworks\u002F00.overview","i-lucide-layout-grid",{"title":225,"path":226,"stem":227,"icon":228},"Nuxt","\u002Fintegrate\u002Fframeworks\u002Fnuxt","4.integrate\u002Fframeworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":230,"path":231,"stem":232,"icon":233},"Next.js","\u002Fintegrate\u002Fframeworks\u002Fnextjs","4.integrate\u002Fframeworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":235,"path":236,"stem":237,"icon":238},"SvelteKit","\u002Fintegrate\u002Fframeworks\u002Fsveltekit","4.integrate\u002Fframeworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":240,"path":241,"stem":242,"icon":243},"Nitro","\u002Fintegrate\u002Fframeworks\u002Fnitro","4.integrate\u002Fframeworks\u002F04.nitro","i-custom-nitro",{"title":245,"path":246,"stem":247,"icon":248},"TanStack Start","\u002Fintegrate\u002Fframeworks\u002Ftanstack-start","4.integrate\u002Fframeworks\u002F05.tanstack-start","i-custom-tanstack",{"title":250,"path":251,"stem":252,"icon":253},"NestJS","\u002Fintegrate\u002Fframeworks\u002Fnestjs","4.integrate\u002Fframeworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":255,"path":256,"stem":257,"icon":258},"Express","\u002Fintegrate\u002Fframeworks\u002Fexpress","4.integrate\u002Fframeworks\u002F07.express","i-simple-icons-express",{"title":260,"path":261,"stem":262,"icon":263},"Hono","\u002Fintegrate\u002Fframeworks\u002Fhono","4.integrate\u002Fframeworks\u002F08.hono","i-simple-icons-hono",{"title":265,"path":266,"stem":267,"icon":268},"Fastify","\u002Fintegrate\u002Fframeworks\u002Ffastify","4.integrate\u002Fframeworks\u002F09.fastify","i-simple-icons-fastify",{"title":270,"path":271,"stem":272,"icon":273},"Elysia","\u002Fintegrate\u002Fframeworks\u002Felysia","4.integrate\u002Fframeworks\u002F10.elysia","i-custom-elysia",{"title":275,"path":276,"stem":277,"icon":278},"React Router","\u002Fintegrate\u002Fframeworks\u002Freact-router","4.integrate\u002Fframeworks\u002F11.react-router","i-custom-reactrouter",{"title":280,"path":281,"stem":282,"icon":283},"Cloudflare Workers","\u002Fintegrate\u002Fframeworks\u002Fcloudflare-workers","4.integrate\u002Fframeworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":285,"path":286,"stem":287,"icon":74},"Standalone","\u002Fintegrate\u002Fframeworks\u002Fstandalone","4.integrate\u002Fframeworks\u002F13.standalone",{"title":289,"path":290,"stem":291,"icon":292},"Astro","\u002Fintegrate\u002Fframeworks\u002Fastro","4.integrate\u002Fframeworks\u002F14.astro","i-simple-icons-astro",{"title":294,"path":295,"stem":296,"icon":297},"oRPC","\u002Fintegrate\u002Fframeworks\u002Forpc","4.integrate\u002Fframeworks\u002F15.orpc","i-lucide-network",{"title":299,"path":300,"stem":301,"icon":302},"AWS Lambda","\u002Fintegrate\u002Fframeworks\u002Faws-lambda","4.integrate\u002Fframeworks\u002F16.aws-lambda","i-custom-lambda",{"title":304,"path":305,"stem":306,"children":307,"page":29},"Use Cases","\u002Fuse-cases","5.use-cases",[308,311,316,345,372,404,425,430],{"title":36,"path":309,"stem":310,"icon":102},"\u002Fuse-cases\u002Foverview","5.use-cases\u002F0.overview",{"title":312,"path":313,"stem":314,"icon":315},"Client Logging","\u002Fuse-cases\u002Fclient-logging","5.use-cases\u002F1.client-logging","i-lucide-monitor",{"title":317,"icon":318,"path":319,"stem":320,"children":321,"page":29},"AI SDK","i-simple-icons-vercel","\u002Fuse-cases\u002Fai-sdk","5.use-cases\u002F2.ai-sdk",[322,325,330,335,340],{"title":36,"path":323,"stem":324,"icon":39},"\u002Fuse-cases\u002Fai-sdk\u002Foverview","5.use-cases\u002F2.ai-sdk\u002F01.overview",{"title":326,"path":327,"stem":328,"icon":329},"Usage","\u002Fuse-cases\u002Fai-sdk\u002Fusage","5.use-cases\u002F2.ai-sdk\u002F02.usage","i-lucide-code",{"title":331,"path":332,"stem":333,"icon":334},"Options","\u002Fuse-cases\u002Fai-sdk\u002Foptions","5.use-cases\u002F2.ai-sdk\u002F03.options","i-lucide-sliders",{"title":336,"path":337,"stem":338,"icon":339},"Metadata","\u002Fuse-cases\u002Fai-sdk\u002Fmetadata","5.use-cases\u002F2.ai-sdk\u002F04.metadata","i-lucide-database",{"title":341,"path":342,"stem":343,"icon":344},"Telemetry","\u002Fuse-cases\u002Fai-sdk\u002Ftelemetry","5.use-cases\u002F2.ai-sdk\u002F05.telemetry","i-lucide-activity",{"title":346,"icon":347,"path":348,"stem":349,"children":350,"page":29},"Better Auth","i-simple-icons-betterauth","\u002Fuse-cases\u002Fbetter-auth","5.use-cases\u002F3.better-auth",[351,354,359,364,368],{"title":36,"path":352,"stem":353,"icon":39},"\u002Fuse-cases\u002Fbetter-auth\u002Foverview","5.use-cases\u002F3.better-auth\u002F01.overview",{"title":355,"path":356,"stem":357,"icon":358},"Identify User","\u002Fuse-cases\u002Fbetter-auth\u002Fidentify-user","5.use-cases\u002F3.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":360,"path":361,"stem":362,"icon":363},"Middleware","\u002Fuse-cases\u002Fbetter-auth\u002Fmiddleware","5.use-cases\u002F3.better-auth\u002F03.middleware","i-lucide-shield",{"title":365,"path":366,"stem":367,"icon":315},"Client Sync","\u002Fuse-cases\u002Fbetter-auth\u002Fclient-sync","5.use-cases\u002F3.better-auth\u002F04.client-sync",{"title":369,"path":370,"stem":371,"icon":107},"Performance","\u002Fuse-cases\u002Fbetter-auth\u002Fperformance","5.use-cases\u002F3.better-auth\u002F05.performance",{"title":373,"icon":374,"path":375,"stem":376,"children":377,"page":29},"Audit Logs","i-lucide-shield-check","\u002Fuse-cases\u002Faudit","5.use-cases\u002F4.audit",[378,381,386,391,396,400],{"title":36,"path":379,"stem":380,"icon":39},"\u002Fuse-cases\u002Faudit\u002Foverview","5.use-cases\u002F4.audit\u002F01.overview",{"title":382,"path":383,"stem":384,"icon":385},"Schema","\u002Fuse-cases\u002Faudit\u002Fschema","5.use-cases\u002F4.audit\u002F02.schema","i-lucide-file-text",{"title":387,"path":388,"stem":389,"icon":390},"Recording","\u002Fuse-cases\u002Faudit\u002Frecording","5.use-cases\u002F4.audit\u002F03.recording","i-lucide-pen-line",{"title":392,"path":393,"stem":394,"icon":395},"Drains","\u002Fuse-cases\u002Faudit\u002Fpipeline","5.use-cases\u002F4.audit\u002F04.pipeline","i-lucide-link",{"title":397,"path":398,"stem":399,"icon":374},"Compliance","\u002Fuse-cases\u002Faudit\u002Fcompliance","5.use-cases\u002F4.audit\u002F05.compliance",{"title":401,"path":402,"stem":403,"icon":79},"Recipes","\u002Fuse-cases\u002Faudit\u002Frecipes","5.use-cases\u002F4.audit\u002F06.recipes",{"title":341,"icon":107,"path":405,"stem":406,"children":407,"page":29},"\u002Fuse-cases\u002Ftelemetry","5.use-cases\u002F4.telemetry",[408,411,416,421],{"title":36,"path":409,"stem":410,"icon":39},"\u002Fuse-cases\u002Ftelemetry\u002Foverview","5.use-cases\u002F4.telemetry\u002F01.overview",{"title":412,"path":413,"stem":414,"icon":415},"Setup","\u002Fuse-cases\u002Ftelemetry\u002Fsetup","5.use-cases\u002F4.telemetry\u002F02.setup","i-lucide-wrench",{"title":417,"path":418,"stem":419,"icon":420},"Ingest","\u002Fuse-cases\u002Ftelemetry\u002Fingest","5.use-cases\u002F4.telemetry\u002F03.ingest","i-lucide-server",{"title":422,"path":423,"stem":424,"icon":79},"Reference","\u002Fuse-cases\u002Ftelemetry\u002Freference","5.use-cases\u002F4.telemetry\u002F04.reference",{"title":426,"path":427,"stem":428,"icon":429},"Enrichers","\u002Fuse-cases\u002Fenrichers","5.use-cases\u002F5.enrichers","i-lucide-sparkles",{"title":431,"path":432,"stem":433,"icon":434},"eve","\u002Fuse-cases\u002Feve","5.use-cases\u002F5.eve","i-custom-eve",{"title":436,"path":437,"stem":438,"children":439,"page":29},"Extend","\u002Fextend","6.extend",[440,444,449,454,459,463,467,471,475,480,485],{"title":36,"path":441,"stem":442,"icon":443},"\u002Fextend\u002Foverview","6.extend\u002F0.overview","i-lucide-blocks",{"title":445,"path":446,"stem":447,"icon":448},"Stream","\u002Fextend\u002Fstream","6.extend\u002F1.stream","i-lucide-radio-tower",{"title":450,"path":451,"stem":452,"icon":453},"Custom framework","\u002Fextend\u002Fcustom-framework","6.extend\u002F10.custom-framework","i-lucide-puzzle",{"title":455,"path":456,"stem":457,"icon":458},"FS reader","\u002Fextend\u002Ffs-reader","6.extend\u002F2.fs-reader","i-lucide-folder-search",{"title":401,"path":460,"stem":461,"icon":462},"\u002Fextend\u002Fconsumer-recipes","6.extend\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":464,"path":465,"stem":466,"icon":443},"Plugins","\u002Fextend\u002Fplugins","6.extend\u002F4.plugins",{"title":468,"path":469,"stem":470,"icon":429},"Custom enrichers","\u002Fextend\u002Fcustom-enrichers","6.extend\u002F5.custom-enrichers",{"title":472,"path":473,"stem":474,"icon":64},"Tail sampling","\u002Fextend\u002Ftail-sampling","6.extend\u002F6.tail-sampling",{"title":476,"path":477,"stem":478,"icon":479},"Identity headers","\u002Fextend\u002Fidentity-headers","6.extend\u002F7.identity-headers","i-lucide-fingerprint",{"title":481,"path":482,"stem":483,"icon":484},"Custom drains","\u002Fextend\u002Fcustom-drains","6.extend\u002F8.custom-drains","i-lucide-share-2",{"title":486,"path":487,"stem":488,"icon":489},"Drain pipeline","\u002Fextend\u002Fdrain-pipeline","6.extend\u002F9.drain-pipeline","i-lucide-workflow",{"title":422,"path":491,"stem":492,"children":493,"page":29},"\u002Freference","7.reference",[494,499,502,507,511,516],{"title":495,"path":496,"stem":497,"icon":498},"Configuration","\u002Freference\u002Fconfiguration","7.reference\u002F1.configuration","i-lucide-settings",{"title":369,"path":500,"stem":501,"icon":107},"\u002Freference\u002Fperformance","7.reference\u002F2.performance",{"title":503,"path":504,"stem":505,"icon":506},"Vite Plugin","\u002Freference\u002Fvite-plugin","7.reference\u002F3.vite-plugin","i-custom-vite",{"title":508,"path":509,"stem":510,"icon":374},"Best Practices","\u002Freference\u002Fbest-practices","7.reference\u002F4.best-practices",{"title":512,"path":513,"stem":514,"icon":515},"vs Other Loggers","\u002Freference\u002Fvs-other-loggers","7.reference\u002F5.vs-other-loggers","i-lucide-scale",{"title":517,"path":518,"stem":519,"icon":429},"Agent Skills","\u002Freference\u002Fagent-skills","7.reference\u002F6.agent-skills",{"id":521,"title":522,"body":523,"description":3053,"extension":3054,"links":3055,"meta":3059,"navigation":3060,"path":451,"seo":3061,"stem":452,"__hash__":3062},"docs\u002F6.extend\u002F10.custom-framework.md","Custom Framework Integration",{"type":524,"value":525,"toc":3040},"minimark",[526,539,547,557,640,803,808,879,883,1099,1122,1126,1135,1960,1966,1974,1977,2037,2040,2044,2056,2166,2180,2184,2196,2204,2321,2336,2578,2588,2592,2599,2849,2856,2860,2863,2987,2998,3002,3036],[527,528,529,530,534,535,538],"p",{},"When the framework you use doesn't have an ",[531,532,533],"code",{},"evlog\u002F\u003Cframework>"," package yet, you build the integration yourself. ",[531,536,537],{},"evlog\u002Ftoolkit"," ships the same building blocks that power every built-in integration (Hono, Express, Fastify, Elysia, NestJS, SvelteKit) — you only write the framework-specific glue.",[527,540,541,542,546],{},"The mental model is always the same: ",[543,544,545],"strong",{},"request lifecycle → logger creation → enrich → drain",". The toolkit handles the request-context plumbing.",[548,549,552,553,556],"callout",{"color":550,"icon":551},"warning","i-lucide-flask-conical","The toolkit API is marked as ",[543,554,555],{},"beta",". The surface is stable (used by all built-in integrations) but may evolve based on community feedback.",[558,559,560,576],"table",{},[561,562,563],"thead",{},[564,565,566,570,573],"tr",{},[567,568,569],"th",{},"Surface",[567,571,572],{},"What it does",[567,574,575],{},"When to use",[577,578,579,601,624],"tbody",{},[564,580,581,591,594],{},[582,583,584],"td",{},[585,586,588],"a",{"href":587},"#manifest-mode-recommended",[531,589,590],{},"defineFrameworkIntegration()",[582,592,593],{},"Declaratively wire request extraction + logger attachment",[582,595,596,597,600],{},"HTTP frameworks with a ",[531,598,599],{},"(ctx, next)"," middleware shape (Hono, Express, Fastify, Elysia, NestJS-shaped)",[564,602,603,611,614],{},[582,604,605],{},[585,606,608],{"href":607},"#custom-mode",[531,609,610],{},"createMiddlewareLogger()",[582,612,613],{},"Imperative path: create the logger at request start, emit on response end",[582,615,616,617,619,620,623],{},"Frameworks whose lifecycle doesn't fit ",[531,618,599],{}," (NestJS interceptors, Next.js App Router, SvelteKit ",[531,621,622],{},"handle",")",[564,625,626,634,637],{},[582,627,628],{},[585,629,631],{"href":630},"#non-http-runtimes",[531,632,633],{},"createRequestLogger()",[582,635,636],{},"Wrap any unit of work in a logger lifecycle",[582,638,639],{},"Non-HTTP runtimes (queue workers, CLI, cron, durable workflows)",[641,642,645,648,795],"prompt",{":actions":643,"description":644,"icon":453},"[\"copy\",\"cursor\",\"claude\"]","Build an evlog integration for a custom framework",[527,646,647],{},"Wire evlog into an HTTP framework (or non-HTTP runtime) that doesn't have a built-in integration.",[649,650,651,685,699,709,723,738,749,775,786],"ul",{},[652,653,654,655,657,658,661,662,664,665,668,669,672,673,676,677,680,681,684],"li",{},"For HTTP frameworks with ",[531,656,599],{},", use ",[531,659,660],{},"defineFrameworkIntegration"," from ",[531,663,537],{}," — declare ",[531,666,667],{},"extractRequest(ctx)"," returning ",[531,670,671],{},"{ method, path, headers, requestId? }",", ",[531,674,675],{},"attachLogger(ctx, logger)",", and an optional storage from ",[531,678,679],{},"createLoggerStorage()"," (prefer ",[531,682,683],{},"evlog\u002Ftoolkit\u002Fstorage"," on Workers \u002F edge)",[652,686,687,688,691,692,695,696,698],{},"Headers may be either Web ",[531,689,690],{},"Headers"," or Node ",[531,693,694],{},"IncomingHttpHeaders"," — ",[531,697,660],{}," normalizes both",[652,700,701,702,705,706],{},"In your middleware, call ",[531,703,704],{},"integration.start(ctx, options)"," which returns ",[531,707,708],{},"{ skipped, finish, runWith, logger, middlewareOptions }",[652,710,711,712,715,716,719,720],{},"If ",[531,713,714],{},"skipped"," is ",[531,717,718],{},"true",", skip directly to ",[531,721,722],{},"next",[652,724,725,726,729,730,733,734,737],{},"Run downstream handlers inside ",[531,727,728],{},"runWith(() => next())"," so ",[531,731,732],{},"AsyncLocalStorage"," and ",[531,735,736],{},"log.fork()"," work",[652,739,740,741,744,745,748],{},"On success: ",[531,742,743],{},"await finish({ status })","; on error: ",[531,746,747],{},"await finish({ error })"," then re-throw",[652,750,751,752,672,755,672,758,672,761,672,764,672,767,770,771,774],{},"Expose ",[531,753,754],{},"drain",[531,756,757],{},"enrich",[531,759,760],{},"keep",[531,762,763],{},"include",[531,765,766],{},"exclude",[531,768,769],{},"routes",", and ",[531,772,773],{},"plugins"," options",[652,776,777,778,781,782,785],{},"On Cloudflare Workers \u002F Vercel Edge, pass ",[531,779,780],{},"waitUntil"," (or ",[531,783,784],{},"extractWaitUntil"," on the manifest) so async drains complete after the response",[652,787,788,789,661,792,794],{},"For non-HTTP runtimes (queue workers, CLI, cron), use ",[531,790,791],{},"createRequestLogger",[531,793,537],{}," directly — wrap each unit of work in a logger lifecycle",[527,796,797,798],{},"Docs: ",[585,799,800],{"href":800,"rel":801},"https:\u002F\u002Fwww.evlog.dev\u002Fextend\u002Fcustom-framework",[802],"nofollow",[804,805,807],"h2",{"id":806},"install","Install",[809,810,811,836,850,864],"code-group",{},[812,813,819],"pre",{"className":814,"code":815,"filename":816,"language":817,"meta":818,"style":818},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add evlog\n","pnpm","bash","",[531,820,821],{"__ignoreMap":818},[822,823,826,829,833],"span",{"class":824,"line":825},"line",1,[822,827,816],{"class":828},"sBMFI",[822,830,832],{"class":831},"sfazB"," add",[822,834,835],{"class":831}," evlog\n",[812,837,840],{"className":814,"code":838,"filename":839,"language":817,"meta":818,"style":818},"bun add evlog\n","bun",[531,841,842],{"__ignoreMap":818},[822,843,844,846,848],{"class":824,"line":825},[822,845,839],{"class":828},[822,847,832],{"class":831},[822,849,835],{"class":831},[812,851,854],{"className":814,"code":852,"filename":853,"language":817,"meta":818,"style":818},"yarn add evlog\n","yarn",[531,855,856],{"__ignoreMap":818},[822,857,858,860,862],{"class":824,"line":825},[822,859,853],{"class":828},[822,861,832],{"class":831},[822,863,835],{"class":831},[812,865,868],{"className":814,"code":866,"filename":867,"language":817,"meta":818,"style":818},"npm install evlog\n","npm",[531,869,870],{"__ignoreMap":818},[822,871,872,874,877],{"class":824,"line":825},[822,873,867],{"class":828},[822,875,876],{"class":831}," install",[822,878,835],{"class":831},[804,880,882],{"id":881},"whats-in-the-toolkit","What's in the toolkit",[558,884,885,895],{},[561,886,887],{},[564,888,889,892],{},[567,890,891],{},"Export",[567,893,894],{},"Purpose",[577,896,897,907,917,931,941,965,978,991,1003,1026,1044,1058,1089],{},[564,898,899,904],{},[582,900,901],{},[531,902,903],{},"defineFrameworkIntegration(spec)",[582,905,906],{},"Manifest factory — extract request, create logger, attach, run with ALS",[564,908,909,914],{},[582,910,911],{},[531,912,913],{},"createMiddlewareLogger(opts)",[582,915,916],{},"Lower-level lifecycle (custom mode)",[564,918,919,924],{},[582,920,921,923],{},[531,922,780],{}," on middleware options",[582,925,926,927,623],{},"Defer drain on Cloudflare Workers \u002F Vercel Edge (see ",[585,928,930],{"href":929},"#serverless-workers-edge","Serverless",[564,932,933,938],{},[582,934,935],{},[531,936,937],{},"createRequestLogger(opts)",[582,939,940],{},"Wrap a non-HTTP unit of work in a logger lifecycle",[564,942,943,948],{},[582,944,945],{},[531,946,947],{},"BaseEvlogOptions",[582,949,950,951,672,953,672,955,672,957,672,959,672,961,672,963],{},"Base user-facing options — ",[531,952,754],{},[531,954,757],{},[531,956,760],{},[531,958,763],{},[531,960,766],{},[531,962,769],{},[531,964,773],{},[564,966,967,972],{},[582,968,969],{},[531,970,971],{},"MiddlewareLoggerResult",[582,973,974,975],{},"Return type: ",[531,976,977],{},"{ logger, finish, skipped }",[564,979,980,985],{},[582,981,982],{},[531,983,984],{},"extractSafeHeaders(headers)",[582,986,987,988,990],{},"Filter sensitive headers from a Web API ",[531,989,690],{}," object",[564,992,993,998],{},[582,994,995],{},[531,996,997],{},"extractSafeNodeHeaders(headers)",[582,999,1000,1001],{},"Filter sensitive headers from Node.js ",[531,1002,694],{},[564,1004,1005,1010],{},[582,1006,1007],{},[531,1008,1009],{},"createLoggerStorage(hint)",[582,1011,1012,1013,1016,1017,1019,1020,1022,1023,623],{},"Factory returning ",[531,1014,1015],{},"{ storage, useLogger }"," backed by ",[531,1018,732],{}," — also on ",[531,1021,683],{}," (prefer that entry on Workers \u002F edge to isolate ",[531,1024,1025],{},"node:async_hooks",[564,1027,1028,1033],{},[582,1029,1030],{},[531,1031,1032],{},"attachForkToLogger(storage, parent, opts)",[582,1034,1035,1036,1039,1040,1043],{},"Wires ",[531,1037,1038],{},"log.fork(label, fn)"," onto the request logger so consumers can spawn correlated background work — used by manifest mode automatically; call manually in custom mode after ",[531,1041,1042],{},"createMiddlewareLogger"," returns the logger and before the lifecycle finishes",[564,1045,1046,1051],{},[582,1047,1048],{},[531,1049,1050],{},"defineEvlog(config)",[582,1052,1053,1054,1057],{},"Canonical config object — works for ",[531,1055,1056],{},"initLogger"," and middleware options",[564,1059,1060,1065],{},[582,1061,1062],{},[531,1063,1064],{},"definePlugin(plugin)",[582,1066,1067,1068,672,1071,672,1073,672,1075,672,1077,672,1080,672,1083,672,1086],{},"Plugin contract — opt into any subset of ",[531,1069,1070],{},"setup",[531,1072,757],{},[531,1074,754],{},[531,1076,760],{},[531,1078,1079],{},"onRequestStart",[531,1081,1082],{},"onRequestFinish",[531,1084,1085],{},"onClientLog",[531,1087,1088],{},"extendLogger",[564,1090,1091,1096],{},[582,1092,1093],{},[531,1094,1095],{},"composeEnrichers \u002F composeDrains \u002F composeKeep \u002F composePlugins",[582,1097,1098],{},"Combine multiple extensions into one",[527,1100,1101,1102,672,1105,672,1108,672,1111,770,1114,1117,1118,1121],{},"Types like ",[531,1103,1104],{},"RequestLogger",[531,1106,1107],{},"DrainContext",[531,1109,1110],{},"EnrichContext",[531,1112,1113],{},"WideEvent",[531,1115,1116],{},"TailSamplingContext"," are exported from the main ",[531,1119,1120],{},"evlog"," package.",[804,1123,1125],{"id":1124},"manifest-mode-recommended","Manifest mode (recommended)",[527,1127,1128,1129,1131,1132,1134],{},"Most frameworks fit a ",[531,1130,599],{}," middleware shape. For those, write a manifest describing how to extract the request and attach the logger — ",[531,1133,660],{}," does the rest.",[1136,1137,1138],"code-collapse",{},[812,1139,1144],{"className":1140,"code":1141,"filename":1142,"language":1143,"meta":818,"style":818},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport {\n  createLoggerStorage,\n  defineFrameworkIntegration,\n  type BaseEvlogOptions,\n} from 'evlog\u002Ftoolkit'\n\u002F\u002F On Workers \u002F edge, prefer: import { createLoggerStorage } from 'evlog\u002Ftoolkit\u002Fstorage'\nimport type { RequestLogger } from 'evlog'\n\nexport type MyFrameworkEvlogOptions = BaseEvlogOptions\n\nconst { storage, useLogger } = createLoggerStorage(\n  'Cannot access logger outside of middleware context. Make sure evlog middleware is registered before your routes.',\n)\n\nexport { useLogger }\n\nconst integration = defineFrameworkIntegration\u003CIncomingMessage>({\n  name: 'my-framework',\n  extractRequest: (req) => ({\n    method: req.method || 'GET',\n    path: req.url || '\u002F',\n    headers: req.headers,\n    requestId: typeof req.headers['x-request-id'] === 'string'\n      ? req.headers['x-request-id']\n      : undefined,\n  }),\n  attachLogger: (req, logger) => {\n    (req as IncomingMessage & { log: RequestLogger }).log = logger\n  },\n  storage,\n})\n\nexport function evlog(options: MyFrameworkEvlogOptions = {}) {\n  return async (req: IncomingMessage, res: ServerResponse, next: () => Promise\u003Cvoid>) => {\n    const { skipped, finish, runWith } = integration.start(req, options)\n    if (skipped) {\n      await next()\n      return\n    }\n    try {\n      await runWith(() => next())\n      await finish({ status: res.statusCode })\n    } catch (error) {\n      await finish({ error: error as Error })\n      throw error\n    }\n  }\n}\n","my-framework-evlog.ts","typescript",[531,1145,1146,1184,1192,1201,1209,1220,1234,1241,1263,1270,1288,1293,1320,1334,1340,1345,1358,1363,1392,1411,1435,1464,1490,1507,1545,1566,1575,1585,1608,1647,1653,1661,1668,1673,1700,1753,1796,1811,1822,1828,1834,1842,1861,1889,1907,1934,1943,1948,1954],{"__ignoreMap":818},[822,1147,1148,1152,1155,1159,1163,1166,1169,1172,1175,1178,1181],{"class":824,"line":825},[822,1149,1151],{"class":1150},"s7zQu","import",[822,1153,1154],{"class":1150}," type",[822,1156,1158],{"class":1157},"sMK4o"," {",[822,1160,1162],{"class":1161},"sTEyZ"," IncomingMessage",[822,1164,1165],{"class":1157},",",[822,1167,1168],{"class":1161}," ServerResponse",[822,1170,1171],{"class":1157}," }",[822,1173,1174],{"class":1150}," from",[822,1176,1177],{"class":1157}," '",[822,1179,1180],{"class":831},"node:http",[822,1182,1183],{"class":1157},"'\n",[822,1185,1187,1189],{"class":824,"line":1186},2,[822,1188,1151],{"class":1150},[822,1190,1191],{"class":1157}," {\n",[822,1193,1195,1198],{"class":824,"line":1194},3,[822,1196,1197],{"class":1161},"  createLoggerStorage",[822,1199,1200],{"class":1157},",\n",[822,1202,1204,1207],{"class":824,"line":1203},4,[822,1205,1206],{"class":1161},"  defineFrameworkIntegration",[822,1208,1200],{"class":1157},[822,1210,1212,1215,1218],{"class":824,"line":1211},5,[822,1213,1214],{"class":1150},"  type",[822,1216,1217],{"class":1161}," BaseEvlogOptions",[822,1219,1200],{"class":1157},[822,1221,1223,1226,1228,1230,1232],{"class":824,"line":1222},6,[822,1224,1225],{"class":1157},"}",[822,1227,1174],{"class":1150},[822,1229,1177],{"class":1157},[822,1231,537],{"class":831},[822,1233,1183],{"class":1157},[822,1235,1237],{"class":824,"line":1236},7,[822,1238,1240],{"class":1239},"sHwdD","\u002F\u002F On Workers \u002F edge, prefer: import { createLoggerStorage } from 'evlog\u002Ftoolkit\u002Fstorage'\n",[822,1242,1244,1246,1248,1250,1253,1255,1257,1259,1261],{"class":824,"line":1243},8,[822,1245,1151],{"class":1150},[822,1247,1154],{"class":1150},[822,1249,1158],{"class":1157},[822,1251,1252],{"class":1161}," RequestLogger",[822,1254,1171],{"class":1157},[822,1256,1174],{"class":1150},[822,1258,1177],{"class":1157},[822,1260,1120],{"class":831},[822,1262,1183],{"class":1157},[822,1264,1266],{"class":824,"line":1265},9,[822,1267,1269],{"emptyLinePlaceholder":1268},true,"\n",[822,1271,1273,1276,1279,1282,1285],{"class":824,"line":1272},10,[822,1274,1275],{"class":1150},"export",[822,1277,1154],{"class":1278},"spNyl",[822,1280,1281],{"class":828}," MyFrameworkEvlogOptions",[822,1283,1284],{"class":1157}," =",[822,1286,1287],{"class":828}," BaseEvlogOptions\n",[822,1289,1291],{"class":824,"line":1290},11,[822,1292,1269],{"emptyLinePlaceholder":1268},[822,1294,1296,1299,1301,1304,1306,1309,1311,1313,1317],{"class":824,"line":1295},12,[822,1297,1298],{"class":1278},"const",[822,1300,1158],{"class":1157},[822,1302,1303],{"class":1161}," storage",[822,1305,1165],{"class":1157},[822,1307,1308],{"class":1161}," useLogger ",[822,1310,1225],{"class":1157},[822,1312,1284],{"class":1157},[822,1314,1316],{"class":1315},"s2Zo4"," createLoggerStorage",[822,1318,1319],{"class":1161},"(\n",[822,1321,1323,1326,1329,1332],{"class":824,"line":1322},13,[822,1324,1325],{"class":1157},"  '",[822,1327,1328],{"class":831},"Cannot access logger outside of middleware context. Make sure evlog middleware is registered before your routes.",[822,1330,1331],{"class":1157},"'",[822,1333,1200],{"class":1157},[822,1335,1337],{"class":824,"line":1336},14,[822,1338,1339],{"class":1161},")\n",[822,1341,1343],{"class":824,"line":1342},15,[822,1344,1269],{"emptyLinePlaceholder":1268},[822,1346,1348,1350,1352,1355],{"class":824,"line":1347},16,[822,1349,1275],{"class":1150},[822,1351,1158],{"class":1157},[822,1353,1354],{"class":1161}," useLogger",[822,1356,1357],{"class":1157}," }\n",[822,1359,1361],{"class":824,"line":1360},17,[822,1362,1269],{"emptyLinePlaceholder":1268},[822,1364,1366,1368,1371,1374,1377,1380,1383,1386,1389],{"class":824,"line":1365},18,[822,1367,1298],{"class":1278},[822,1369,1370],{"class":1161}," integration ",[822,1372,1373],{"class":1157},"=",[822,1375,1376],{"class":1315}," defineFrameworkIntegration",[822,1378,1379],{"class":1157},"\u003C",[822,1381,1382],{"class":828},"IncomingMessage",[822,1384,1385],{"class":1157},">",[822,1387,1388],{"class":1161},"(",[822,1390,1391],{"class":1157},"{\n",[822,1393,1395,1399,1402,1404,1407,1409],{"class":824,"line":1394},19,[822,1396,1398],{"class":1397},"swJcz","  name",[822,1400,1401],{"class":1157},":",[822,1403,1177],{"class":1157},[822,1405,1406],{"class":831},"my-framework",[822,1408,1331],{"class":1157},[822,1410,1200],{"class":1157},[822,1412,1414,1417,1419,1422,1426,1428,1431,1433],{"class":824,"line":1413},20,[822,1415,1416],{"class":1315},"  extractRequest",[822,1418,1401],{"class":1157},[822,1420,1421],{"class":1157}," (",[822,1423,1425],{"class":1424},"sHdIc","req",[822,1427,623],{"class":1157},[822,1429,1430],{"class":1278}," =>",[822,1432,1421],{"class":1161},[822,1434,1391],{"class":1157},[822,1436,1438,1441,1443,1446,1449,1452,1455,1457,1460,1462],{"class":824,"line":1437},21,[822,1439,1440],{"class":1397},"    method",[822,1442,1401],{"class":1157},[822,1444,1445],{"class":1161}," req",[822,1447,1448],{"class":1157},".",[822,1450,1451],{"class":1161},"method ",[822,1453,1454],{"class":1157},"||",[822,1456,1177],{"class":1157},[822,1458,1459],{"class":831},"GET",[822,1461,1331],{"class":1157},[822,1463,1200],{"class":1157},[822,1465,1467,1470,1472,1474,1476,1479,1481,1483,1486,1488],{"class":824,"line":1466},22,[822,1468,1469],{"class":1397},"    path",[822,1471,1401],{"class":1157},[822,1473,1445],{"class":1161},[822,1475,1448],{"class":1157},[822,1477,1478],{"class":1161},"url ",[822,1480,1454],{"class":1157},[822,1482,1177],{"class":1157},[822,1484,1485],{"class":831},"\u002F",[822,1487,1331],{"class":1157},[822,1489,1200],{"class":1157},[822,1491,1493,1496,1498,1500,1502,1505],{"class":824,"line":1492},23,[822,1494,1495],{"class":1397},"    headers",[822,1497,1401],{"class":1157},[822,1499,1445],{"class":1161},[822,1501,1448],{"class":1157},[822,1503,1504],{"class":1161},"headers",[822,1506,1200],{"class":1157},[822,1508,1510,1513,1515,1518,1520,1522,1525,1527,1530,1532,1535,1538,1540,1543],{"class":824,"line":1509},24,[822,1511,1512],{"class":1397},"    requestId",[822,1514,1401],{"class":1157},[822,1516,1517],{"class":1157}," typeof",[822,1519,1445],{"class":1161},[822,1521,1448],{"class":1157},[822,1523,1524],{"class":1161},"headers[",[822,1526,1331],{"class":1157},[822,1528,1529],{"class":831},"x-request-id",[822,1531,1331],{"class":1157},[822,1533,1534],{"class":1161},"] ",[822,1536,1537],{"class":1157},"===",[822,1539,1177],{"class":1157},[822,1541,1542],{"class":831},"string",[822,1544,1183],{"class":1157},[822,1546,1548,1551,1553,1555,1557,1559,1561,1563],{"class":824,"line":1547},25,[822,1549,1550],{"class":1157},"      ?",[822,1552,1445],{"class":1161},[822,1554,1448],{"class":1157},[822,1556,1524],{"class":1161},[822,1558,1331],{"class":1157},[822,1560,1529],{"class":831},[822,1562,1331],{"class":1157},[822,1564,1565],{"class":1161},"]\n",[822,1567,1569,1572],{"class":824,"line":1568},26,[822,1570,1571],{"class":1157},"      :",[822,1573,1574],{"class":1157}," undefined,\n",[822,1576,1578,1581,1583],{"class":824,"line":1577},27,[822,1579,1580],{"class":1157},"  }",[822,1582,623],{"class":1161},[822,1584,1200],{"class":1157},[822,1586,1588,1591,1593,1595,1597,1599,1602,1604,1606],{"class":824,"line":1587},28,[822,1589,1590],{"class":1315},"  attachLogger",[822,1592,1401],{"class":1157},[822,1594,1421],{"class":1157},[822,1596,1425],{"class":1424},[822,1598,1165],{"class":1157},[822,1600,1601],{"class":1424}," logger",[822,1603,623],{"class":1157},[822,1605,1430],{"class":1278},[822,1607,1191],{"class":1157},[822,1609,1611,1614,1616,1619,1621,1624,1626,1629,1631,1633,1635,1637,1639,1642,1644],{"class":824,"line":1610},29,[822,1612,1613],{"class":1397},"    (",[822,1615,1425],{"class":1161},[822,1617,1618],{"class":1150}," as",[822,1620,1162],{"class":828},[822,1622,1623],{"class":1157}," &",[822,1625,1158],{"class":1157},[822,1627,1628],{"class":1397}," log",[822,1630,1401],{"class":1157},[822,1632,1252],{"class":828},[822,1634,1171],{"class":1157},[822,1636,623],{"class":1397},[822,1638,1448],{"class":1157},[822,1640,1641],{"class":1161},"log",[822,1643,1284],{"class":1157},[822,1645,1646],{"class":1161}," logger\n",[822,1648,1650],{"class":824,"line":1649},30,[822,1651,1652],{"class":1157},"  },\n",[822,1654,1656,1659],{"class":824,"line":1655},31,[822,1657,1658],{"class":1161},"  storage",[822,1660,1200],{"class":1157},[822,1662,1664,1666],{"class":824,"line":1663},32,[822,1665,1225],{"class":1157},[822,1667,1339],{"class":1161},[822,1669,1671],{"class":824,"line":1670},33,[822,1672,1269],{"emptyLinePlaceholder":1268},[822,1674,1676,1678,1681,1684,1686,1689,1691,1693,1695,1698],{"class":824,"line":1675},34,[822,1677,1275],{"class":1150},[822,1679,1680],{"class":1278}," function",[822,1682,1683],{"class":1315}," evlog",[822,1685,1388],{"class":1157},[822,1687,1688],{"class":1424},"options",[822,1690,1401],{"class":1157},[822,1692,1281],{"class":828},[822,1694,1284],{"class":1157},[822,1696,1697],{"class":1157}," {})",[822,1699,1191],{"class":1157},[822,1701,1703,1706,1709,1711,1713,1715,1717,1719,1722,1724,1726,1728,1731,1733,1736,1738,1741,1743,1746,1749,1751],{"class":824,"line":1702},35,[822,1704,1705],{"class":1150},"  return",[822,1707,1708],{"class":1278}," async",[822,1710,1421],{"class":1157},[822,1712,1425],{"class":1424},[822,1714,1401],{"class":1157},[822,1716,1162],{"class":828},[822,1718,1165],{"class":1157},[822,1720,1721],{"class":1424}," res",[822,1723,1401],{"class":1157},[822,1725,1168],{"class":828},[822,1727,1165],{"class":1157},[822,1729,1730],{"class":1315}," next",[822,1732,1401],{"class":1157},[822,1734,1735],{"class":1157}," ()",[822,1737,1430],{"class":1278},[822,1739,1740],{"class":828}," Promise",[822,1742,1379],{"class":1157},[822,1744,1745],{"class":828},"void",[822,1747,1748],{"class":1157},">)",[822,1750,1430],{"class":1278},[822,1752,1191],{"class":1157},[822,1754,1756,1759,1761,1764,1766,1769,1771,1774,1776,1778,1781,1783,1786,1788,1790,1792,1794],{"class":824,"line":1755},36,[822,1757,1758],{"class":1278},"    const",[822,1760,1158],{"class":1157},[822,1762,1763],{"class":1161}," skipped",[822,1765,1165],{"class":1157},[822,1767,1768],{"class":1161}," finish",[822,1770,1165],{"class":1157},[822,1772,1773],{"class":1161}," runWith",[822,1775,1171],{"class":1157},[822,1777,1284],{"class":1157},[822,1779,1780],{"class":1161}," integration",[822,1782,1448],{"class":1157},[822,1784,1785],{"class":1315},"start",[822,1787,1388],{"class":1397},[822,1789,1425],{"class":1161},[822,1791,1165],{"class":1157},[822,1793,774],{"class":1161},[822,1795,1339],{"class":1397},[822,1797,1799,1802,1804,1806,1809],{"class":824,"line":1798},37,[822,1800,1801],{"class":1150},"    if",[822,1803,1421],{"class":1397},[822,1805,714],{"class":1161},[822,1807,1808],{"class":1397},") ",[822,1810,1391],{"class":1157},[822,1812,1814,1817,1819],{"class":824,"line":1813},38,[822,1815,1816],{"class":1150},"      await",[822,1818,1730],{"class":1315},[822,1820,1821],{"class":1397},"()\n",[822,1823,1825],{"class":824,"line":1824},39,[822,1826,1827],{"class":1150},"      return\n",[822,1829,1831],{"class":824,"line":1830},40,[822,1832,1833],{"class":1157},"    }\n",[822,1835,1837,1840],{"class":824,"line":1836},41,[822,1838,1839],{"class":1150},"    try",[822,1841,1191],{"class":1157},[822,1843,1845,1847,1849,1851,1854,1856,1858],{"class":824,"line":1844},42,[822,1846,1816],{"class":1150},[822,1848,1773],{"class":1315},[822,1850,1388],{"class":1397},[822,1852,1853],{"class":1157},"()",[822,1855,1430],{"class":1278},[822,1857,1730],{"class":1315},[822,1859,1860],{"class":1397},"())\n",[822,1862,1864,1866,1868,1870,1873,1876,1878,1880,1882,1885,1887],{"class":824,"line":1863},43,[822,1865,1816],{"class":1150},[822,1867,1768],{"class":1315},[822,1869,1388],{"class":1397},[822,1871,1872],{"class":1157},"{",[822,1874,1875],{"class":1397}," status",[822,1877,1401],{"class":1157},[822,1879,1721],{"class":1161},[822,1881,1448],{"class":1157},[822,1883,1884],{"class":1161},"statusCode",[822,1886,1171],{"class":1157},[822,1888,1339],{"class":1397},[822,1890,1892,1895,1898,1900,1903,1905],{"class":824,"line":1891},44,[822,1893,1894],{"class":1157},"    }",[822,1896,1897],{"class":1150}," catch",[822,1899,1421],{"class":1397},[822,1901,1902],{"class":1161},"error",[822,1904,1808],{"class":1397},[822,1906,1391],{"class":1157},[822,1908,1910,1912,1914,1916,1918,1921,1923,1925,1927,1930,1932],{"class":824,"line":1909},45,[822,1911,1816],{"class":1150},[822,1913,1768],{"class":1315},[822,1915,1388],{"class":1397},[822,1917,1872],{"class":1157},[822,1919,1920],{"class":1397}," error",[822,1922,1401],{"class":1157},[822,1924,1920],{"class":1161},[822,1926,1618],{"class":1150},[822,1928,1929],{"class":828}," Error",[822,1931,1171],{"class":1157},[822,1933,1339],{"class":1397},[822,1935,1937,1940],{"class":824,"line":1936},46,[822,1938,1939],{"class":1150},"      throw",[822,1941,1942],{"class":1161}," error\n",[822,1944,1946],{"class":824,"line":1945},47,[822,1947,1833],{"class":1157},[822,1949,1951],{"class":824,"line":1950},48,[822,1952,1953],{"class":1157},"  }\n",[822,1955,1957],{"class":824,"line":1956},49,[822,1958,1959],{"class":1157},"}\n",[527,1961,1962,1963,1965],{},"That's it. This middleware gets every feature for free: route filtering, drain adapters, enrichers, tail sampling, error capture, plugin lifecycle hooks, ",[531,1964,736],{},", and duration tracking.",[1967,1968,1970,1971,1973],"h3",{"id":1969},"what-defineframeworkintegration-does","What ",[531,1972,660],{}," does",[527,1975,1976],{},"Given the manifest above, the helper:",[1978,1979,1980,1989,2000,2006,2010,2020],"ol",{},[652,1981,1982,1983,1985,1986,1988],{},"Normalizes headers (auto-detects ",[531,1984,690],{}," vs ",[531,1987,694],{},").",[652,1990,1991,1992,1995,1996,1999],{},"Generates a ",[531,1993,1994],{},"requestId"," if ",[531,1997,1998],{},"extractRequest"," doesn't return one.",[652,2001,2002,2003,2005],{},"Calls ",[531,2004,1042],{}," with the merged options.",[652,2007,2002,2008,1448],{},[531,2009,675],{},[652,2011,2012,2013,2015,2016,2019],{},"Attaches ",[531,2014,736],{}," to the logger when ",[531,2017,2018],{},"storage"," is provided (so users can spawn correlated background work).",[652,2021,2022,2023,2026,2027,2030,2031,2034,2035,1448],{},"Exposes ",[531,2024,2025],{},"runWith(fn)"," — runs ",[531,2028,2029],{},"fn()"," inside ",[531,2032,2033],{},"storage.run(logger, …)"," if storage is configured, otherwise just calls ",[531,2036,2029],{},[527,2038,2039],{},"You're left with only the framework-specific glue: where to read the request from, where to attach the logger, and how to compute the response status.",[804,2041,2043],{"id":2042},"custom-mode","Custom mode",[527,2045,2046,2047,2049,2050,2052,2053,2055],{},"If your framework's lifecycle doesn't fit a clean ",[531,2048,599],{}," shape (NestJS interceptors, Next.js App Router, SvelteKit ",[531,2051,622],{},"), drop one level lower and call ",[531,2054,1042],{}," directly:",[812,2057,2059],{"className":1140,"code":2058,"language":1143,"meta":818,"style":818},"import { createMiddlewareLogger, extractSafeNodeHeaders } from 'evlog\u002Ftoolkit'\n\nconst { logger, finish, skipped } = createMiddlewareLogger({\n  method,\n  path,\n  requestId,\n  headers: extractSafeNodeHeaders(rawHeaders),\n  ...options,\n})\n",[531,2060,2061,2085,2089,2116,2123,2130,2137,2151,2160],{"__ignoreMap":818},[822,2062,2063,2065,2067,2070,2072,2075,2077,2079,2081,2083],{"class":824,"line":825},[822,2064,1151],{"class":1150},[822,2066,1158],{"class":1157},[822,2068,2069],{"class":1161}," createMiddlewareLogger",[822,2071,1165],{"class":1157},[822,2073,2074],{"class":1161}," extractSafeNodeHeaders",[822,2076,1171],{"class":1157},[822,2078,1174],{"class":1150},[822,2080,1177],{"class":1157},[822,2082,537],{"class":831},[822,2084,1183],{"class":1157},[822,2086,2087],{"class":824,"line":1186},[822,2088,1269],{"emptyLinePlaceholder":1268},[822,2090,2091,2093,2095,2097,2099,2101,2103,2106,2108,2110,2112,2114],{"class":824,"line":1194},[822,2092,1298],{"class":1278},[822,2094,1158],{"class":1157},[822,2096,1601],{"class":1161},[822,2098,1165],{"class":1157},[822,2100,1768],{"class":1161},[822,2102,1165],{"class":1157},[822,2104,2105],{"class":1161}," skipped ",[822,2107,1225],{"class":1157},[822,2109,1284],{"class":1157},[822,2111,2069],{"class":1315},[822,2113,1388],{"class":1161},[822,2115,1391],{"class":1157},[822,2117,2118,2121],{"class":824,"line":1203},[822,2119,2120],{"class":1161},"  method",[822,2122,1200],{"class":1157},[822,2124,2125,2128],{"class":824,"line":1211},[822,2126,2127],{"class":1161},"  path",[822,2129,1200],{"class":1157},[822,2131,2132,2135],{"class":824,"line":1222},[822,2133,2134],{"class":1161},"  requestId",[822,2136,1200],{"class":1157},[822,2138,2139,2142,2144,2146,2149],{"class":824,"line":1236},[822,2140,2141],{"class":1397},"  headers",[822,2143,1401],{"class":1157},[822,2145,2074],{"class":1315},[822,2147,2148],{"class":1161},"(rawHeaders)",[822,2150,1200],{"class":1157},[822,2152,2153,2156,2158],{"class":824,"line":1243},[822,2154,2155],{"class":1157},"  ...",[822,2157,1688],{"class":1161},[822,2159,1200],{"class":1157},[822,2161,2162,2164],{"class":824,"line":1265},[822,2163,1225],{"class":1157},[822,2165,1339],{"class":1161},[527,2167,2168,2169,2172,2173,2175,2176,2179],{},"You'll be responsible for ALS wrapping (",[531,2170,2171],{},"storage.run","), ",[531,2174,736],{}," attachment (via ",[531,2177,2178],{},"attachForkToLogger","), and finishing the lifecycle — but you keep the full pipeline (route filtering, sampling, emit, enrich, drain, plugins) for free.",[804,2181,2183],{"id":2182},"serverless-workers-edge","Serverless (Workers \u002F Edge)",[527,2185,2186,2187,2189,2190,2195],{},"On Cloudflare Workers and Vercel Edge, the runtime can terminate as soon as the response is returned. If your drain sends HTTP to an observability backend, pass ",[531,2188,780],{}," so enrich still runs inline but drain work survives after the response — the same behavior as ",[585,2191,2192],{"href":281},[531,2193,2194],{},"evlog\u002Fworkers"," and the Nitro plugin.",[527,2197,2198,2200,2201,2203],{},[543,2199,2043],{}," — pass ",[531,2202,780],{}," per request:",[812,2205,2207],{"className":1140,"code":2206,"language":1143,"meta":818,"style":818},"import { waitUntil } from '@vercel\u002Ffunctions'\n\u002F\u002F import { waitUntil } from 'cloudflare:workers' \u002F\u002F Vercel-style global on some runtimes\n\nconst { logger, finish, skipped } = createMiddlewareLogger({\n  method,\n  path,\n  requestId,\n  headers: extractSafeNodeHeaders(rawHeaders),\n  waitUntil, \u002F\u002F or ctx.waitUntil.bind(ctx) on Cloudflare\n  ...options,\n})\n",[531,2208,2209,2229,2237,2241,2267,2273,2279,2285,2297,2307,2315],{"__ignoreMap":818},[822,2210,2211,2213,2215,2218,2220,2222,2224,2227],{"class":824,"line":825},[822,2212,1151],{"class":1150},[822,2214,1158],{"class":1157},[822,2216,2217],{"class":1161}," waitUntil",[822,2219,1171],{"class":1157},[822,2221,1174],{"class":1150},[822,2223,1177],{"class":1157},[822,2225,2226],{"class":831},"@vercel\u002Ffunctions",[822,2228,1183],{"class":1157},[822,2230,2231,2234],{"class":824,"line":1186},[822,2232,2233],{"class":1239},"\u002F\u002F import { waitUntil } from 'cloudflare:workers'",[822,2235,2236],{"class":1239}," \u002F\u002F Vercel-style global on some runtimes\n",[822,2238,2239],{"class":824,"line":1194},[822,2240,1269],{"emptyLinePlaceholder":1268},[822,2242,2243,2245,2247,2249,2251,2253,2255,2257,2259,2261,2263,2265],{"class":824,"line":1203},[822,2244,1298],{"class":1278},[822,2246,1158],{"class":1157},[822,2248,1601],{"class":1161},[822,2250,1165],{"class":1157},[822,2252,1768],{"class":1161},[822,2254,1165],{"class":1157},[822,2256,2105],{"class":1161},[822,2258,1225],{"class":1157},[822,2260,1284],{"class":1157},[822,2262,2069],{"class":1315},[822,2264,1388],{"class":1161},[822,2266,1391],{"class":1157},[822,2268,2269,2271],{"class":824,"line":1211},[822,2270,2120],{"class":1161},[822,2272,1200],{"class":1157},[822,2274,2275,2277],{"class":824,"line":1222},[822,2276,2127],{"class":1161},[822,2278,1200],{"class":1157},[822,2280,2281,2283],{"class":824,"line":1236},[822,2282,2134],{"class":1161},[822,2284,1200],{"class":1157},[822,2286,2287,2289,2291,2293,2295],{"class":824,"line":1243},[822,2288,2141],{"class":1397},[822,2290,1401],{"class":1157},[822,2292,2074],{"class":1315},[822,2294,2148],{"class":1161},[822,2296,1200],{"class":1157},[822,2298,2299,2302,2304],{"class":824,"line":1265},[822,2300,2301],{"class":1161},"  waitUntil",[822,2303,1165],{"class":1157},[822,2305,2306],{"class":1239}," \u002F\u002F or ctx.waitUntil.bind(ctx) on Cloudflare\n",[822,2308,2309,2311,2313],{"class":824,"line":1272},[822,2310,2155],{"class":1157},[822,2312,1688],{"class":1161},[822,2314,1200],{"class":1157},[822,2316,2317,2319],{"class":824,"line":1290},[822,2318,1225],{"class":1157},[822,2320,1339],{"class":1161},[527,2322,2323,2326,2327,2329,2330,2332,2333,2335],{},[543,2324,2325],{},"Manifest mode"," — either pass ",[531,2328,780],{}," in ",[531,2331,704],{}," or declare ",[531,2334,784],{}," on the manifest when the hook lives on the framework context:",[812,2337,2339],{"className":1140,"code":2338,"language":1143,"meta":818,"style":818},"const integration = defineFrameworkIntegration\u003CWorkerContext>({\n  name: 'my-framework',\n  extractRequest: (ctx) => ({ \u002F* … *\u002F }),\n  attachLogger: (ctx, logger) => { \u002F* … *\u002F },\n  extractWaitUntil: ctx => ctx.executionCtx.waitUntil.bind(ctx.executionCtx),\n})\n\nexport function evlog(options: BaseEvlogOptions = {}) {\n  return async (ctx, next) => {\n    const { skipped, finish, runWith } = integration.start(ctx, options)\n    \u002F\u002F Per-request override still works:\n    \u002F\u002F integration.start(ctx, { ...options, waitUntil: ctx.executionCtx.waitUntil.bind(ctx.executionCtx) })\n    \u002F\u002F …\n  }\n}\n",[531,2340,2341,2362,2376,2404,2429,2467,2473,2477,2499,2519,2555,2560,2565,2570,2574],{"__ignoreMap":818},[822,2342,2343,2345,2347,2349,2351,2353,2356,2358,2360],{"class":824,"line":825},[822,2344,1298],{"class":1278},[822,2346,1370],{"class":1161},[822,2348,1373],{"class":1157},[822,2350,1376],{"class":1315},[822,2352,1379],{"class":1157},[822,2354,2355],{"class":828},"WorkerContext",[822,2357,1385],{"class":1157},[822,2359,1388],{"class":1161},[822,2361,1391],{"class":1157},[822,2363,2364,2366,2368,2370,2372,2374],{"class":824,"line":1186},[822,2365,1398],{"class":1397},[822,2367,1401],{"class":1157},[822,2369,1177],{"class":1157},[822,2371,1406],{"class":831},[822,2373,1331],{"class":1157},[822,2375,1200],{"class":1157},[822,2377,2378,2380,2382,2384,2387,2389,2391,2393,2395,2398,2400,2402],{"class":824,"line":1194},[822,2379,1416],{"class":1315},[822,2381,1401],{"class":1157},[822,2383,1421],{"class":1157},[822,2385,2386],{"class":1424},"ctx",[822,2388,623],{"class":1157},[822,2390,1430],{"class":1278},[822,2392,1421],{"class":1161},[822,2394,1872],{"class":1157},[822,2396,2397],{"class":1239}," \u002F* … *\u002F",[822,2399,1171],{"class":1157},[822,2401,623],{"class":1161},[822,2403,1200],{"class":1157},[822,2405,2406,2408,2410,2412,2414,2416,2418,2420,2422,2424,2426],{"class":824,"line":1203},[822,2407,1590],{"class":1315},[822,2409,1401],{"class":1157},[822,2411,1421],{"class":1157},[822,2413,2386],{"class":1424},[822,2415,1165],{"class":1157},[822,2417,1601],{"class":1424},[822,2419,623],{"class":1157},[822,2421,1430],{"class":1278},[822,2423,1158],{"class":1157},[822,2425,2397],{"class":1239},[822,2427,2428],{"class":1157}," },\n",[822,2430,2431,2434,2436,2439,2441,2443,2445,2448,2450,2452,2454,2457,2460,2462,2465],{"class":824,"line":1211},[822,2432,2433],{"class":1315},"  extractWaitUntil",[822,2435,1401],{"class":1157},[822,2437,2438],{"class":1424}," ctx",[822,2440,1430],{"class":1278},[822,2442,2438],{"class":1161},[822,2444,1448],{"class":1157},[822,2446,2447],{"class":1161},"executionCtx",[822,2449,1448],{"class":1157},[822,2451,780],{"class":1161},[822,2453,1448],{"class":1157},[822,2455,2456],{"class":1315},"bind",[822,2458,2459],{"class":1161},"(ctx",[822,2461,1448],{"class":1157},[822,2463,2464],{"class":1161},"executionCtx)",[822,2466,1200],{"class":1157},[822,2468,2469,2471],{"class":824,"line":1222},[822,2470,1225],{"class":1157},[822,2472,1339],{"class":1161},[822,2474,2475],{"class":824,"line":1236},[822,2476,1269],{"emptyLinePlaceholder":1268},[822,2478,2479,2481,2483,2485,2487,2489,2491,2493,2495,2497],{"class":824,"line":1243},[822,2480,1275],{"class":1150},[822,2482,1680],{"class":1278},[822,2484,1683],{"class":1315},[822,2486,1388],{"class":1157},[822,2488,1688],{"class":1424},[822,2490,1401],{"class":1157},[822,2492,1217],{"class":828},[822,2494,1284],{"class":1157},[822,2496,1697],{"class":1157},[822,2498,1191],{"class":1157},[822,2500,2501,2503,2505,2507,2509,2511,2513,2515,2517],{"class":824,"line":1265},[822,2502,1705],{"class":1150},[822,2504,1708],{"class":1278},[822,2506,1421],{"class":1157},[822,2508,2386],{"class":1424},[822,2510,1165],{"class":1157},[822,2512,1730],{"class":1424},[822,2514,623],{"class":1157},[822,2516,1430],{"class":1278},[822,2518,1191],{"class":1157},[822,2520,2521,2523,2525,2527,2529,2531,2533,2535,2537,2539,2541,2543,2545,2547,2549,2551,2553],{"class":824,"line":1272},[822,2522,1758],{"class":1278},[822,2524,1158],{"class":1157},[822,2526,1763],{"class":1161},[822,2528,1165],{"class":1157},[822,2530,1768],{"class":1161},[822,2532,1165],{"class":1157},[822,2534,1773],{"class":1161},[822,2536,1171],{"class":1157},[822,2538,1284],{"class":1157},[822,2540,1780],{"class":1161},[822,2542,1448],{"class":1157},[822,2544,1785],{"class":1315},[822,2546,1388],{"class":1397},[822,2548,2386],{"class":1161},[822,2550,1165],{"class":1157},[822,2552,774],{"class":1161},[822,2554,1339],{"class":1397},[822,2556,2557],{"class":824,"line":1290},[822,2558,2559],{"class":1239},"    \u002F\u002F Per-request override still works:\n",[822,2561,2562],{"class":824,"line":1295},[822,2563,2564],{"class":1239},"    \u002F\u002F integration.start(ctx, { ...options, waitUntil: ctx.executionCtx.waitUntil.bind(ctx.executionCtx) })\n",[822,2566,2567],{"class":824,"line":1322},[822,2568,2569],{"class":1239},"    \u002F\u002F …\n",[822,2571,2572],{"class":824,"line":1336},[822,2573,1953],{"class":1157},[822,2575,2576],{"class":824,"line":1342},[822,2577,1959],{"class":1157},[527,2579,2580,2581,2584,2585,2587],{},"Per-request ",[531,2582,2583],{},"options.waitUntil"," takes precedence over ",[531,2586,784],{},". Without either, drains are awaited (correct for traditional Node.js servers).",[804,2589,2591],{"id":2590},"non-http-runtimes","Non-HTTP runtimes",[527,2593,2594,2595,661,2597,2055],{},"For queue workers, CLI drivers, cron jobs, or durable execution engines, skip the HTTP-shaped helpers and use ",[531,2596,791],{},[531,2598,537],{},[812,2600,2604],{"className":2601,"code":2602,"language":2603,"meta":818,"style":818},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { createRequestLogger } from 'evlog\u002Ftoolkit'\n\nasync function processJob(job: Job) {\n  const logger = createRequestLogger({\n    service: 'jobs',\n    context: { jobId: job.id, queue: job.queue },\n  })\n\n  try {\n    await runJob(job)\n    logger.set({ status: 'success' })\n  } catch (err) {\n    logger.error(err)\n    throw err\n  } finally {\n    await logger.emit()\n  }\n}\n","ts",[531,2605,2606,2625,2629,2653,2668,2684,2722,2728,2732,2739,2753,2782,2797,2811,2819,2828,2841,2845],{"__ignoreMap":818},[822,2607,2608,2610,2612,2615,2617,2619,2621,2623],{"class":824,"line":825},[822,2609,1151],{"class":1150},[822,2611,1158],{"class":1157},[822,2613,2614],{"class":1161}," createRequestLogger",[822,2616,1171],{"class":1157},[822,2618,1174],{"class":1150},[822,2620,1177],{"class":1157},[822,2622,537],{"class":831},[822,2624,1183],{"class":1157},[822,2626,2627],{"class":824,"line":1186},[822,2628,1269],{"emptyLinePlaceholder":1268},[822,2630,2631,2634,2636,2639,2641,2644,2646,2649,2651],{"class":824,"line":1194},[822,2632,2633],{"class":1278},"async",[822,2635,1680],{"class":1278},[822,2637,2638],{"class":1315}," processJob",[822,2640,1388],{"class":1157},[822,2642,2643],{"class":1424},"job",[822,2645,1401],{"class":1157},[822,2647,2648],{"class":828}," Job",[822,2650,623],{"class":1157},[822,2652,1191],{"class":1157},[822,2654,2655,2658,2660,2662,2664,2666],{"class":824,"line":1203},[822,2656,2657],{"class":1278},"  const",[822,2659,1601],{"class":1161},[822,2661,1284],{"class":1157},[822,2663,2614],{"class":1315},[822,2665,1388],{"class":1397},[822,2667,1391],{"class":1157},[822,2669,2670,2673,2675,2677,2680,2682],{"class":824,"line":1211},[822,2671,2672],{"class":1397},"    service",[822,2674,1401],{"class":1157},[822,2676,1177],{"class":1157},[822,2678,2679],{"class":831},"jobs",[822,2681,1331],{"class":1157},[822,2683,1200],{"class":1157},[822,2685,2686,2689,2691,2693,2696,2698,2701,2703,2706,2708,2711,2713,2715,2717,2720],{"class":824,"line":1222},[822,2687,2688],{"class":1397},"    context",[822,2690,1401],{"class":1157},[822,2692,1158],{"class":1157},[822,2694,2695],{"class":1397}," jobId",[822,2697,1401],{"class":1157},[822,2699,2700],{"class":1161}," job",[822,2702,1448],{"class":1157},[822,2704,2705],{"class":1161},"id",[822,2707,1165],{"class":1157},[822,2709,2710],{"class":1397}," queue",[822,2712,1401],{"class":1157},[822,2714,2700],{"class":1161},[822,2716,1448],{"class":1157},[822,2718,2719],{"class":1161},"queue",[822,2721,2428],{"class":1157},[822,2723,2724,2726],{"class":824,"line":1236},[822,2725,1580],{"class":1157},[822,2727,1339],{"class":1397},[822,2729,2730],{"class":824,"line":1243},[822,2731,1269],{"emptyLinePlaceholder":1268},[822,2733,2734,2737],{"class":824,"line":1265},[822,2735,2736],{"class":1150},"  try",[822,2738,1191],{"class":1157},[822,2740,2741,2744,2747,2749,2751],{"class":824,"line":1272},[822,2742,2743],{"class":1150},"    await",[822,2745,2746],{"class":1315}," runJob",[822,2748,1388],{"class":1397},[822,2750,2643],{"class":1161},[822,2752,1339],{"class":1397},[822,2754,2755,2758,2760,2763,2765,2767,2769,2771,2773,2776,2778,2780],{"class":824,"line":1290},[822,2756,2757],{"class":1161},"    logger",[822,2759,1448],{"class":1157},[822,2761,2762],{"class":1315},"set",[822,2764,1388],{"class":1397},[822,2766,1872],{"class":1157},[822,2768,1875],{"class":1397},[822,2770,1401],{"class":1157},[822,2772,1177],{"class":1157},[822,2774,2775],{"class":831},"success",[822,2777,1331],{"class":1157},[822,2779,1171],{"class":1157},[822,2781,1339],{"class":1397},[822,2783,2784,2786,2788,2790,2793,2795],{"class":824,"line":1295},[822,2785,1580],{"class":1157},[822,2787,1897],{"class":1150},[822,2789,1421],{"class":1397},[822,2791,2792],{"class":1161},"err",[822,2794,1808],{"class":1397},[822,2796,1391],{"class":1157},[822,2798,2799,2801,2803,2805,2807,2809],{"class":824,"line":1322},[822,2800,2757],{"class":1161},[822,2802,1448],{"class":1157},[822,2804,1902],{"class":1315},[822,2806,1388],{"class":1397},[822,2808,2792],{"class":1161},[822,2810,1339],{"class":1397},[822,2812,2813,2816],{"class":824,"line":1336},[822,2814,2815],{"class":1150},"    throw",[822,2817,2818],{"class":1161}," err\n",[822,2820,2821,2823,2826],{"class":824,"line":1342},[822,2822,1580],{"class":1157},[822,2824,2825],{"class":1150}," finally",[822,2827,1191],{"class":1157},[822,2829,2830,2832,2834,2836,2839],{"class":824,"line":1347},[822,2831,2743],{"class":1150},[822,2833,1601],{"class":1161},[822,2835,1448],{"class":1157},[822,2837,2838],{"class":1315},"emit",[822,2840,1821],{"class":1397},[822,2842,2843],{"class":824,"line":1360},[822,2844,1953],{"class":1157},[822,2846,2847],{"class":824,"line":1365},[822,2848,1959],{"class":1157},[527,2850,2851,2852,2855],{},"Same enrichers, same drain hook, same ",[585,2853,2854],{"href":477},"identity headers"," on outbound HTTP drain requests — only the entry point shape changes.",[804,2857,2859],{"id":2858},"reference-implementations","Reference implementations",[527,2861,2862],{},"Study these built-in integrations for framework-specific patterns:",[558,2864,2865,2881],{},[561,2866,2867],{},[564,2868,2869,2872,2875,2878],{},[567,2870,2871],{},"Framework",[567,2873,2874],{},"Lines",[567,2876,2877],{},"Mode",[567,2879,2880],{},"Source",[577,2882,2883,2900,2916,2933,2950,2967],{},[564,2884,2885,2887,2890,2893],{},[582,2886,260],{},[582,2888,2889],{},"~50",[582,2891,2892],{},"manifest",[582,2894,2895],{},[585,2896,2899],{"href":2897,"rel":2898},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Fhono\u002Findex.ts",[802],"hono\u002Findex.ts",[564,2901,2902,2904,2906,2909],{},[582,2903,255],{},[582,2905,2889],{},[582,2907,2908],{},"manifest + ALS",[582,2910,2911],{},[585,2912,2915],{"href":2913,"rel":2914},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Fexpress\u002Findex.ts",[802],"express\u002Findex.ts",[564,2917,2918,2920,2923,2926],{},[582,2919,265],{},[582,2921,2922],{},"~70",[582,2924,2925],{},"manifest + Fastify hooks",[582,2927,2928],{},[585,2929,2932],{"href":2930,"rel":2931},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Ffastify\u002Findex.ts",[802],"fastify\u002Findex.ts",[564,2934,2935,2937,2940,2943],{},[582,2936,270],{},[582,2938,2939],{},"~80",[582,2941,2942],{},"manifest + custom ALS scoping",[582,2944,2945],{},[585,2946,2949],{"href":2947,"rel":2948},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Felysia\u002Findex.ts",[802],"elysia\u002Findex.ts",[564,2951,2952,2954,2957,2960],{},[582,2953,250],{},[582,2955,2956],{},"~120",[582,2958,2959],{},"custom (interceptor)",[582,2961,2962],{},[585,2963,2966],{"href":2964,"rel":2965},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Fnestjs\u002F",[802],"nestjs\u002F",[564,2968,2969,2971,2974,2980],{},[582,2970,235],{},[582,2972,2973],{},"~90",[582,2975,2976,2977,2979],{},"custom (",[531,2978,622],{}," hook)",[582,2981,2982],{},[585,2983,2986],{"href":2984,"rel":2985},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Fsveltekit\u002F",[802],"sveltekit\u002F",[548,2988,2991,2992,2997],{"color":2989,"icon":2990},"neutral","i-lucide-heart","Built an integration for a framework we don't support? ",[585,2993,2996],{"href":2994,"rel":2995},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fpulls",[802],"Open a PR"," — the community will thank you.",[804,2999,3001],{"id":3000},"next-steps","Next steps",[649,3003,3004,3010,3016,3021,3026,3031],{},[652,3005,3006,3009],{},[585,3007,3008],{"href":482},"Custom Drains"," — same toolkit shape for drain destinations",[652,3011,3012,3015],{},[585,3013,3014],{"href":469},"Custom Enrichers"," — same toolkit shape for derived event fields",[652,3017,3018,3020],{},[585,3019,464],{"href":465}," — multi-hook extensions (drain + enrich + keep in one object)",[652,3022,3023,3025],{},[585,3024,46],{"href":47}," — design comprehensive events with context layering",[652,3027,3028,3030],{},[585,3029,61],{"href":62}," — control log volume with head and tail sampling",[652,3032,3033,3035],{},[585,3034,133],{"href":138}," — send logs to Axiom, Sentry, PostHog, and more",[3037,3038,3039],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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}",{"title":818,"searchDepth":1186,"depth":1186,"links":3041},[3042,3043,3044,3048,3049,3050,3051,3052],{"id":806,"depth":1186,"text":807},{"id":881,"depth":1186,"text":882},{"id":1124,"depth":1186,"text":1125,"children":3045},[3046],{"id":1969,"depth":1194,"text":3047},"What defineFrameworkIntegration does",{"id":2042,"depth":1186,"text":2043},{"id":2182,"depth":1186,"text":2183},{"id":2590,"depth":1186,"text":2591},{"id":2858,"depth":1186,"text":2859},{"id":3000,"depth":1186,"text":3001},"Build evlog support for an HTTP framework (or non-HTTP runtime) without a built-in integration. Use defineFrameworkIntegration for the (ctx, next) middleware shape, or createMiddlewareLogger \u002F createRequestLogger for everything else.","md",[3056,3058],{"label":3008,"icon":484,"to":482,"color":2989,"variant":3057},"subtle",{"label":3014,"icon":429,"to":469,"color":2989,"variant":3057},{},{"title":450,"icon":453},{"title":522,"description":3053},"tE0g7MuhC5DtwwxqiGtuCyY-5TQDWiziJyFf9R_bXaA",[3064,3066],{"title":445,"path":446,"stem":447,"description":3065,"icon":448,"children":-1},"Subscribe to wide events flowing through evlog — in-process with createStreamDrain, or over the network with the local SSE stream server.",{"title":455,"path":456,"stem":457,"description":3067,"icon":458,"children":-1},"Replay and tail the local NDJSON drain with readFsLogs and tailFsLogs — works in-process or from any external Node tool, survives restarts.",1785678940160]