[{"data":1,"prerenderedAt":1339},["ShallowReactive",2],{"navigation_docs":3,"-build-on-top-plugins":454,"-build-on-top-plugins-surround":1334},[4,35,159,201,289,352,438],{"title":5,"path":6,"stem":7,"children":8,"page":34},"Getting Started","\u002Fgetting-started","1.getting-started",[9,14,19,24,29],{"title":10,"path":11,"stem":12,"icon":13},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-info",{"title":15,"path":16,"stem":17,"icon":18},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":20,"path":21,"stem":22,"icon":23},"Quick Start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-zap",{"title":25,"path":26,"stem":27,"icon":28},"Agent Skills","\u002Fgetting-started\u002Fagent-skills","1.getting-started\u002F4.agent-skills","i-lucide-sparkles",{"title":30,"path":31,"stem":32,"icon":33},"vs Other Loggers","\u002Fgetting-started\u002Fvs-other-loggers","1.getting-started\u002F5.vs-other-loggers","i-lucide-scale",false,{"title":36,"path":37,"stem":38,"children":39,"page":34},"Logging","\u002Flogging","2.logging",[40,45,50,55,60,65,70,99,127],{"title":41,"path":42,"stem":43,"icon":44},"Overview","\u002Flogging\u002Foverview","2.logging\u002F0.overview","i-lucide-list",{"title":46,"path":47,"stem":48,"icon":49},"Simple Logging","\u002Flogging\u002Fsimple-logging","2.logging\u002F1.simple-logging","i-lucide-terminal",{"title":51,"path":52,"stem":53,"icon":54},"Wide Events","\u002Flogging\u002Fwide-events","2.logging\u002F2.wide-events","i-lucide-layers",{"title":56,"path":57,"stem":58,"icon":59},"Structured Errors","\u002Flogging\u002Fstructured-errors","2.logging\u002F3.structured-errors","i-lucide-shield-alert",{"title":61,"path":62,"stem":63,"icon":64},"Catalogs","\u002Flogging\u002Fcatalogs","2.logging\u002F4.catalogs","i-lucide-book-open",{"title":66,"path":67,"stem":68,"icon":69},"Client Logging","\u002Flogging\u002Fclient-logging","2.logging\u002F5.client-logging","i-lucide-monitor",{"title":71,"icon":72,"path":73,"stem":74,"children":75,"page":34},"AI SDK","i-simple-icons-vercel","\u002Flogging\u002Fai-sdk","2.logging\u002F6.ai-sdk",[76,79,84,89,94],{"title":41,"path":77,"stem":78,"icon":44},"\u002Flogging\u002Fai-sdk\u002Foverview","2.logging\u002F6.ai-sdk\u002F01.overview",{"title":80,"path":81,"stem":82,"icon":83},"Usage","\u002Flogging\u002Fai-sdk\u002Fusage","2.logging\u002F6.ai-sdk\u002F02.usage","i-lucide-code",{"title":85,"path":86,"stem":87,"icon":88},"Options","\u002Flogging\u002Fai-sdk\u002Foptions","2.logging\u002F6.ai-sdk\u002F03.options","i-lucide-sliders",{"title":90,"path":91,"stem":92,"icon":93},"Metadata","\u002Flogging\u002Fai-sdk\u002Fmetadata","2.logging\u002F6.ai-sdk\u002F04.metadata","i-lucide-database",{"title":95,"path":96,"stem":97,"icon":98},"Telemetry","\u002Flogging\u002Fai-sdk\u002Ftelemetry","2.logging\u002F6.ai-sdk\u002F05.telemetry","i-lucide-activity",{"title":100,"icon":101,"path":102,"stem":103,"children":104,"page":34},"Better Auth","i-simple-icons-betterauth","\u002Flogging\u002Fbetter-auth","2.logging\u002F7.better-auth",[105,108,113,118,122],{"title":41,"path":106,"stem":107,"icon":44},"\u002Flogging\u002Fbetter-auth\u002Foverview","2.logging\u002F7.better-auth\u002F01.overview",{"title":109,"path":110,"stem":111,"icon":112},"Identify User","\u002Flogging\u002Fbetter-auth\u002Fidentify-user","2.logging\u002F7.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":114,"path":115,"stem":116,"icon":117},"Middleware","\u002Flogging\u002Fbetter-auth\u002Fmiddleware","2.logging\u002F7.better-auth\u002F03.middleware","i-lucide-shield",{"title":119,"path":120,"stem":121,"icon":69},"Client Sync","\u002Flogging\u002Fbetter-auth\u002Fclient-sync","2.logging\u002F7.better-auth\u002F04.client-sync",{"title":123,"path":124,"stem":125,"icon":126},"Performance","\u002Flogging\u002Fbetter-auth\u002Fperformance","2.logging\u002F7.better-auth\u002F05.performance","i-lucide-gauge",{"title":128,"icon":129,"path":130,"stem":131,"children":132,"page":34},"Audit Logs","i-lucide-shield-check","\u002Flogging\u002Faudit","2.logging\u002F8.audit",[133,136,141,146,151,155],{"title":41,"path":134,"stem":135,"icon":44},"\u002Flogging\u002Faudit\u002Foverview","2.logging\u002F8.audit\u002F01.overview",{"title":137,"path":138,"stem":139,"icon":140},"Schema","\u002Flogging\u002Faudit\u002Fschema","2.logging\u002F8.audit\u002F02.schema","i-lucide-file-text",{"title":142,"path":143,"stem":144,"icon":145},"Recording","\u002Flogging\u002Faudit\u002Frecording","2.logging\u002F8.audit\u002F03.recording","i-lucide-pen-line",{"title":147,"path":148,"stem":149,"icon":150},"Drains","\u002Flogging\u002Faudit\u002Fpipeline","2.logging\u002F8.audit\u002F04.pipeline","i-lucide-link",{"title":152,"path":153,"stem":154,"icon":129},"Compliance","\u002Flogging\u002Faudit\u002Fcompliance","2.logging\u002F8.audit\u002F05.compliance",{"title":156,"path":157,"stem":158,"icon":64},"Recipes","\u002Flogging\u002Faudit\u002Frecipes","2.logging\u002F8.audit\u002F06.recipes",{"title":160,"path":161,"stem":162,"children":163,"page":34},"Core Concepts","\u002Fcore-concepts","3.core-concepts",[164,169,174,179,184,188,191,196],{"title":165,"path":166,"stem":167,"icon":168},"Lifecycle","\u002Fcore-concepts\u002Flifecycle","3.core-concepts\u002F0.lifecycle","i-lucide-arrow-right-left",{"title":170,"path":171,"stem":172,"icon":173},"Configuration","\u002Fcore-concepts\u002Fconfiguration","3.core-concepts\u002F1.configuration","i-lucide-settings",{"title":175,"path":176,"stem":177,"icon":178},"Sampling","\u002Fcore-concepts\u002Fsampling","3.core-concepts\u002F2.sampling","i-lucide-filter",{"title":180,"path":181,"stem":182,"icon":183},"Typed Fields","\u002Fcore-concepts\u002Ftyped-fields","3.core-concepts\u002F3.typed-fields","i-simple-icons-typescript",{"title":185,"path":186,"stem":187,"icon":129},"Best Practices","\u002Fcore-concepts\u002Fbest-practices","3.core-concepts\u002F4.best-practices",{"title":123,"path":189,"stem":190,"icon":126},"\u002Fcore-concepts\u002Fperformance","3.core-concepts\u002F5.performance",{"title":192,"path":193,"stem":194,"icon":195},"Vite Plugin","\u002Fcore-concepts\u002Fvite-plugin","3.core-concepts\u002F6.vite-plugin","i-custom-vite",{"title":197,"path":198,"stem":199,"icon":200},"Auto-Redaction","\u002Fcore-concepts\u002Fredaction","3.core-concepts\u002F7.redaction","i-lucide-eye-off",{"title":202,"path":203,"stem":204,"children":205,"page":34},"Frameworks","\u002Fframeworks","4.frameworks",[206,210,215,220,225,230,235,240,245,250,255,260,265,270,274,279,284],{"title":41,"path":207,"stem":208,"icon":209},"\u002Fframeworks\u002Foverview","4.frameworks\u002F00.overview","i-lucide-layout-grid",{"title":211,"path":212,"stem":213,"icon":214},"Nuxt","\u002Fframeworks\u002Fnuxt","4.frameworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":216,"path":217,"stem":218,"icon":219},"Next.js","\u002Fframeworks\u002Fnextjs","4.frameworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":221,"path":222,"stem":223,"icon":224},"SvelteKit","\u002Fframeworks\u002Fsveltekit","4.frameworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":226,"path":227,"stem":228,"icon":229},"Nitro","\u002Fframeworks\u002Fnitro","4.frameworks\u002F04.nitro","i-custom-nitro",{"title":231,"path":232,"stem":233,"icon":234},"TanStack Start","\u002Fframeworks\u002Ftanstack-start","4.frameworks\u002F05.tanstack-start","i-custom-tanstack",{"title":236,"path":237,"stem":238,"icon":239},"NestJS","\u002Fframeworks\u002Fnestjs","4.frameworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":241,"path":242,"stem":243,"icon":244},"Express","\u002Fframeworks\u002Fexpress","4.frameworks\u002F07.express","i-simple-icons-express",{"title":246,"path":247,"stem":248,"icon":249},"Hono","\u002Fframeworks\u002Fhono","4.frameworks\u002F08.hono","i-simple-icons-hono",{"title":251,"path":252,"stem":253,"icon":254},"Fastify","\u002Fframeworks\u002Ffastify","4.frameworks\u002F09.fastify","i-simple-icons-fastify",{"title":256,"path":257,"stem":258,"icon":259},"Elysia","\u002Fframeworks\u002Felysia","4.frameworks\u002F10.elysia","i-custom-elysia",{"title":261,"path":262,"stem":263,"icon":264},"React Router","\u002Fframeworks\u002Freact-router","4.frameworks\u002F11.react-router","i-custom-reactrouter",{"title":266,"path":267,"stem":268,"icon":269},"Cloudflare Workers","\u002Fframeworks\u002Fcloudflare-workers","4.frameworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":271,"path":272,"stem":273,"icon":183},"Standalone","\u002Fframeworks\u002Fstandalone","4.frameworks\u002F13.standalone",{"title":275,"path":276,"stem":277,"icon":278},"Astro","\u002Fframeworks\u002Fastro","4.frameworks\u002F14.astro","i-simple-icons-astro",{"title":280,"path":281,"stem":282,"icon":283},"AWS Lambda","\u002Fframeworks\u002Faws-lambda","4.frameworks\u002F16.aws-lambda","i-custom-lambda",{"title":285,"path":286,"stem":287,"icon":288},"Custom Integration","\u002Fframeworks\u002Fcustom-integration","4.frameworks\u002F17.custom-integration","i-lucide-puzzle",{"title":290,"path":291,"stem":292,"children":293,"page":34},"Build on top","\u002Fbuild-on-top","5.build-on-top",[294,297,302,307,312,316,321,326,330,334,338,342,347],{"title":41,"path":295,"stem":296,"icon":54},"\u002Fbuild-on-top\u002Foverview","5.build-on-top\u002F0.overview",{"title":298,"path":299,"stem":300,"icon":301},"In-process stream","\u002Fbuild-on-top\u002Fin-process-stream","5.build-on-top\u002F1.in-process-stream","i-lucide-radio-tower",{"title":303,"path":304,"stem":305,"icon":306},"Fanout","\u002Fbuild-on-top\u002Ffanout-and-multi-drain","5.build-on-top\u002F10.fanout-and-multi-drain","i-lucide-share-2",{"title":308,"path":309,"stem":310,"icon":311},"Identity headers","\u002Fbuild-on-top\u002Fidentity-headers","5.build-on-top\u002F11.identity-headers","i-lucide-fingerprint",{"title":313,"path":314,"stem":315,"icon":288},"Custom framework","\u002Fbuild-on-top\u002Fcustom-framework","5.build-on-top\u002F12.custom-framework",{"title":317,"path":318,"stem":319,"icon":320},"Stream server","\u002Fbuild-on-top\u002Fstream-server","5.build-on-top\u002F2.stream-server","i-lucide-radio",{"title":322,"path":323,"stem":324,"icon":325},"FS reader","\u002Fbuild-on-top\u002Ffs-reader","5.build-on-top\u002F3.fs-reader","i-lucide-folder-search",{"title":156,"path":327,"stem":328,"icon":329},"\u002Fbuild-on-top\u002Fconsumer-recipes","5.build-on-top\u002F4.consumer-recipes","i-lucide-chef-hat",{"title":331,"path":332,"stem":333,"icon":288},"Plugins","\u002Fbuild-on-top\u002Fplugins","5.build-on-top\u002F5.plugins",{"title":335,"path":336,"stem":337,"icon":28},"Custom enrichers","\u002Fbuild-on-top\u002Fcustom-enrichers","5.build-on-top\u002F6.custom-enrichers",{"title":339,"path":340,"stem":341,"icon":178},"Tail sampling","\u002Fbuild-on-top\u002Ftail-sampling","5.build-on-top\u002F7.tail-sampling",{"title":343,"path":344,"stem":345,"icon":346},"Custom drains","\u002Fbuild-on-top\u002Fcustom-drains","5.build-on-top\u002F8.custom-drains","i-lucide-code-2",{"title":348,"path":349,"stem":350,"icon":351},"Drain pipeline","\u002Fbuild-on-top\u002Fdrain-pipeline","5.build-on-top\u002F9.drain-pipeline","i-lucide-workflow",{"title":353,"path":354,"stem":355,"children":356,"page":34},"Adapters","\u002Fadapters","6.adapters",[357,360,400,415],{"title":41,"path":358,"stem":359,"icon":44},"\u002Fadapters\u002Foverview","6.adapters\u002F01.overview",{"title":361,"path":362,"stem":363,"children":364,"page":34},"Cloud destinations","\u002Fadapters\u002Fcloud","6.adapters\u002F02.cloud",[365,370,375,380,385,390,395],{"title":366,"path":367,"stem":368,"icon":369},"Axiom","\u002Fadapters\u002Fcloud\u002Faxiom","6.adapters\u002F02.cloud\u002F01.axiom","i-custom-axiom",{"title":371,"path":372,"stem":373,"icon":374},"OTLP","\u002Fadapters\u002Fcloud\u002Fotlp","6.adapters\u002F02.cloud\u002F02.otlp","i-simple-icons-opentelemetry",{"title":376,"path":377,"stem":378,"icon":379},"PostHog","\u002Fadapters\u002Fcloud\u002Fposthog","6.adapters\u002F02.cloud\u002F03.posthog","i-simple-icons-posthog",{"title":381,"path":382,"stem":383,"icon":384},"Sentry","\u002Fadapters\u002Fcloud\u002Fsentry","6.adapters\u002F02.cloud\u002F04.sentry","i-simple-icons-sentry",{"title":386,"path":387,"stem":388,"icon":389},"Better Stack","\u002Fadapters\u002Fcloud\u002Fbetter-stack","6.adapters\u002F02.cloud\u002F05.better-stack","i-simple-icons-betterstack",{"title":391,"path":392,"stem":393,"icon":394},"Datadog","\u002Fadapters\u002Fcloud\u002Fdatadog","6.adapters\u002F02.cloud\u002F06.datadog","i-simple-icons-datadog",{"title":396,"path":397,"stem":398,"icon":399},"HyperDX","\u002Fadapters\u002Fcloud\u002Fhyperdx","6.adapters\u002F02.cloud\u002F07.hyperdx","i-custom-hyperdx",{"title":401,"path":402,"stem":403,"children":404,"page":34},"Self-hosted","\u002Fadapters\u002Fself-hosted","6.adapters\u002F03.self-hosted",[405,410],{"title":406,"path":407,"stem":408,"icon":409},"File System","\u002Fadapters\u002Fself-hosted\u002Ffs","6.adapters\u002F03.self-hosted\u002F01.fs","i-lucide-hard-drive",{"title":411,"path":412,"stem":413,"icon":414},"NuxtHub","\u002Fadapters\u002Fself-hosted\u002Fnuxthub","6.adapters\u002F03.self-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":416,"path":417,"stem":418,"children":419,"page":34},"Building blocks","\u002Fadapters\u002Fbuilding-blocks","6.adapters\u002F04.building-blocks",[420,424,429,433],{"title":421,"path":422,"stem":423,"icon":351},"Pipeline","\u002Fadapters\u002Fbuilding-blocks\u002Fpipeline","6.adapters\u002F04.building-blocks\u002F01.pipeline",{"title":425,"path":426,"stem":427,"icon":428},"HTTP","\u002Fadapters\u002Fbuilding-blocks\u002Fhttp","6.adapters\u002F04.building-blocks\u002F02.http","i-lucide-globe",{"title":430,"path":431,"stem":432,"icon":83},"Custom Adapters","\u002Fadapters\u002Fbuilding-blocks\u002Fcustom","6.adapters\u002F04.building-blocks\u002F03.custom",{"title":434,"path":435,"stem":436,"icon":437},"Toolkit","\u002Fadapters\u002Fbuilding-blocks\u002Ftoolkit","6.adapters\u002F04.building-blocks\u002F04.toolkit","i-lucide-blocks",{"title":439,"path":440,"stem":441,"children":442,"page":34},"Enrichers","\u002Fenrichers","7.enrichers",[443,446,450],{"title":41,"path":444,"stem":445,"icon":28},"\u002Fenrichers\u002Foverview","7.enrichers\u002F1.overview",{"title":447,"path":448,"stem":449,"icon":288},"Built-in","\u002Fenrichers\u002Fbuilt-in","7.enrichers\u002F2.built-in",{"title":451,"path":452,"stem":453,"icon":83},"Custom","\u002Fenrichers\u002Fcustom","7.enrichers\u002F3.custom",{"id":455,"title":331,"body":456,"description":1327,"extension":1328,"links":1329,"meta":1330,"navigation":1331,"path":332,"seo":1332,"stem":333,"__hash__":1333},"docs\u002F5.build-on-top\u002F5.plugins.md",{"type":457,"value":458,"toc":1320},"minimark",[459,472,477,484,508,519,523,816,820,968,975,1231,1235,1295,1299,1316],[460,461,462,466,467,471],"p",{},[463,464,465],"code",{},"definePlugin()"," is the ",[468,469,470],"strong",{},"canonical extension point"," for evlog. Drains and enrichers are special cases of plugins, but a single plugin can opt into multiple hooks at once — the right shape for any non-trivial extension that mixes several concerns.",[473,474,476],"h2",{"id":475},"what-is-this-and-when-do-i-want-it","What is this and when do I want it?",[460,478,479,480,483],{},"Use a plugin when your feature touches ",[468,481,482],{},"more than one"," point in the pipeline:",[485,486,487,495,498],"ul",{},[488,489,490,491,494],"li",{},"\"On every request, copy ",[463,492,493],{},"x-tenant-id"," from headers into a context field, AND tag the event with the tenant's plan, AND alert when an error event has plan=enterprise\" → one plugin",[488,496,497],{},"\"Add Sentry breadcrumbs every time we drain a wide event with level=error\" → one plugin",[488,499,500,501,504,505],{},"\"Decorate the request logger with a custom ",[463,502,503],{},"audit.refund(...)"," method\" → one plugin's ",[463,506,507],{},"extendLogger",[460,509,510,511,514,515,518],{},"Single-purpose extensions (just an enricher, just a drain) can use the dedicated wrappers ",[463,512,513],{},"enricherPlugin()"," \u002F ",[463,516,517],{},"drainPlugin()"," instead.",[473,520,522],{"id":521},"minimal-example","Minimal example",[524,525,530],"pre",{"className":526,"code":527,"language":528,"meta":529,"style":529},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { definePlugin, getGlobalPluginRunner } from 'evlog\u002Ftoolkit'\n\nexport const tenantPlugin = definePlugin({\n  name: 'tenant',\n  onRequestStart({ logger, headers }) {\n    const tenantId = headers?.['x-tenant-id']\n    if (tenantId) logger.set({ tenant: { id: tenantId } })\n  },\n  enrich({ event }) {\n    event.region = process.env.REGION\n  },\n})\n\n\u002F\u002F Register on the global runner (typically once at startup):\ngetGlobalPluginRunner().add(tenantPlugin)\n","ts","",[463,531,532,571,578,603,624,648,677,727,733,748,774,779,787,792,799],{"__ignoreMap":529},[533,534,537,541,545,549,552,555,558,561,564,568],"span",{"class":535,"line":536},"line",1,[533,538,540],{"class":539},"s7zQu","import",[533,542,544],{"class":543},"sMK4o"," {",[533,546,548],{"class":547},"sTEyZ"," definePlugin",[533,550,551],{"class":543},",",[533,553,554],{"class":547}," getGlobalPluginRunner",[533,556,557],{"class":543}," }",[533,559,560],{"class":539}," from",[533,562,563],{"class":543}," '",[533,565,567],{"class":566},"sfazB","evlog\u002Ftoolkit",[533,569,570],{"class":543},"'\n",[533,572,574],{"class":535,"line":573},2,[533,575,577],{"emptyLinePlaceholder":576},true,"\n",[533,579,581,584,588,591,594,597,600],{"class":535,"line":580},3,[533,582,583],{"class":539},"export",[533,585,587],{"class":586},"spNyl"," const",[533,589,590],{"class":547}," tenantPlugin ",[533,592,593],{"class":543},"=",[533,595,548],{"class":596},"s2Zo4",[533,598,599],{"class":547},"(",[533,601,602],{"class":543},"{\n",[533,604,606,610,613,615,618,621],{"class":535,"line":605},4,[533,607,609],{"class":608},"swJcz","  name",[533,611,612],{"class":543},":",[533,614,563],{"class":543},[533,616,617],{"class":566},"tenant",[533,619,620],{"class":543},"'",[533,622,623],{"class":543},",\n",[533,625,627,630,633,637,639,642,645],{"class":535,"line":626},5,[533,628,629],{"class":608},"  onRequestStart",[533,631,632],{"class":543},"({",[533,634,636],{"class":635},"sHdIc"," logger",[533,638,551],{"class":543},[533,640,641],{"class":635}," headers",[533,643,644],{"class":543}," })",[533,646,647],{"class":543}," {\n",[533,649,651,654,657,660,662,665,668,670,672,674],{"class":535,"line":650},6,[533,652,653],{"class":586},"    const",[533,655,656],{"class":547}," tenantId",[533,658,659],{"class":543}," =",[533,661,641],{"class":547},[533,663,664],{"class":543},"?.",[533,666,667],{"class":608},"[",[533,669,620],{"class":543},[533,671,493],{"class":566},[533,673,620],{"class":543},[533,675,676],{"class":608},"]\n",[533,678,680,683,686,689,692,695,698,701,703,706,709,711,713,716,718,720,722,724],{"class":535,"line":679},7,[533,681,682],{"class":539},"    if",[533,684,685],{"class":608}," (",[533,687,688],{"class":547},"tenantId",[533,690,691],{"class":608},") ",[533,693,694],{"class":547},"logger",[533,696,697],{"class":543},".",[533,699,700],{"class":596},"set",[533,702,599],{"class":608},[533,704,705],{"class":543},"{",[533,707,708],{"class":608}," tenant",[533,710,612],{"class":543},[533,712,544],{"class":543},[533,714,715],{"class":608}," id",[533,717,612],{"class":543},[533,719,656],{"class":547},[533,721,557],{"class":543},[533,723,557],{"class":543},[533,725,726],{"class":608},")\n",[533,728,730],{"class":535,"line":729},8,[533,731,732],{"class":543},"  },\n",[533,734,736,739,741,744,746],{"class":535,"line":735},9,[533,737,738],{"class":608},"  enrich",[533,740,632],{"class":543},[533,742,743],{"class":635}," event",[533,745,644],{"class":543},[533,747,647],{"class":543},[533,749,751,754,756,759,761,764,766,769,771],{"class":535,"line":750},10,[533,752,753],{"class":547},"    event",[533,755,697],{"class":543},[533,757,758],{"class":547},"region",[533,760,659],{"class":543},[533,762,763],{"class":547}," process",[533,765,697],{"class":543},[533,767,768],{"class":547},"env",[533,770,697],{"class":543},[533,772,773],{"class":547},"REGION\n",[533,775,777],{"class":535,"line":776},11,[533,778,732],{"class":543},[533,780,782,785],{"class":535,"line":781},12,[533,783,784],{"class":543},"}",[533,786,726],{"class":547},[533,788,790],{"class":535,"line":789},13,[533,791,577],{"emptyLinePlaceholder":576},[533,793,795],{"class":535,"line":794},14,[533,796,798],{"class":797},"sHwdD","\u002F\u002F Register on the global runner (typically once at startup):\n",[533,800,802,805,808,810,813],{"class":535,"line":801},15,[533,803,804],{"class":596},"getGlobalPluginRunner",[533,806,807],{"class":547},"()",[533,809,697],{"class":543},[533,811,812],{"class":596},"add",[533,814,815],{"class":547},"(tenantPlugin)\n",[473,817,819],{"id":818},"full-api","Full API",[821,822,823,839],"table",{},[824,825,826],"thead",{},[827,828,829,833,836],"tr",{},[830,831,832],"th",{},"Hook",[830,834,835],{},"When",[830,837,838],{},"Use it for",[840,841,842,859,874,887,908,921,938,951],"tbody",{},[827,843,844,850,853],{},[845,846,847],"td",{},[463,848,849],{},"setup(ctx)",[845,851,852],{},"Once when registered",[845,854,855,856,858],{},"Read ",[463,857,768],{},", set up shared state",[827,860,861,866,869],{},[845,862,863],{},[463,864,865],{},"onRequestStart(ctx)",[845,867,868],{},"Each request, before any handler runs",[845,870,871,872],{},"Pull values from headers into ",[463,873,694],{},[827,875,876,881,884],{},[845,877,878],{},[463,879,880],{},"enrich(ctx)",[845,882,883],{},"Every event, before drain",[845,885,886],{},"Add derived fields (geo, deploy id…)",[827,888,889,894,897],{},[845,890,891],{},[463,892,893],{},"keep(ctx)",[845,895,896],{},"Tail sampling decision",[845,898,899,900,903,904,907],{},"Force-keep based on outcome (",[463,901,902],{},"status >= 400",", ",[463,905,906],{},"duration > 500",", …)",[827,909,910,915,918],{},[845,911,912],{},[463,913,914],{},"drain(ctx)",[845,916,917],{},"Every emitted event",[845,919,920],{},"Side-effect: alert, mirror to a queue, etc.",[827,922,923,928,935],{},[845,924,925],{},[463,926,927],{},"onRequestFinish(ctx)",[845,929,930,931,934],{},"After response, includes the emitted event (or ",[463,932,933],{},"null"," if sampled out)",[845,936,937],{},"Per-request post-processing",[827,939,940,945,948],{},[845,941,942],{},[463,943,944],{},"onClientLog(ctx)",[845,946,947],{},"Browser-submitted event hits the ingest endpoint",[845,949,950],{},"Observe \u002F reject client traffic",[827,952,953,958,961],{},[845,954,955],{},[463,956,957],{},"extendLogger(logger)",[845,959,960],{},"Each request",[845,962,963,964,967],{},"Add custom methods (e.g. ",[463,965,966],{},"logger.audit.refund()",")",[460,969,970,971,974],{},"Every hook is ",[468,972,973],{},"optional",". A plugin can implement any subset.",[524,976,978],{"className":526,"code":977,"language":528,"meta":529,"style":529},"export interface EvlogPlugin {\n  name: string\n  setup?: (ctx: PluginSetupContext) => void | Promise\u003Cvoid>\n  enrich?: (ctx: EnrichContext) => void | Promise\u003Cvoid>\n  drain?: (ctx: DrainContext) => void | Promise\u003Cvoid>\n  keep?: (ctx: TailSamplingContext) => void | Promise\u003Cvoid>\n  onRequestStart?: (ctx: RequestLifecycleContext) => void\n  onRequestFinish?: (ctx: RequestFinishContext) => void\n  onClientLog?: (ctx: ClientLogContext) => void\n  extendLogger?: (logger: RequestLogger) => void\n}\n",[463,979,980,993,1002,1043,1074,1106,1138,1160,1182,1204,1226],{"__ignoreMap":529},[533,981,982,984,987,991],{"class":535,"line":536},[533,983,583],{"class":539},[533,985,986],{"class":586}," interface",[533,988,990],{"class":989},"sBMFI"," EvlogPlugin",[533,992,647],{"class":543},[533,994,995,997,999],{"class":535,"line":573},[533,996,609],{"class":608},[533,998,612],{"class":543},[533,1000,1001],{"class":989}," string\n",[533,1003,1004,1007,1010,1012,1015,1017,1020,1022,1025,1028,1031,1034,1037,1040],{"class":535,"line":580},[533,1005,1006],{"class":608},"  setup",[533,1008,1009],{"class":543},"?:",[533,1011,685],{"class":543},[533,1013,1014],{"class":635},"ctx",[533,1016,612],{"class":543},[533,1018,1019],{"class":989}," PluginSetupContext",[533,1021,967],{"class":543},[533,1023,1024],{"class":586}," =>",[533,1026,1027],{"class":989}," void",[533,1029,1030],{"class":543}," |",[533,1032,1033],{"class":989}," Promise",[533,1035,1036],{"class":543},"\u003C",[533,1038,1039],{"class":989},"void",[533,1041,1042],{"class":543},">\n",[533,1044,1045,1047,1049,1051,1053,1055,1058,1060,1062,1064,1066,1068,1070,1072],{"class":535,"line":605},[533,1046,738],{"class":608},[533,1048,1009],{"class":543},[533,1050,685],{"class":543},[533,1052,1014],{"class":635},[533,1054,612],{"class":543},[533,1056,1057],{"class":989}," EnrichContext",[533,1059,967],{"class":543},[533,1061,1024],{"class":586},[533,1063,1027],{"class":989},[533,1065,1030],{"class":543},[533,1067,1033],{"class":989},[533,1069,1036],{"class":543},[533,1071,1039],{"class":989},[533,1073,1042],{"class":543},[533,1075,1076,1079,1081,1083,1085,1087,1090,1092,1094,1096,1098,1100,1102,1104],{"class":535,"line":626},[533,1077,1078],{"class":608},"  drain",[533,1080,1009],{"class":543},[533,1082,685],{"class":543},[533,1084,1014],{"class":635},[533,1086,612],{"class":543},[533,1088,1089],{"class":989}," DrainContext",[533,1091,967],{"class":543},[533,1093,1024],{"class":586},[533,1095,1027],{"class":989},[533,1097,1030],{"class":543},[533,1099,1033],{"class":989},[533,1101,1036],{"class":543},[533,1103,1039],{"class":989},[533,1105,1042],{"class":543},[533,1107,1108,1111,1113,1115,1117,1119,1122,1124,1126,1128,1130,1132,1134,1136],{"class":535,"line":650},[533,1109,1110],{"class":608},"  keep",[533,1112,1009],{"class":543},[533,1114,685],{"class":543},[533,1116,1014],{"class":635},[533,1118,612],{"class":543},[533,1120,1121],{"class":989}," TailSamplingContext",[533,1123,967],{"class":543},[533,1125,1024],{"class":586},[533,1127,1027],{"class":989},[533,1129,1030],{"class":543},[533,1131,1033],{"class":989},[533,1133,1036],{"class":543},[533,1135,1039],{"class":989},[533,1137,1042],{"class":543},[533,1139,1140,1142,1144,1146,1148,1150,1153,1155,1157],{"class":535,"line":679},[533,1141,629],{"class":608},[533,1143,1009],{"class":543},[533,1145,685],{"class":543},[533,1147,1014],{"class":635},[533,1149,612],{"class":543},[533,1151,1152],{"class":989}," RequestLifecycleContext",[533,1154,967],{"class":543},[533,1156,1024],{"class":586},[533,1158,1159],{"class":989}," void\n",[533,1161,1162,1165,1167,1169,1171,1173,1176,1178,1180],{"class":535,"line":729},[533,1163,1164],{"class":608},"  onRequestFinish",[533,1166,1009],{"class":543},[533,1168,685],{"class":543},[533,1170,1014],{"class":635},[533,1172,612],{"class":543},[533,1174,1175],{"class":989}," RequestFinishContext",[533,1177,967],{"class":543},[533,1179,1024],{"class":586},[533,1181,1159],{"class":989},[533,1183,1184,1187,1189,1191,1193,1195,1198,1200,1202],{"class":535,"line":735},[533,1185,1186],{"class":608},"  onClientLog",[533,1188,1009],{"class":543},[533,1190,685],{"class":543},[533,1192,1014],{"class":635},[533,1194,612],{"class":543},[533,1196,1197],{"class":989}," ClientLogContext",[533,1199,967],{"class":543},[533,1201,1024],{"class":586},[533,1203,1159],{"class":989},[533,1205,1206,1209,1211,1213,1215,1217,1220,1222,1224],{"class":535,"line":750},[533,1207,1208],{"class":608},"  extendLogger",[533,1210,1009],{"class":543},[533,1212,685],{"class":543},[533,1214,694],{"class":635},[533,1216,612],{"class":543},[533,1218,1219],{"class":989}," RequestLogger",[533,1221,967],{"class":543},[533,1223,1024],{"class":586},[533,1225,1159],{"class":989},[533,1227,1228],{"class":535,"line":776},[533,1229,1230],{"class":543},"}\n",[473,1232,1234],{"id":1233},"common-pitfalls","Common pitfalls",[485,1236,1237,1247,1259,1283],{},[488,1238,1239,1242,1243,1246],{},[468,1240,1241],{},"Don't throw from a hook",". The plugin runner catches and logs errors with the plugin name, but a thrown error from ",[463,1244,1245],{},"enrich"," won't propagate the event downstream. Keep hooks defensive.",[488,1248,1249,1255,1256,518],{},[468,1250,1251,1254],{},[463,1252,1253],{},"drain"," runs for every event"," — not just per-request. If you only care about per-request lifecycle, use ",[463,1257,1258],{},"onRequestFinish",[488,1260,1261,1266,1267,1270,1271,1274,1275,1278,1279,697],{},[468,1262,1263,1265],{},[463,1264,507],{}," mutates the logger object"," — augment ",[463,1268,1269],{},"RequestLogger"," in a ",[463,1272,1273],{},".d.ts"," so ",[463,1276,1277],{},"useLogger(event)"," exposes the new methods to TypeScript. See ",[1280,1281,1282],"a",{"href":181},"typed fields",[488,1284,1285,1291,1292,1294],{},[468,1286,1287,1288],{},"Plugins are de-duplicated by ",[463,1289,1290],{},"name",". Re-registering with the same ",[463,1293,1290],{}," replaces the previous version (last registration wins).",[473,1296,1298],{"id":1297},"going-further","Going further",[485,1300,1301,1306,1311],{},[488,1302,1303,1304],{},"Single-purpose enricher → ",[1280,1305,335],{"href":336},[488,1307,1308,1309],{},"Tail-only logic → ",[1280,1310,339],{"href":340},[488,1312,1313,1314],{},"Drain-only side effect → ",[1280,1315,343],{"href":344},[1317,1318,1319],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .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}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 .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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":529,"searchDepth":573,"depth":573,"links":1321},[1322,1323,1324,1325,1326],{"id":475,"depth":573,"text":476},{"id":521,"depth":573,"text":522},{"id":818,"depth":573,"text":819},{"id":1233,"depth":573,"text":1234},{"id":1297,"depth":573,"text":1298},"definePlugin is the canonical extension contract for evlog. One plugin can opt into any subset of lifecycle hooks — enrich, drain, tail sampling, request lifecycle, client log observation.","md",null,{},{"title":331,"icon":288},{"title":331,"description":1327},"HX-RONlg6l4deEmrgHBDtc0vvcaAPTZ2pFHx-CS9ggI",[1335,1337],{"title":156,"path":327,"stem":328,"description":1336,"icon":329,"children":-1},"Concrete copy-paste recipes — build your own minimal devtool, pipe to curl + jq, replay history then go live, and aggregate on the consumer side.",{"title":335,"path":336,"stem":337,"description":1338,"icon":28,"children":-1},"defineEnricher derives context from request headers, env, or anything else, and adds it to every wide event before drain — without touching call sites.",1778340169124]