[{"data":1,"prerenderedAt":2557},["ShallowReactive",2],{"navigation_docs":3,"-extend-custom-framework":464,"-extend-custom-framework-surround":2552},[4,30,80,245,379,434],{"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,369,374],{"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":284,"icon":315,"path":349,"stem":350,"children":351,"page":29},"\u002Fuse-cases\u002Ftelemetry","4.use-cases\u002F4.telemetry",[352,355,360,365],{"title":36,"path":353,"stem":354,"icon":39},"\u002Fuse-cases\u002Ftelemetry\u002Foverview","4.use-cases\u002F4.telemetry\u002F01.overview",{"title":356,"path":357,"stem":358,"icon":359},"Setup","\u002Fuse-cases\u002Ftelemetry\u002Fsetup","4.use-cases\u002F4.telemetry\u002F02.setup","i-lucide-wrench",{"title":361,"path":362,"stem":363,"icon":364},"Ingest","\u002Fuse-cases\u002Ftelemetry\u002Fingest","4.use-cases\u002F4.telemetry\u002F03.ingest","i-lucide-server",{"title":366,"path":367,"stem":368,"icon":79},"Reference","\u002Fuse-cases\u002Ftelemetry\u002Freference","4.use-cases\u002F4.telemetry\u002F04.reference",{"title":370,"path":371,"stem":372,"icon":373},"Enrichers","\u002Fuse-cases\u002Fenrichers","4.use-cases\u002F5.enrichers","i-lucide-sparkles",{"title":375,"path":376,"stem":377,"icon":378},"eve","\u002Fuse-cases\u002Feve","4.use-cases\u002F5.eve","i-custom-eve",{"title":380,"path":381,"stem":382,"children":383,"page":29},"Extend","\u002Fextend","5.extend",[384,388,393,398,403,407,411,415,419,424,429],{"title":36,"path":385,"stem":386,"icon":387},"\u002Fextend\u002Foverview","5.extend\u002F0.overview","i-lucide-blocks",{"title":389,"path":390,"stem":391,"icon":392},"Stream","\u002Fextend\u002Fstream","5.extend\u002F1.stream","i-lucide-radio-tower",{"title":394,"path":395,"stem":396,"icon":397},"Custom framework","\u002Fextend\u002Fcustom-framework","5.extend\u002F10.custom-framework","i-lucide-puzzle",{"title":399,"path":400,"stem":401,"icon":402},"FS reader","\u002Fextend\u002Ffs-reader","5.extend\u002F2.fs-reader","i-lucide-folder-search",{"title":345,"path":404,"stem":405,"icon":406},"\u002Fextend\u002Fconsumer-recipes","5.extend\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":408,"path":409,"stem":410,"icon":387},"Plugins","\u002Fextend\u002Fplugins","5.extend\u002F4.plugins",{"title":412,"path":413,"stem":414,"icon":373},"Custom enrichers","\u002Fextend\u002Fcustom-enrichers","5.extend\u002F5.custom-enrichers",{"title":416,"path":417,"stem":418,"icon":64},"Tail sampling","\u002Fextend\u002Ftail-sampling","5.extend\u002F6.tail-sampling",{"title":420,"path":421,"stem":422,"icon":423},"Identity headers","\u002Fextend\u002Fidentity-headers","5.extend\u002F7.identity-headers","i-lucide-fingerprint",{"title":425,"path":426,"stem":427,"icon":428},"Custom drains","\u002Fextend\u002Fcustom-drains","5.extend\u002F8.custom-drains","i-lucide-share-2",{"title":430,"path":431,"stem":432,"icon":433},"Drain pipeline","\u002Fextend\u002Fdrain-pipeline","5.extend\u002F9.drain-pipeline","i-lucide-workflow",{"title":366,"path":435,"stem":436,"children":437,"page":29},"\u002Freference","6.reference",[438,443,446,451,455,460],{"title":439,"path":440,"stem":441,"icon":442},"Configuration","\u002Freference\u002Fconfiguration","6.reference\u002F1.configuration","i-lucide-settings",{"title":312,"path":444,"stem":445,"icon":315},"\u002Freference\u002Fperformance","6.reference\u002F2.performance",{"title":447,"path":448,"stem":449,"icon":450},"Vite Plugin","\u002Freference\u002Fvite-plugin","6.reference\u002F3.vite-plugin","i-custom-vite",{"title":452,"path":453,"stem":454,"icon":318},"Best Practices","\u002Freference\u002Fbest-practices","6.reference\u002F4.best-practices",{"title":456,"path":457,"stem":458,"icon":459},"vs Other Loggers","\u002Freference\u002Fvs-other-loggers","6.reference\u002F5.vs-other-loggers","i-lucide-scale",{"title":461,"path":462,"stem":463,"icon":373},"Agent Skills","\u002Freference\u002Fagent-skills","6.reference\u002F6.agent-skills",{"id":465,"title":466,"body":467,"description":2542,"extension":2543,"links":2544,"meta":2548,"navigation":2549,"path":395,"seo":2550,"stem":396,"__hash__":2551},"docs\u002F5.extend\u002F10.custom-framework.md","Custom Framework Integration",{"type":468,"value":469,"toc":2530},"minimark",[470,483,491,501,584,731,736,807,811,1006,1029,1033,1042,1857,1863,1871,1874,1934,1937,1941,1953,2063,2077,2081,2088,2339,2346,2350,2353,2477,2488,2492,2526],[471,472,473,474,478,479,482],"p",{},"When the framework you use doesn't have an ",[475,476,477],"code",{},"evlog\u002F\u003Cframework>"," package yet, you build the integration yourself. ",[475,480,481],{},"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.",[471,484,485,486,490],{},"The mental model is always the same: ",[487,488,489],"strong",{},"request lifecycle → logger creation → enrich → drain",". The toolkit handles the request-context plumbing.",[492,493,496,497,500],"callout",{"color":494,"icon":495},"warning","i-lucide-flask-conical","The toolkit API is marked as ",[487,498,499],{},"beta",". The surface is stable (used by all built-in integrations) but may evolve based on community feedback.",[502,503,504,520],"table",{},[505,506,507],"thead",{},[508,509,510,514,517],"tr",{},[511,512,513],"th",{},"Surface",[511,515,516],{},"What it does",[511,518,519],{},"When to use",[521,522,523,545,568],"tbody",{},[508,524,525,535,538],{},[526,527,528],"td",{},[529,530,532],"a",{"href":531},"#manifest-mode-recommended",[475,533,534],{},"defineFrameworkIntegration()",[526,536,537],{},"Declaratively wire request extraction + logger attachment",[526,539,540,541,544],{},"HTTP frameworks with a ",[475,542,543],{},"(ctx, next)"," middleware shape (Hono, Express, Fastify, Elysia, NestJS-shaped)",[508,546,547,555,558],{},[526,548,549],{},[529,550,552],{"href":551},"#custom-mode",[475,553,554],{},"createMiddlewareLogger()",[526,556,557],{},"Imperative path: create the logger at request start, emit on response end",[526,559,560,561,563,564,567],{},"Frameworks whose lifecycle doesn't fit ",[475,562,543],{}," (NestJS interceptors, Next.js App Router, SvelteKit ",[475,565,566],{},"handle",")",[508,569,570,578,581],{},[526,571,572],{},[529,573,575],{"href":574},"#non-http-runtimes",[475,576,577],{},"createRequestLogger()",[526,579,580],{},"Wrap any unit of work in a logger lifecycle",[526,582,583],{},"Non-HTTP runtimes (queue workers, CLI, cron, durable workflows)",[585,586,589,592,723],"prompt",{":actions":587,"description":588,"icon":397},"[\"copy\",\"cursor\",\"claude\"]","Build an evlog integration for a custom framework",[471,590,591],{},"Wire evlog into an HTTP framework (or non-HTTP runtime) that doesn't have a built-in integration.",[593,594,595,624,638,648,662,677,688,714],"ul",{},[596,597,598,599,601,602,605,606,608,609,612,613,616,617,620,621],"li",{},"For HTTP frameworks with ",[475,600,543],{},", use ",[475,603,604],{},"defineFrameworkIntegration"," from ",[475,607,481],{}," — declare ",[475,610,611],{},"extractRequest(ctx)"," returning ",[475,614,615],{},"{ method, path, headers, requestId? }",", ",[475,618,619],{},"attachLogger(ctx, logger)",", and an optional storage from ",[475,622,623],{},"createLoggerStorage()",[596,625,626,627,630,631,634,635,637],{},"Headers may be either Web ",[475,628,629],{},"Headers"," or Node ",[475,632,633],{},"IncomingHttpHeaders"," — ",[475,636,604],{}," normalizes both",[596,639,640,641,644,645],{},"In your middleware, call ",[475,642,643],{},"integration.start(ctx, options)"," which returns ",[475,646,647],{},"{ skipped, finish, runWith, logger, middlewareOptions }",[596,649,650,651,654,655,658,659],{},"If ",[475,652,653],{},"skipped"," is ",[475,656,657],{},"true",", skip directly to ",[475,660,661],{},"next",[596,663,664,665,668,669,672,673,676],{},"Run downstream handlers inside ",[475,666,667],{},"runWith(() => next())"," so ",[475,670,671],{},"AsyncLocalStorage"," and ",[475,674,675],{},"log.fork()"," work",[596,678,679,680,683,684,687],{},"On success: ",[475,681,682],{},"await finish({ status })","; on error: ",[475,685,686],{},"await finish({ error })"," then re-throw",[596,689,690,691,616,694,616,697,616,700,616,703,616,706,709,710,713],{},"Expose ",[475,692,693],{},"drain",[475,695,696],{},"enrich",[475,698,699],{},"keep",[475,701,702],{},"include",[475,704,705],{},"exclude",[475,707,708],{},"routes",", and ",[475,711,712],{},"plugins"," options",[596,715,716,717,605,720,722],{},"For non-HTTP runtimes (queue workers, CLI, cron), use ",[475,718,719],{},"createRequestLogger",[475,721,481],{}," directly — wrap each unit of work in a logger lifecycle",[471,724,725,726],{},"Docs: ",[529,727,728],{"href":728,"rel":729},"https:\u002F\u002Fwww.evlog.dev\u002Fextend\u002Fcustom-framework",[730],"nofollow",[732,733,735],"h2",{"id":734},"install","Install",[737,738,739,764,778,792],"code-group",{},[740,741,747],"pre",{"className":742,"code":743,"filename":744,"language":745,"meta":746,"style":746},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add evlog\n","pnpm","bash","",[475,748,749],{"__ignoreMap":746},[750,751,754,757,761],"span",{"class":752,"line":753},"line",1,[750,755,744],{"class":756},"sBMFI",[750,758,760],{"class":759},"sfazB"," add",[750,762,763],{"class":759}," evlog\n",[740,765,768],{"className":742,"code":766,"filename":767,"language":745,"meta":746,"style":746},"bun add evlog\n","bun",[475,769,770],{"__ignoreMap":746},[750,771,772,774,776],{"class":752,"line":753},[750,773,767],{"class":756},[750,775,760],{"class":759},[750,777,763],{"class":759},[740,779,782],{"className":742,"code":780,"filename":781,"language":745,"meta":746,"style":746},"yarn add evlog\n","yarn",[475,783,784],{"__ignoreMap":746},[750,785,786,788,790],{"class":752,"line":753},[750,787,781],{"class":756},[750,789,760],{"class":759},[750,791,763],{"class":759},[740,793,796],{"className":742,"code":794,"filename":795,"language":745,"meta":746,"style":746},"npm install evlog\n","npm",[475,797,798],{"__ignoreMap":746},[750,799,800,802,805],{"class":752,"line":753},[750,801,795],{"class":756},[750,803,804],{"class":759}," install",[750,806,763],{"class":759},[732,808,810],{"id":809},"whats-in-the-toolkit","What's in the toolkit",[502,812,813,823],{},[505,814,815],{},[508,816,817,820],{},[511,818,819],{},"Export",[511,821,822],{},"Purpose",[521,824,825,835,845,855,879,892,905,917,933,951,965,996],{},[508,826,827,832],{},[526,828,829],{},[475,830,831],{},"defineFrameworkIntegration(spec)",[526,833,834],{},"Manifest factory — extract request, create logger, attach, run with ALS",[508,836,837,842],{},[526,838,839],{},[475,840,841],{},"createMiddlewareLogger(opts)",[526,843,844],{},"Lower-level lifecycle (custom mode)",[508,846,847,852],{},[526,848,849],{},[475,850,851],{},"createRequestLogger(opts)",[526,853,854],{},"Wrap a non-HTTP unit of work in a logger lifecycle",[508,856,857,862],{},[526,858,859],{},[475,860,861],{},"BaseEvlogOptions",[526,863,864,865,616,867,616,869,616,871,616,873,616,875,616,877],{},"Base user-facing options — ",[475,866,693],{},[475,868,696],{},[475,870,699],{},[475,872,702],{},[475,874,705],{},[475,876,708],{},[475,878,712],{},[508,880,881,886],{},[526,882,883],{},[475,884,885],{},"MiddlewareLoggerResult",[526,887,888,889],{},"Return type: ",[475,890,891],{},"{ logger, finish, skipped }",[508,893,894,899],{},[526,895,896],{},[475,897,898],{},"extractSafeHeaders(headers)",[526,900,901,902,904],{},"Filter sensitive headers from a Web API ",[475,903,629],{}," object",[508,906,907,912],{},[526,908,909],{},[475,910,911],{},"extractSafeNodeHeaders(headers)",[526,913,914,915],{},"Filter sensitive headers from Node.js ",[475,916,633],{},[508,918,919,924],{},[526,920,921],{},[475,922,923],{},"createLoggerStorage(hint)",[526,925,926,927,930,931],{},"Factory returning ",[475,928,929],{},"{ storage, useLogger }"," backed by ",[475,932,671],{},[508,934,935,940],{},[526,936,937],{},[475,938,939],{},"attachForkToLogger(storage, parent, opts)",[526,941,942,943,946,947,950],{},"Wires ",[475,944,945],{},"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 ",[475,948,949],{},"createMiddlewareLogger"," returns the logger and before the lifecycle finishes",[508,952,953,958],{},[526,954,955],{},[475,956,957],{},"defineEvlog(config)",[526,959,960,961,964],{},"Canonical config object — works for ",[475,962,963],{},"initLogger"," and middleware options",[508,966,967,972],{},[526,968,969],{},[475,970,971],{},"definePlugin(plugin)",[526,973,974,975,616,978,616,980,616,982,616,984,616,987,616,990,616,993],{},"Plugin contract — opt into any subset of ",[475,976,977],{},"setup",[475,979,696],{},[475,981,693],{},[475,983,699],{},[475,985,986],{},"onRequestStart",[475,988,989],{},"onRequestFinish",[475,991,992],{},"onClientLog",[475,994,995],{},"extendLogger",[508,997,998,1003],{},[526,999,1000],{},[475,1001,1002],{},"composeEnrichers \u002F composeDrains \u002F composeKeep \u002F composePlugins",[526,1004,1005],{},"Combine multiple extensions into one",[471,1007,1008,1009,616,1012,616,1015,616,1018,709,1021,1024,1025,1028],{},"Types like ",[475,1010,1011],{},"RequestLogger",[475,1013,1014],{},"DrainContext",[475,1016,1017],{},"EnrichContext",[475,1019,1020],{},"WideEvent",[475,1022,1023],{},"TailSamplingContext"," are exported from the main ",[475,1026,1027],{},"evlog"," package.",[732,1030,1032],{"id":1031},"manifest-mode-recommended","Manifest mode (recommended)",[471,1034,1035,1036,1038,1039,1041],{},"Most frameworks fit a ",[475,1037,543],{}," middleware shape. For those, write a manifest describing how to extract the request and attach the logger — ",[475,1040,604],{}," does the rest.",[740,1043,1048],{"className":1044,"code":1045,"filename":1046,"language":1047,"meta":746,"style":746},"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'\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",[475,1049,1050,1088,1096,1105,1113,1124,1138,1160,1167,1185,1190,1217,1231,1237,1242,1255,1260,1289,1308,1332,1361,1387,1404,1442,1463,1472,1482,1505,1544,1550,1558,1565,1570,1597,1650,1693,1708,1719,1725,1731,1739,1758,1786,1804,1831,1840,1845,1851],{"__ignoreMap":746},[750,1051,1052,1056,1059,1063,1067,1070,1073,1076,1079,1082,1085],{"class":752,"line":753},[750,1053,1055],{"class":1054},"s7zQu","import",[750,1057,1058],{"class":1054}," type",[750,1060,1062],{"class":1061},"sMK4o"," {",[750,1064,1066],{"class":1065},"sTEyZ"," IncomingMessage",[750,1068,1069],{"class":1061},",",[750,1071,1072],{"class":1065}," ServerResponse",[750,1074,1075],{"class":1061}," }",[750,1077,1078],{"class":1054}," from",[750,1080,1081],{"class":1061}," '",[750,1083,1084],{"class":759},"node:http",[750,1086,1087],{"class":1061},"'\n",[750,1089,1091,1093],{"class":752,"line":1090},2,[750,1092,1055],{"class":1054},[750,1094,1095],{"class":1061}," {\n",[750,1097,1099,1102],{"class":752,"line":1098},3,[750,1100,1101],{"class":1065},"  createLoggerStorage",[750,1103,1104],{"class":1061},",\n",[750,1106,1108,1111],{"class":752,"line":1107},4,[750,1109,1110],{"class":1065},"  defineFrameworkIntegration",[750,1112,1104],{"class":1061},[750,1114,1116,1119,1122],{"class":752,"line":1115},5,[750,1117,1118],{"class":1054},"  type",[750,1120,1121],{"class":1065}," BaseEvlogOptions",[750,1123,1104],{"class":1061},[750,1125,1127,1130,1132,1134,1136],{"class":752,"line":1126},6,[750,1128,1129],{"class":1061},"}",[750,1131,1078],{"class":1054},[750,1133,1081],{"class":1061},[750,1135,481],{"class":759},[750,1137,1087],{"class":1061},[750,1139,1141,1143,1145,1147,1150,1152,1154,1156,1158],{"class":752,"line":1140},7,[750,1142,1055],{"class":1054},[750,1144,1058],{"class":1054},[750,1146,1062],{"class":1061},[750,1148,1149],{"class":1065}," RequestLogger",[750,1151,1075],{"class":1061},[750,1153,1078],{"class":1054},[750,1155,1081],{"class":1061},[750,1157,1027],{"class":759},[750,1159,1087],{"class":1061},[750,1161,1163],{"class":752,"line":1162},8,[750,1164,1166],{"emptyLinePlaceholder":1165},true,"\n",[750,1168,1170,1173,1176,1179,1182],{"class":752,"line":1169},9,[750,1171,1172],{"class":1054},"export",[750,1174,1058],{"class":1175},"spNyl",[750,1177,1178],{"class":756}," MyFrameworkEvlogOptions",[750,1180,1181],{"class":1061}," =",[750,1183,1184],{"class":756}," BaseEvlogOptions\n",[750,1186,1188],{"class":752,"line":1187},10,[750,1189,1166],{"emptyLinePlaceholder":1165},[750,1191,1193,1196,1198,1201,1203,1206,1208,1210,1214],{"class":752,"line":1192},11,[750,1194,1195],{"class":1175},"const",[750,1197,1062],{"class":1061},[750,1199,1200],{"class":1065}," storage",[750,1202,1069],{"class":1061},[750,1204,1205],{"class":1065}," useLogger ",[750,1207,1129],{"class":1061},[750,1209,1181],{"class":1061},[750,1211,1213],{"class":1212},"s2Zo4"," createLoggerStorage",[750,1215,1216],{"class":1065},"(\n",[750,1218,1220,1223,1226,1229],{"class":752,"line":1219},12,[750,1221,1222],{"class":1061},"  '",[750,1224,1225],{"class":759},"Cannot access logger outside of middleware context. Make sure evlog middleware is registered before your routes.",[750,1227,1228],{"class":1061},"'",[750,1230,1104],{"class":1061},[750,1232,1234],{"class":752,"line":1233},13,[750,1235,1236],{"class":1065},")\n",[750,1238,1240],{"class":752,"line":1239},14,[750,1241,1166],{"emptyLinePlaceholder":1165},[750,1243,1245,1247,1249,1252],{"class":752,"line":1244},15,[750,1246,1172],{"class":1054},[750,1248,1062],{"class":1061},[750,1250,1251],{"class":1065}," useLogger",[750,1253,1254],{"class":1061}," }\n",[750,1256,1258],{"class":752,"line":1257},16,[750,1259,1166],{"emptyLinePlaceholder":1165},[750,1261,1263,1265,1268,1271,1274,1277,1280,1283,1286],{"class":752,"line":1262},17,[750,1264,1195],{"class":1175},[750,1266,1267],{"class":1065}," integration ",[750,1269,1270],{"class":1061},"=",[750,1272,1273],{"class":1212}," defineFrameworkIntegration",[750,1275,1276],{"class":1061},"\u003C",[750,1278,1279],{"class":756},"IncomingMessage",[750,1281,1282],{"class":1061},">",[750,1284,1285],{"class":1065},"(",[750,1287,1288],{"class":1061},"{\n",[750,1290,1292,1296,1299,1301,1304,1306],{"class":752,"line":1291},18,[750,1293,1295],{"class":1294},"swJcz","  name",[750,1297,1298],{"class":1061},":",[750,1300,1081],{"class":1061},[750,1302,1303],{"class":759},"my-framework",[750,1305,1228],{"class":1061},[750,1307,1104],{"class":1061},[750,1309,1311,1314,1316,1319,1323,1325,1328,1330],{"class":752,"line":1310},19,[750,1312,1313],{"class":1212},"  extractRequest",[750,1315,1298],{"class":1061},[750,1317,1318],{"class":1061}," (",[750,1320,1322],{"class":1321},"sHdIc","req",[750,1324,567],{"class":1061},[750,1326,1327],{"class":1175}," =>",[750,1329,1318],{"class":1065},[750,1331,1288],{"class":1061},[750,1333,1335,1338,1340,1343,1346,1349,1352,1354,1357,1359],{"class":752,"line":1334},20,[750,1336,1337],{"class":1294},"    method",[750,1339,1298],{"class":1061},[750,1341,1342],{"class":1065}," req",[750,1344,1345],{"class":1061},".",[750,1347,1348],{"class":1065},"method ",[750,1350,1351],{"class":1061},"||",[750,1353,1081],{"class":1061},[750,1355,1356],{"class":759},"GET",[750,1358,1228],{"class":1061},[750,1360,1104],{"class":1061},[750,1362,1364,1367,1369,1371,1373,1376,1378,1380,1383,1385],{"class":752,"line":1363},21,[750,1365,1366],{"class":1294},"    path",[750,1368,1298],{"class":1061},[750,1370,1342],{"class":1065},[750,1372,1345],{"class":1061},[750,1374,1375],{"class":1065},"url ",[750,1377,1351],{"class":1061},[750,1379,1081],{"class":1061},[750,1381,1382],{"class":759},"\u002F",[750,1384,1228],{"class":1061},[750,1386,1104],{"class":1061},[750,1388,1390,1393,1395,1397,1399,1402],{"class":752,"line":1389},22,[750,1391,1392],{"class":1294},"    headers",[750,1394,1298],{"class":1061},[750,1396,1342],{"class":1065},[750,1398,1345],{"class":1061},[750,1400,1401],{"class":1065},"headers",[750,1403,1104],{"class":1061},[750,1405,1407,1410,1412,1415,1417,1419,1422,1424,1427,1429,1432,1435,1437,1440],{"class":752,"line":1406},23,[750,1408,1409],{"class":1294},"    requestId",[750,1411,1298],{"class":1061},[750,1413,1414],{"class":1061}," typeof",[750,1416,1342],{"class":1065},[750,1418,1345],{"class":1061},[750,1420,1421],{"class":1065},"headers[",[750,1423,1228],{"class":1061},[750,1425,1426],{"class":759},"x-request-id",[750,1428,1228],{"class":1061},[750,1430,1431],{"class":1065},"] ",[750,1433,1434],{"class":1061},"===",[750,1436,1081],{"class":1061},[750,1438,1439],{"class":759},"string",[750,1441,1087],{"class":1061},[750,1443,1445,1448,1450,1452,1454,1456,1458,1460],{"class":752,"line":1444},24,[750,1446,1447],{"class":1061},"      ?",[750,1449,1342],{"class":1065},[750,1451,1345],{"class":1061},[750,1453,1421],{"class":1065},[750,1455,1228],{"class":1061},[750,1457,1426],{"class":759},[750,1459,1228],{"class":1061},[750,1461,1462],{"class":1065},"]\n",[750,1464,1466,1469],{"class":752,"line":1465},25,[750,1467,1468],{"class":1061},"      :",[750,1470,1471],{"class":1061}," undefined,\n",[750,1473,1475,1478,1480],{"class":752,"line":1474},26,[750,1476,1477],{"class":1061},"  }",[750,1479,567],{"class":1065},[750,1481,1104],{"class":1061},[750,1483,1485,1488,1490,1492,1494,1496,1499,1501,1503],{"class":752,"line":1484},27,[750,1486,1487],{"class":1212},"  attachLogger",[750,1489,1298],{"class":1061},[750,1491,1318],{"class":1061},[750,1493,1322],{"class":1321},[750,1495,1069],{"class":1061},[750,1497,1498],{"class":1321}," logger",[750,1500,567],{"class":1061},[750,1502,1327],{"class":1175},[750,1504,1095],{"class":1061},[750,1506,1508,1511,1513,1516,1518,1521,1523,1526,1528,1530,1532,1534,1536,1539,1541],{"class":752,"line":1507},28,[750,1509,1510],{"class":1294},"    (",[750,1512,1322],{"class":1065},[750,1514,1515],{"class":1054}," as",[750,1517,1066],{"class":756},[750,1519,1520],{"class":1061}," &",[750,1522,1062],{"class":1061},[750,1524,1525],{"class":1294}," log",[750,1527,1298],{"class":1061},[750,1529,1149],{"class":756},[750,1531,1075],{"class":1061},[750,1533,567],{"class":1294},[750,1535,1345],{"class":1061},[750,1537,1538],{"class":1065},"log",[750,1540,1181],{"class":1061},[750,1542,1543],{"class":1065}," logger\n",[750,1545,1547],{"class":752,"line":1546},29,[750,1548,1549],{"class":1061},"  },\n",[750,1551,1553,1556],{"class":752,"line":1552},30,[750,1554,1555],{"class":1065},"  storage",[750,1557,1104],{"class":1061},[750,1559,1561,1563],{"class":752,"line":1560},31,[750,1562,1129],{"class":1061},[750,1564,1236],{"class":1065},[750,1566,1568],{"class":752,"line":1567},32,[750,1569,1166],{"emptyLinePlaceholder":1165},[750,1571,1573,1575,1578,1581,1583,1586,1588,1590,1592,1595],{"class":752,"line":1572},33,[750,1574,1172],{"class":1054},[750,1576,1577],{"class":1175}," function",[750,1579,1580],{"class":1212}," evlog",[750,1582,1285],{"class":1061},[750,1584,1585],{"class":1321},"options",[750,1587,1298],{"class":1061},[750,1589,1178],{"class":756},[750,1591,1181],{"class":1061},[750,1593,1594],{"class":1061}," {})",[750,1596,1095],{"class":1061},[750,1598,1600,1603,1606,1608,1610,1612,1614,1616,1619,1621,1623,1625,1628,1630,1633,1635,1638,1640,1643,1646,1648],{"class":752,"line":1599},34,[750,1601,1602],{"class":1054},"  return",[750,1604,1605],{"class":1175}," async",[750,1607,1318],{"class":1061},[750,1609,1322],{"class":1321},[750,1611,1298],{"class":1061},[750,1613,1066],{"class":756},[750,1615,1069],{"class":1061},[750,1617,1618],{"class":1321}," res",[750,1620,1298],{"class":1061},[750,1622,1072],{"class":756},[750,1624,1069],{"class":1061},[750,1626,1627],{"class":1212}," next",[750,1629,1298],{"class":1061},[750,1631,1632],{"class":1061}," ()",[750,1634,1327],{"class":1175},[750,1636,1637],{"class":756}," Promise",[750,1639,1276],{"class":1061},[750,1641,1642],{"class":756},"void",[750,1644,1645],{"class":1061},">)",[750,1647,1327],{"class":1175},[750,1649,1095],{"class":1061},[750,1651,1653,1656,1658,1661,1663,1666,1668,1671,1673,1675,1678,1680,1683,1685,1687,1689,1691],{"class":752,"line":1652},35,[750,1654,1655],{"class":1175},"    const",[750,1657,1062],{"class":1061},[750,1659,1660],{"class":1065}," skipped",[750,1662,1069],{"class":1061},[750,1664,1665],{"class":1065}," finish",[750,1667,1069],{"class":1061},[750,1669,1670],{"class":1065}," runWith",[750,1672,1075],{"class":1061},[750,1674,1181],{"class":1061},[750,1676,1677],{"class":1065}," integration",[750,1679,1345],{"class":1061},[750,1681,1682],{"class":1212},"start",[750,1684,1285],{"class":1294},[750,1686,1322],{"class":1065},[750,1688,1069],{"class":1061},[750,1690,713],{"class":1065},[750,1692,1236],{"class":1294},[750,1694,1696,1699,1701,1703,1706],{"class":752,"line":1695},36,[750,1697,1698],{"class":1054},"    if",[750,1700,1318],{"class":1294},[750,1702,653],{"class":1065},[750,1704,1705],{"class":1294},") ",[750,1707,1288],{"class":1061},[750,1709,1711,1714,1716],{"class":752,"line":1710},37,[750,1712,1713],{"class":1054},"      await",[750,1715,1627],{"class":1212},[750,1717,1718],{"class":1294},"()\n",[750,1720,1722],{"class":752,"line":1721},38,[750,1723,1724],{"class":1054},"      return\n",[750,1726,1728],{"class":752,"line":1727},39,[750,1729,1730],{"class":1061},"    }\n",[750,1732,1734,1737],{"class":752,"line":1733},40,[750,1735,1736],{"class":1054},"    try",[750,1738,1095],{"class":1061},[750,1740,1742,1744,1746,1748,1751,1753,1755],{"class":752,"line":1741},41,[750,1743,1713],{"class":1054},[750,1745,1670],{"class":1212},[750,1747,1285],{"class":1294},[750,1749,1750],{"class":1061},"()",[750,1752,1327],{"class":1175},[750,1754,1627],{"class":1212},[750,1756,1757],{"class":1294},"())\n",[750,1759,1761,1763,1765,1767,1770,1773,1775,1777,1779,1782,1784],{"class":752,"line":1760},42,[750,1762,1713],{"class":1054},[750,1764,1665],{"class":1212},[750,1766,1285],{"class":1294},[750,1768,1769],{"class":1061},"{",[750,1771,1772],{"class":1294}," status",[750,1774,1298],{"class":1061},[750,1776,1618],{"class":1065},[750,1778,1345],{"class":1061},[750,1780,1781],{"class":1065},"statusCode",[750,1783,1075],{"class":1061},[750,1785,1236],{"class":1294},[750,1787,1789,1792,1795,1797,1800,1802],{"class":752,"line":1788},43,[750,1790,1791],{"class":1061},"    }",[750,1793,1794],{"class":1054}," catch",[750,1796,1318],{"class":1294},[750,1798,1799],{"class":1065},"error",[750,1801,1705],{"class":1294},[750,1803,1288],{"class":1061},[750,1805,1807,1809,1811,1813,1815,1818,1820,1822,1824,1827,1829],{"class":752,"line":1806},44,[750,1808,1713],{"class":1054},[750,1810,1665],{"class":1212},[750,1812,1285],{"class":1294},[750,1814,1769],{"class":1061},[750,1816,1817],{"class":1294}," error",[750,1819,1298],{"class":1061},[750,1821,1817],{"class":1065},[750,1823,1515],{"class":1054},[750,1825,1826],{"class":756}," Error",[750,1828,1075],{"class":1061},[750,1830,1236],{"class":1294},[750,1832,1834,1837],{"class":752,"line":1833},45,[750,1835,1836],{"class":1054},"      throw",[750,1838,1839],{"class":1065}," error\n",[750,1841,1843],{"class":752,"line":1842},46,[750,1844,1730],{"class":1061},[750,1846,1848],{"class":752,"line":1847},47,[750,1849,1850],{"class":1061},"  }\n",[750,1852,1854],{"class":752,"line":1853},48,[750,1855,1856],{"class":1061},"}\n",[471,1858,1859,1860,1862],{},"That's it. This middleware gets every feature for free: route filtering, drain adapters, enrichers, tail sampling, error capture, plugin lifecycle hooks, ",[475,1861,675],{},", and duration tracking.",[1864,1865,1867,1868,1870],"h3",{"id":1866},"what-defineframeworkintegration-does","What ",[475,1869,604],{}," does",[471,1872,1873],{},"Given the manifest above, the helper:",[1875,1876,1877,1886,1897,1903,1907,1917],"ol",{},[596,1878,1879,1880,1882,1883,1885],{},"Normalizes headers (auto-detects ",[475,1881,629],{}," vs ",[475,1884,633],{},").",[596,1887,1888,1889,1892,1893,1896],{},"Generates a ",[475,1890,1891],{},"requestId"," if ",[475,1894,1895],{},"extractRequest"," doesn't return one.",[596,1898,1899,1900,1902],{},"Calls ",[475,1901,949],{}," with the merged options.",[596,1904,1899,1905,1345],{},[475,1906,619],{},[596,1908,1909,1910,1912,1913,1916],{},"Attaches ",[475,1911,675],{}," to the logger when ",[475,1914,1915],{},"storage"," is provided (so users can spawn correlated background work).",[596,1918,1919,1920,1923,1924,1927,1928,1931,1932,1345],{},"Exposes ",[475,1921,1922],{},"runWith(fn)"," — runs ",[475,1925,1926],{},"fn()"," inside ",[475,1929,1930],{},"storage.run(logger, …)"," if storage is configured, otherwise just calls ",[475,1933,1926],{},[471,1935,1936],{},"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.",[732,1938,1940],{"id":1939},"custom-mode","Custom mode",[471,1942,1943,1944,1946,1947,1949,1950,1952],{},"If your framework's lifecycle doesn't fit a clean ",[475,1945,543],{}," shape (NestJS interceptors, Next.js App Router, SvelteKit ",[475,1948,566],{},"), drop one level lower and call ",[475,1951,949],{}," directly:",[740,1954,1956],{"className":1044,"code":1955,"language":1047,"meta":746,"style":746},"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",[475,1957,1958,1982,1986,2013,2020,2027,2034,2048,2057],{"__ignoreMap":746},[750,1959,1960,1962,1964,1967,1969,1972,1974,1976,1978,1980],{"class":752,"line":753},[750,1961,1055],{"class":1054},[750,1963,1062],{"class":1061},[750,1965,1966],{"class":1065}," createMiddlewareLogger",[750,1968,1069],{"class":1061},[750,1970,1971],{"class":1065}," extractSafeNodeHeaders",[750,1973,1075],{"class":1061},[750,1975,1078],{"class":1054},[750,1977,1081],{"class":1061},[750,1979,481],{"class":759},[750,1981,1087],{"class":1061},[750,1983,1984],{"class":752,"line":1090},[750,1985,1166],{"emptyLinePlaceholder":1165},[750,1987,1988,1990,1992,1994,1996,1998,2000,2003,2005,2007,2009,2011],{"class":752,"line":1098},[750,1989,1195],{"class":1175},[750,1991,1062],{"class":1061},[750,1993,1498],{"class":1065},[750,1995,1069],{"class":1061},[750,1997,1665],{"class":1065},[750,1999,1069],{"class":1061},[750,2001,2002],{"class":1065}," skipped ",[750,2004,1129],{"class":1061},[750,2006,1181],{"class":1061},[750,2008,1966],{"class":1212},[750,2010,1285],{"class":1065},[750,2012,1288],{"class":1061},[750,2014,2015,2018],{"class":752,"line":1107},[750,2016,2017],{"class":1065},"  method",[750,2019,1104],{"class":1061},[750,2021,2022,2025],{"class":752,"line":1115},[750,2023,2024],{"class":1065},"  path",[750,2026,1104],{"class":1061},[750,2028,2029,2032],{"class":752,"line":1126},[750,2030,2031],{"class":1065},"  requestId",[750,2033,1104],{"class":1061},[750,2035,2036,2039,2041,2043,2046],{"class":752,"line":1140},[750,2037,2038],{"class":1294},"  headers",[750,2040,1298],{"class":1061},[750,2042,1971],{"class":1212},[750,2044,2045],{"class":1065},"(rawHeaders)",[750,2047,1104],{"class":1061},[750,2049,2050,2053,2055],{"class":752,"line":1162},[750,2051,2052],{"class":1061},"  ...",[750,2054,1585],{"class":1065},[750,2056,1104],{"class":1061},[750,2058,2059,2061],{"class":752,"line":1169},[750,2060,1129],{"class":1061},[750,2062,1236],{"class":1065},[471,2064,2065,2066,2069,2070,2072,2073,2076],{},"You'll be responsible for ALS wrapping (",[475,2067,2068],{},"storage.run","), ",[475,2071,675],{}," attachment (via ",[475,2074,2075],{},"attachForkToLogger","), and finishing the lifecycle — but you keep the full pipeline (route filtering, sampling, emit, enrich, drain, plugins) for free.",[732,2078,2080],{"id":2079},"non-http-runtimes","Non-HTTP runtimes",[471,2082,2083,2084,605,2086,1952],{},"For queue workers, CLI drivers, cron jobs, or durable execution engines, skip the HTTP-shaped helpers and use ",[475,2085,719],{},[475,2087,481],{},[740,2089,2093],{"className":2090,"code":2091,"language":2092,"meta":746,"style":746},"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",[475,2094,2095,2114,2118,2142,2157,2173,2212,2218,2222,2229,2243,2272,2287,2301,2309,2318,2331,2335],{"__ignoreMap":746},[750,2096,2097,2099,2101,2104,2106,2108,2110,2112],{"class":752,"line":753},[750,2098,1055],{"class":1054},[750,2100,1062],{"class":1061},[750,2102,2103],{"class":1065}," createRequestLogger",[750,2105,1075],{"class":1061},[750,2107,1078],{"class":1054},[750,2109,1081],{"class":1061},[750,2111,481],{"class":759},[750,2113,1087],{"class":1061},[750,2115,2116],{"class":752,"line":1090},[750,2117,1166],{"emptyLinePlaceholder":1165},[750,2119,2120,2123,2125,2128,2130,2133,2135,2138,2140],{"class":752,"line":1098},[750,2121,2122],{"class":1175},"async",[750,2124,1577],{"class":1175},[750,2126,2127],{"class":1212}," processJob",[750,2129,1285],{"class":1061},[750,2131,2132],{"class":1321},"job",[750,2134,1298],{"class":1061},[750,2136,2137],{"class":756}," Job",[750,2139,567],{"class":1061},[750,2141,1095],{"class":1061},[750,2143,2144,2147,2149,2151,2153,2155],{"class":752,"line":1107},[750,2145,2146],{"class":1175},"  const",[750,2148,1498],{"class":1065},[750,2150,1181],{"class":1061},[750,2152,2103],{"class":1212},[750,2154,1285],{"class":1294},[750,2156,1288],{"class":1061},[750,2158,2159,2162,2164,2166,2169,2171],{"class":752,"line":1115},[750,2160,2161],{"class":1294},"    service",[750,2163,1298],{"class":1061},[750,2165,1081],{"class":1061},[750,2167,2168],{"class":759},"jobs",[750,2170,1228],{"class":1061},[750,2172,1104],{"class":1061},[750,2174,2175,2178,2180,2182,2185,2187,2190,2192,2195,2197,2200,2202,2204,2206,2209],{"class":752,"line":1126},[750,2176,2177],{"class":1294},"    context",[750,2179,1298],{"class":1061},[750,2181,1062],{"class":1061},[750,2183,2184],{"class":1294}," jobId",[750,2186,1298],{"class":1061},[750,2188,2189],{"class":1065}," job",[750,2191,1345],{"class":1061},[750,2193,2194],{"class":1065},"id",[750,2196,1069],{"class":1061},[750,2198,2199],{"class":1294}," queue",[750,2201,1298],{"class":1061},[750,2203,2189],{"class":1065},[750,2205,1345],{"class":1061},[750,2207,2208],{"class":1065},"queue",[750,2210,2211],{"class":1061}," },\n",[750,2213,2214,2216],{"class":752,"line":1140},[750,2215,1477],{"class":1061},[750,2217,1236],{"class":1294},[750,2219,2220],{"class":752,"line":1162},[750,2221,1166],{"emptyLinePlaceholder":1165},[750,2223,2224,2227],{"class":752,"line":1169},[750,2225,2226],{"class":1054},"  try",[750,2228,1095],{"class":1061},[750,2230,2231,2234,2237,2239,2241],{"class":752,"line":1187},[750,2232,2233],{"class":1054},"    await",[750,2235,2236],{"class":1212}," runJob",[750,2238,1285],{"class":1294},[750,2240,2132],{"class":1065},[750,2242,1236],{"class":1294},[750,2244,2245,2248,2250,2253,2255,2257,2259,2261,2263,2266,2268,2270],{"class":752,"line":1192},[750,2246,2247],{"class":1065},"    logger",[750,2249,1345],{"class":1061},[750,2251,2252],{"class":1212},"set",[750,2254,1285],{"class":1294},[750,2256,1769],{"class":1061},[750,2258,1772],{"class":1294},[750,2260,1298],{"class":1061},[750,2262,1081],{"class":1061},[750,2264,2265],{"class":759},"success",[750,2267,1228],{"class":1061},[750,2269,1075],{"class":1061},[750,2271,1236],{"class":1294},[750,2273,2274,2276,2278,2280,2283,2285],{"class":752,"line":1219},[750,2275,1477],{"class":1061},[750,2277,1794],{"class":1054},[750,2279,1318],{"class":1294},[750,2281,2282],{"class":1065},"err",[750,2284,1705],{"class":1294},[750,2286,1288],{"class":1061},[750,2288,2289,2291,2293,2295,2297,2299],{"class":752,"line":1233},[750,2290,2247],{"class":1065},[750,2292,1345],{"class":1061},[750,2294,1799],{"class":1212},[750,2296,1285],{"class":1294},[750,2298,2282],{"class":1065},[750,2300,1236],{"class":1294},[750,2302,2303,2306],{"class":752,"line":1239},[750,2304,2305],{"class":1054},"    throw",[750,2307,2308],{"class":1065}," err\n",[750,2310,2311,2313,2316],{"class":752,"line":1244},[750,2312,1477],{"class":1061},[750,2314,2315],{"class":1054}," finally",[750,2317,1095],{"class":1061},[750,2319,2320,2322,2324,2326,2329],{"class":752,"line":1257},[750,2321,2233],{"class":1054},[750,2323,1498],{"class":1065},[750,2325,1345],{"class":1061},[750,2327,2328],{"class":1212},"emit",[750,2330,1718],{"class":1294},[750,2332,2333],{"class":752,"line":1262},[750,2334,1850],{"class":1061},[750,2336,2337],{"class":752,"line":1291},[750,2338,1856],{"class":1061},[471,2340,2341,2342,2345],{},"Same enrichers, same drain hook, same ",[529,2343,2344],{"href":421},"identity headers"," on outbound HTTP drain requests — only the entry point shape changes.",[732,2347,2349],{"id":2348},"reference-implementations","Reference implementations",[471,2351,2352],{},"Study these built-in integrations for framework-specific patterns:",[502,2354,2355,2371],{},[505,2356,2357],{},[508,2358,2359,2362,2365,2368],{},[511,2360,2361],{},"Framework",[511,2363,2364],{},"Lines",[511,2366,2367],{},"Mode",[511,2369,2370],{},"Source",[521,2372,2373,2390,2406,2423,2440,2457],{},[508,2374,2375,2377,2380,2383],{},[526,2376,202],{},[526,2378,2379],{},"~50",[526,2381,2382],{},"manifest",[526,2384,2385],{},[529,2386,2389],{"href":2387,"rel":2388},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Fhono\u002Findex.ts",[730],"hono\u002Findex.ts",[508,2391,2392,2394,2396,2399],{},[526,2393,197],{},[526,2395,2379],{},[526,2397,2398],{},"manifest + ALS",[526,2400,2401],{},[529,2402,2405],{"href":2403,"rel":2404},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Fexpress\u002Findex.ts",[730],"express\u002Findex.ts",[508,2407,2408,2410,2413,2416],{},[526,2409,207],{},[526,2411,2412],{},"~70",[526,2414,2415],{},"manifest + Fastify hooks",[526,2417,2418],{},[529,2419,2422],{"href":2420,"rel":2421},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Ffastify\u002Findex.ts",[730],"fastify\u002Findex.ts",[508,2424,2425,2427,2430,2433],{},[526,2426,212],{},[526,2428,2429],{},"~80",[526,2431,2432],{},"manifest + custom ALS scoping",[526,2434,2435],{},[529,2436,2439],{"href":2437,"rel":2438},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Felysia\u002Findex.ts",[730],"elysia\u002Findex.ts",[508,2441,2442,2444,2447,2450],{},[526,2443,192],{},[526,2445,2446],{},"~120",[526,2448,2449],{},"custom (interceptor)",[526,2451,2452],{},[529,2453,2456],{"href":2454,"rel":2455},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Fnestjs\u002F",[730],"nestjs\u002F",[508,2458,2459,2461,2464,2470],{},[526,2460,177],{},[526,2462,2463],{},"~90",[526,2465,2466,2467,2469],{},"custom (",[475,2468,566],{}," hook)",[526,2471,2472],{},[529,2473,2476],{"href":2474,"rel":2475},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Fsveltekit\u002F",[730],"sveltekit\u002F",[492,2478,2481,2482,2487],{"color":2479,"icon":2480},"neutral","i-lucide-heart","Built an integration for a framework we don't support? ",[529,2483,2486],{"href":2484,"rel":2485},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fpulls",[730],"Open a PR"," — the community will thank you.",[732,2489,2491],{"id":2490},"next-steps","Next steps",[593,2493,2494,2500,2506,2511,2516,2521],{},[596,2495,2496,2499],{},[529,2497,2498],{"href":426},"Custom Drains"," — same toolkit shape for drain destinations",[596,2501,2502,2505],{},[529,2503,2504],{"href":413},"Custom Enrichers"," — same toolkit shape for derived event fields",[596,2507,2508,2510],{},[529,2509,408],{"href":409}," — multi-hook extensions (drain + enrich + keep in one object)",[596,2512,2513,2515],{},[529,2514,46],{"href":47}," — design comprehensive events with context layering",[596,2517,2518,2520],{},[529,2519,61],{"href":62}," — control log volume with head and tail sampling",[596,2522,2523,2525],{},[529,2524,90],{"href":95}," — send logs to Axiom, Sentry, PostHog, and more",[2527,2528,2529],"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 .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":746,"searchDepth":1090,"depth":1090,"links":2531},[2532,2533,2534,2538,2539,2540,2541],{"id":734,"depth":1090,"text":735},{"id":809,"depth":1090,"text":810},{"id":1031,"depth":1090,"text":1032,"children":2535},[2536],{"id":1866,"depth":1098,"text":2537},"What defineFrameworkIntegration does",{"id":1939,"depth":1090,"text":1940},{"id":2079,"depth":1090,"text":2080},{"id":2348,"depth":1090,"text":2349},{"id":2490,"depth":1090,"text":2491},"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",[2545,2547],{"label":2498,"icon":428,"to":426,"color":2479,"variant":2546},"subtle",{"label":2504,"icon":373,"to":413,"color":2479,"variant":2546},{},{"title":394,"icon":397},{"title":466,"description":2542},"DFotRfnyzJSBhAO9Ot5iRW-UTpMFMpF0IyBLqZzA40U",[2553,2555],{"title":389,"path":390,"stem":391,"description":2554,"icon":392,"children":-1},"Subscribe to wide events flowing through evlog — in-process with createStreamDrain, or over the network with the local SSE stream server.",{"title":399,"path":400,"stem":401,"description":2556,"icon":402,"children":-1},"Replay and tail the local NDJSON drain with readFsLogs and tailFsLogs — works in-process or from any external Node tool, survives restarts.",1784203206830]