[{"data":1,"prerenderedAt":2225},["ShallowReactive",2],{"navigation_docs":3,"-build-on-top-pipeline-extension":427,"-build-on-top-pipeline-extension-surround":2220},[4,35,159,201,289,324,411],{"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,311,315,320],{"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},"Stream","\u002Fbuild-on-top\u002Fstream","5.build-on-top\u002F1.stream","i-lucide-radio-tower",{"title":303,"path":304,"stem":305,"icon":306},"FS reader","\u002Fbuild-on-top\u002Ffs-reader","5.build-on-top\u002F2.fs-reader","i-lucide-folder-search",{"title":156,"path":308,"stem":309,"icon":310},"\u002Fbuild-on-top\u002Fconsumer-recipes","5.build-on-top\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":312,"path":313,"stem":314,"icon":288},"Pipeline extension","\u002Fbuild-on-top\u002Fpipeline-extension","5.build-on-top\u002F4.pipeline-extension",{"title":316,"path":317,"stem":318,"icon":319},"Sinks","\u002Fbuild-on-top\u002Fsinks","5.build-on-top\u002F5.sinks","i-lucide-share-2",{"title":321,"path":322,"stem":323,"icon":288},"Framework integration","\u002Fbuild-on-top\u002Fframework-integration","5.build-on-top\u002F6.framework-integration",{"title":325,"path":326,"stem":327,"children":328,"page":34},"Adapters","\u002Fadapters","6.adapters",[329,332,372,387],{"title":41,"path":330,"stem":331,"icon":44},"\u002Fadapters\u002Foverview","6.adapters\u002F01.overview",{"title":333,"path":334,"stem":335,"children":336,"page":34},"Cloud destinations","\u002Fadapters\u002Fcloud","6.adapters\u002F02.cloud",[337,342,347,352,357,362,367],{"title":338,"path":339,"stem":340,"icon":341},"Axiom","\u002Fadapters\u002Fcloud\u002Faxiom","6.adapters\u002F02.cloud\u002F01.axiom","i-custom-axiom",{"title":343,"path":344,"stem":345,"icon":346},"OTLP","\u002Fadapters\u002Fcloud\u002Fotlp","6.adapters\u002F02.cloud\u002F02.otlp","i-simple-icons-opentelemetry",{"title":348,"path":349,"stem":350,"icon":351},"PostHog","\u002Fadapters\u002Fcloud\u002Fposthog","6.adapters\u002F02.cloud\u002F03.posthog","i-simple-icons-posthog",{"title":353,"path":354,"stem":355,"icon":356},"Sentry","\u002Fadapters\u002Fcloud\u002Fsentry","6.adapters\u002F02.cloud\u002F04.sentry","i-simple-icons-sentry",{"title":358,"path":359,"stem":360,"icon":361},"Better Stack","\u002Fadapters\u002Fcloud\u002Fbetter-stack","6.adapters\u002F02.cloud\u002F05.better-stack","i-simple-icons-betterstack",{"title":363,"path":364,"stem":365,"icon":366},"Datadog","\u002Fadapters\u002Fcloud\u002Fdatadog","6.adapters\u002F02.cloud\u002F06.datadog","i-simple-icons-datadog",{"title":368,"path":369,"stem":370,"icon":371},"HyperDX","\u002Fadapters\u002Fcloud\u002Fhyperdx","6.adapters\u002F02.cloud\u002F07.hyperdx","i-custom-hyperdx",{"title":373,"path":374,"stem":375,"children":376,"page":34},"Self-hosted","\u002Fadapters\u002Fself-hosted","6.adapters\u002F03.self-hosted",[377,382],{"title":378,"path":379,"stem":380,"icon":381},"File System","\u002Fadapters\u002Fself-hosted\u002Ffs","6.adapters\u002F03.self-hosted\u002F01.fs","i-lucide-hard-drive",{"title":383,"path":384,"stem":385,"icon":386},"NuxtHub","\u002Fadapters\u002Fself-hosted\u002Fnuxthub","6.adapters\u002F03.self-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":388,"path":389,"stem":390,"children":391,"page":34},"Building blocks","\u002Fadapters\u002Fbuilding-blocks","6.adapters\u002F04.building-blocks",[392,397,402,406],{"title":393,"path":394,"stem":395,"icon":396},"Pipeline","\u002Fadapters\u002Fbuilding-blocks\u002Fpipeline","6.adapters\u002F04.building-blocks\u002F01.pipeline","i-lucide-workflow",{"title":398,"path":399,"stem":400,"icon":401},"HTTP","\u002Fadapters\u002Fbuilding-blocks\u002Fhttp","6.adapters\u002F04.building-blocks\u002F02.http","i-lucide-globe",{"title":403,"path":404,"stem":405,"icon":83},"Custom Adapters","\u002Fadapters\u002Fbuilding-blocks\u002Fcustom","6.adapters\u002F04.building-blocks\u002F03.custom",{"title":407,"path":408,"stem":409,"icon":410},"Toolkit","\u002Fadapters\u002Fbuilding-blocks\u002Ftoolkit","6.adapters\u002F04.building-blocks\u002F04.toolkit","i-lucide-blocks",{"title":412,"path":413,"stem":414,"children":415,"page":34},"Enrichers","\u002Fenrichers","7.enrichers",[416,419,423],{"title":41,"path":417,"stem":418,"icon":28},"\u002Fenrichers\u002Foverview","7.enrichers\u002F1.overview",{"title":420,"path":421,"stem":422,"icon":288},"Built-in","\u002Fenrichers\u002Fbuilt-in","7.enrichers\u002F2.built-in",{"title":424,"path":425,"stem":426,"icon":83},"Custom","\u002Fenrichers\u002Fcustom","7.enrichers\u002F3.custom",{"id":428,"title":312,"body":429,"description":2213,"extension":2214,"links":2215,"meta":2216,"navigation":2217,"path":313,"seo":2218,"stem":314,"__hash__":2219},"docs\u002F5.build-on-top\u002F4.pipeline-extension.md",{"type":430,"value":431,"toc":2195},"minimark",[432,441,506,510,513,524,609,614,873,876,1108,1111,1247,1261,1265,1323,1326,1329,1336,1430,1439,1443,1450,1453,1456,1466,1520,1531,1535,1541,1563,1685,1688,1823,1826,1829,1887,1900,1904,1915,1919,1924,1987,1991,2000,2178,2191],[433,434,435,436,440],"p",{},"evlog runs a pipeline on every request : ",[437,438,439],"strong",{},"request lifecycle → enrich → tail sample → drain",". This page covers every way you can hook into it.",[442,443,444,457],"table",{},[445,446,447],"thead",{},[448,449,450,454],"tr",{},[451,452,453],"th",{},"You want to…",[451,455,456],{},"Use",[458,459,460,473,484,495],"tbody",{},[448,461,462,466],{},[463,464,465],"td",{},"React to lifecycle events from a single cohesive object",[463,467,468],{},[469,470,472],"a",{"href":471},"#plugins","Plugins",[448,474,475,478],{},[463,476,477],{},"Add a derived field on every event automatically",[463,479,480],{},[469,481,483],{"href":482},"#custom-enrichers","Custom enrichers",[448,485,486,489],{},[463,487,488],{},"Decide post-hoc whether to keep an event",[463,490,491],{},[469,492,494],{"href":493},"#tail-sampling","Tail sampling",[448,496,497,500],{},[463,498,499],{},"Identify your evlog traffic on the receiver side",[463,501,502],{},[469,503,505],{"href":504},"#identity-headers","Identity headers",[507,508,472],"h2",{"id":509},"plugins",[511,512],"lifecycle-flow",{},[433,514,515,519,520,523],{},[516,517,518],"code",{},"definePlugin()"," is the ",[437,521,522],{},"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.",[525,526,529,532,601],"prompt",{":actions":527,"description":528,"icon":288},"[\"copy\",\"cursor\",\"windsurf\"]","Build a multi-hook evlog plugin",[433,530,531],{},"Build an evlog plugin that hooks into more than one lifecycle stage.",[533,534,535,567,570,573,587],"ul",{},[536,537,538,539,542,543,546,547,550,551,550,554,550,557,550,560,550,563,566],"li",{},"Import ",[516,540,541],{},"definePlugin"," from ",[516,544,545],{},"evlog"," and pick the hooks I need (",[516,548,549],{},"onRequestStart",", ",[516,552,553],{},"enrich",[516,555,556],{},"drain",[516,558,559],{},"extendLogger",[516,561,562],{},"keep",[516,564,565],{},"onClientLog",")",[536,568,569],{},"Keep enrich pure (no I\u002FO, no throwing — use try\u002Fcatch internally)",[536,571,572],{},"For drains, batch and ship to the destination; respect backpressure if the sink is slow",[536,574,575,576,579,580,583,584,566],{},"Register the plugin via the framework config: Next\u002Fstandalone ",[516,577,578],{},"initLogger({ plugins: [myPlugin] })",", Hono\u002FExpress\u002FFastify\u002FElysia middleware option ",[516,581,582],{},"{ plugins: [myPlugin] }",". For Nitro, register the individual hooks directly (",[516,585,586],{},"nitroApp.hooks.hook('evlog:enrich' | 'evlog:drain' | …)",[536,588,589,590,593,594,597,598,600],{},"Prefer single-purpose ",[516,591,592],{},"enricherPlugin()"," \u002F ",[516,595,596],{},"drainPlugin()"," wrappers for simple extensions; use ",[516,599,541],{}," only when several hooks are needed",[433,602,603,604],{},"Docs: ",[469,605,606],{"href":606,"rel":607},"https:\u002F\u002Fwww.evlog.dev\u002Fbuild-on-top\u002Fpipeline-extension",[608],"nofollow",[610,611,613],"h3",{"id":612},"minimal-example","Minimal example",[615,616,621],"pre",{"className":617,"code":618,"language":619,"meta":620,"style":620},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { definePlugin } from 'evlog'\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","ts","",[516,622,623,655,662,687,708,733,763,813,819,834,860,865],{"__ignoreMap":620},[624,625,628,632,636,640,643,646,649,652],"span",{"class":626,"line":627},"line",1,[624,629,631],{"class":630},"s7zQu","import",[624,633,635],{"class":634},"sMK4o"," {",[624,637,639],{"class":638},"sTEyZ"," definePlugin",[624,641,642],{"class":634}," }",[624,644,645],{"class":630}," from",[624,647,648],{"class":634}," '",[624,650,545],{"class":651},"sfazB",[624,653,654],{"class":634},"'\n",[624,656,658],{"class":626,"line":657},2,[624,659,661],{"emptyLinePlaceholder":660},true,"\n",[624,663,665,668,672,675,678,681,684],{"class":626,"line":664},3,[624,666,667],{"class":630},"export",[624,669,671],{"class":670},"spNyl"," const",[624,673,674],{"class":638}," tenantPlugin ",[624,676,677],{"class":634},"=",[624,679,639],{"class":680},"s2Zo4",[624,682,683],{"class":638},"(",[624,685,686],{"class":634},"{\n",[624,688,690,694,697,699,702,705],{"class":626,"line":689},4,[624,691,693],{"class":692},"swJcz","  name",[624,695,696],{"class":634},":",[624,698,648],{"class":634},[624,700,701],{"class":651},"tenant",[624,703,704],{"class":634},"'",[624,706,707],{"class":634},",\n",[624,709,711,714,717,721,724,727,730],{"class":626,"line":710},5,[624,712,713],{"class":692},"  onRequestStart",[624,715,716],{"class":634},"({",[624,718,720],{"class":719},"sHdIc"," logger",[624,722,723],{"class":634},",",[624,725,726],{"class":719}," headers",[624,728,729],{"class":634}," })",[624,731,732],{"class":634}," {\n",[624,734,736,739,742,745,747,750,753,755,758,760],{"class":626,"line":735},6,[624,737,738],{"class":670},"    const",[624,740,741],{"class":638}," tenantId",[624,743,744],{"class":634}," =",[624,746,726],{"class":638},[624,748,749],{"class":634},"?.",[624,751,752],{"class":692},"[",[624,754,704],{"class":634},[624,756,757],{"class":651},"x-tenant-id",[624,759,704],{"class":634},[624,761,762],{"class":692},"]\n",[624,764,766,769,772,775,778,781,784,787,789,792,795,797,799,802,804,806,808,810],{"class":626,"line":765},7,[624,767,768],{"class":630},"    if",[624,770,771],{"class":692}," (",[624,773,774],{"class":638},"tenantId",[624,776,777],{"class":692},") ",[624,779,780],{"class":638},"logger",[624,782,783],{"class":634},".",[624,785,786],{"class":680},"set",[624,788,683],{"class":692},[624,790,791],{"class":634},"{",[624,793,794],{"class":692}," tenant",[624,796,696],{"class":634},[624,798,635],{"class":634},[624,800,801],{"class":692}," id",[624,803,696],{"class":634},[624,805,741],{"class":638},[624,807,642],{"class":634},[624,809,642],{"class":634},[624,811,812],{"class":692},")\n",[624,814,816],{"class":626,"line":815},8,[624,817,818],{"class":634},"  },\n",[624,820,822,825,827,830,832],{"class":626,"line":821},9,[624,823,824],{"class":692},"  enrich",[624,826,716],{"class":634},[624,828,829],{"class":719}," event",[624,831,729],{"class":634},[624,833,732],{"class":634},[624,835,837,840,842,845,847,850,852,855,857],{"class":626,"line":836},10,[624,838,839],{"class":638},"    event",[624,841,783],{"class":634},[624,843,844],{"class":638},"region",[624,846,744],{"class":634},[624,848,849],{"class":638}," process",[624,851,783],{"class":634},[624,853,854],{"class":638},"env",[624,856,783],{"class":634},[624,858,859],{"class":638},"REGION\n",[624,861,863],{"class":626,"line":862},11,[624,864,818],{"class":634},[624,866,868,871],{"class":626,"line":867},12,[624,869,870],{"class":634},"}",[624,872,812],{"class":638},[433,874,875],{},"Register the plugin where you bootstrap evlog. The shape depends on your runtime:",[877,878,879,949,1027],"code-group",{},[615,880,883],{"className":617,"code":881,"filename":882,"language":619,"meta":620,"style":620},"import { initLogger } from 'evlog'\nimport { tenantPlugin } from '.\u002Fplugins\u002Ftenant'\n\ninitLogger({ plugins: [tenantPlugin] })\n","Next.js \u002F standalone",[516,884,885,904,924,928],{"__ignoreMap":620},[624,886,887,889,891,894,896,898,900,902],{"class":626,"line":627},[624,888,631],{"class":630},[624,890,635],{"class":634},[624,892,893],{"class":638}," initLogger",[624,895,642],{"class":634},[624,897,645],{"class":630},[624,899,648],{"class":634},[624,901,545],{"class":651},[624,903,654],{"class":634},[624,905,906,908,910,913,915,917,919,922],{"class":626,"line":657},[624,907,631],{"class":630},[624,909,635],{"class":634},[624,911,912],{"class":638}," tenantPlugin",[624,914,642],{"class":634},[624,916,645],{"class":630},[624,918,648],{"class":634},[624,920,921],{"class":651},".\u002Fplugins\u002Ftenant",[624,923,654],{"class":634},[624,925,926],{"class":626,"line":664},[624,927,661],{"emptyLinePlaceholder":660},[624,929,930,933,935,937,940,942,945,947],{"class":626,"line":689},[624,931,932],{"class":680},"initLogger",[624,934,683],{"class":638},[624,936,791],{"class":634},[624,938,939],{"class":692}," plugins",[624,941,696],{"class":634},[624,943,944],{"class":638}," [tenantPlugin] ",[624,946,870],{"class":634},[624,948,812],{"class":638},[615,950,953],{"className":617,"code":951,"filename":952,"language":619,"meta":620,"style":620},"import { evlogMiddleware } from 'evlog\u002F\u003Cframework>'\nimport { tenantPlugin } from '.\u002Fplugins\u002Ftenant'\n\napp.use(evlogMiddleware({ plugins: [tenantPlugin] }))\n","Hono \u002F Express \u002F Fastify \u002F Elysia",[516,954,955,975,993,997],{"__ignoreMap":620},[624,956,957,959,961,964,966,968,970,973],{"class":626,"line":627},[624,958,631],{"class":630},[624,960,635],{"class":634},[624,962,963],{"class":638}," evlogMiddleware",[624,965,642],{"class":634},[624,967,645],{"class":630},[624,969,648],{"class":634},[624,971,972],{"class":651},"evlog\u002F\u003Cframework>",[624,974,654],{"class":634},[624,976,977,979,981,983,985,987,989,991],{"class":626,"line":657},[624,978,631],{"class":630},[624,980,635],{"class":634},[624,982,912],{"class":638},[624,984,642],{"class":634},[624,986,645],{"class":630},[624,988,648],{"class":634},[624,990,921],{"class":651},[624,992,654],{"class":634},[624,994,995],{"class":626,"line":664},[624,996,661],{"emptyLinePlaceholder":660},[624,998,999,1002,1004,1007,1009,1012,1014,1016,1018,1020,1022,1024],{"class":626,"line":689},[624,1000,1001],{"class":638},"app",[624,1003,783],{"class":634},[624,1005,1006],{"class":680},"use",[624,1008,683],{"class":638},[624,1010,1011],{"class":680},"evlogMiddleware",[624,1013,683],{"class":638},[624,1015,791],{"class":634},[624,1017,939],{"class":692},[624,1019,696],{"class":634},[624,1021,944],{"class":638},[624,1023,870],{"class":634},[624,1025,1026],{"class":638},"))\n",[615,1028,1030],{"className":617,"code":1029,"filename":226,"language":619,"meta":620,"style":620},"\u002F\u002F Register the hooks you actually use directly:\nnitroApp.hooks.hook('evlog:enrich', tenantPlugin.enrich!)\nnitroApp.hooks.hook('evlog:request:start', tenantPlugin.onRequestStart!)\n",[516,1031,1032,1038,1075],{"__ignoreMap":620},[624,1033,1034],{"class":626,"line":627},[624,1035,1037],{"class":1036},"sHwdD","\u002F\u002F Register the hooks you actually use directly:\n",[624,1039,1040,1043,1045,1048,1050,1053,1055,1057,1060,1062,1064,1066,1068,1070,1073],{"class":626,"line":657},[624,1041,1042],{"class":638},"nitroApp",[624,1044,783],{"class":634},[624,1046,1047],{"class":638},"hooks",[624,1049,783],{"class":634},[624,1051,1052],{"class":680},"hook",[624,1054,683],{"class":638},[624,1056,704],{"class":634},[624,1058,1059],{"class":651},"evlog:enrich",[624,1061,704],{"class":634},[624,1063,723],{"class":634},[624,1065,912],{"class":638},[624,1067,783],{"class":634},[624,1069,553],{"class":638},[624,1071,1072],{"class":634},"!",[624,1074,812],{"class":638},[624,1076,1077,1079,1081,1083,1085,1087,1089,1091,1094,1096,1098,1100,1102,1104,1106],{"class":626,"line":664},[624,1078,1042],{"class":638},[624,1080,783],{"class":634},[624,1082,1047],{"class":638},[624,1084,783],{"class":634},[624,1086,1052],{"class":680},[624,1088,683],{"class":638},[624,1090,704],{"class":634},[624,1092,1093],{"class":651},"evlog:request:start",[624,1095,704],{"class":634},[624,1097,723],{"class":634},[624,1099,912],{"class":638},[624,1101,783],{"class":634},[624,1103,549],{"class":638},[624,1105,1072],{"class":634},[624,1107,812],{"class":638},[610,1109,1110],{"id":1047},"Hooks",[442,1112,1113,1126],{},[445,1114,1115],{},[448,1116,1117,1120,1123],{},[451,1118,1119],{},"Hook",[451,1121,1122],{},"When",[451,1124,1125],{},"Use it for",[458,1127,1128,1144,1159,1172,1192,1205,1218,1231],{},[448,1129,1130,1135,1138],{},[463,1131,1132],{},[516,1133,1134],{},"setup(ctx)",[463,1136,1137],{},"Once when registered",[463,1139,1140,1141,1143],{},"Read ",[516,1142,854],{},", set up shared state",[448,1145,1146,1151,1154],{},[463,1147,1148],{},[516,1149,1150],{},"onRequestStart(ctx)",[463,1152,1153],{},"Each request, before any handler runs",[463,1155,1156,1157],{},"Pull values from headers into ",[516,1158,780],{},[448,1160,1161,1166,1169],{},[463,1162,1163],{},[516,1164,1165],{},"enrich(ctx)",[463,1167,1168],{},"Every event, before drain",[463,1170,1171],{},"Add derived fields (geo, deploy id…)",[448,1173,1174,1179,1182],{},[463,1175,1176],{},[516,1177,1178],{},"keep(ctx)",[463,1180,1181],{},"Tail sampling decision",[463,1183,1184,1185,550,1188,1191],{},"Force-keep based on outcome (",[516,1186,1187],{},"status >= 400",[516,1189,1190],{},"duration > 500",", …)",[448,1193,1194,1199,1202],{},[463,1195,1196],{},[516,1197,1198],{},"drain(ctx)",[463,1200,1201],{},"Every emitted event",[463,1203,1204],{},"Side-effect: alert, mirror to a queue, etc.",[448,1206,1207,1212,1215],{},[463,1208,1209],{},[516,1210,1211],{},"onRequestFinish(ctx)",[463,1213,1214],{},"After response",[463,1216,1217],{},"Per-request post-processing",[448,1219,1220,1225,1228],{},[463,1221,1222],{},[516,1223,1224],{},"onClientLog(ctx)",[463,1226,1227],{},"Browser-submitted event hits the ingest endpoint",[463,1229,1230],{},"Observe \u002F reject client traffic",[448,1232,1233,1238,1241],{},[463,1234,1235],{},[516,1236,1237],{},"extendLogger(logger)",[463,1239,1240],{},"Each request",[463,1242,1243,1244,566],{},"Add custom methods (e.g. ",[516,1245,1246],{},"logger.audit.refund()",[433,1248,1249,1250,1253,1254,783],{},"Every hook is ",[437,1251,1252],{},"optional",". A plugin can implement any subset. The full type lives in ",[469,1255,1258],{"href":1256,"rel":1257},"https:\u002F\u002Fgithub.com\u002FHugoRCD\u002Fevlog\u002Fblob\u002Fmain\u002Fpackages\u002Fevlog\u002Fsrc\u002Fshared\u002Fplugin.ts",[608],[516,1259,1260],{},"packages\u002Fevlog\u002Fsrc\u002Fshared\u002Fplugin.ts",[610,1262,1264],{"id":1263},"common-pitfalls","Common pitfalls",[533,1266,1267,1276,1288,1311],{},[536,1268,1269,1272,1273,1275],{},[437,1270,1271],{},"Don't throw from a hook."," The plugin runner catches and logs errors with the plugin name, but a thrown error from ",[516,1274,553],{}," won't propagate the event downstream. Keep hooks defensive.",[536,1277,1278,1283,1284,1287],{},[437,1279,1280,1282],{},[516,1281,556],{}," runs for every event"," — not just per-request. If you only care about per-request lifecycle, use ",[516,1285,1286],{},"onRequestFinish"," instead.",[536,1289,1290,1295,1296,1299,1300,1303,1304,1307,1308,783],{},[437,1291,1292,1294],{},[516,1293,559],{}," mutates the logger object"," — augment ",[516,1297,1298],{},"RequestLogger"," in a ",[516,1301,1302],{},".d.ts"," so ",[516,1305,1306],{},"useLogger(event)"," exposes the new methods to TypeScript. See ",[469,1309,1310],{"href":181},"typed fields",[536,1312,1313,1319,1320,1322],{},[437,1314,1315,1316],{},"Plugins are de-duplicated by ",[516,1317,1318],{},"name",". Re-registering with the same ",[516,1321,1318],{}," replaces the previous version (last registration wins).",[507,1324,483],{"id":1325},"custom-enrichers",[1327,1328],"enricher-chain",{},[433,1330,1331,1332,1335],{},"An ",[437,1333,1334],{},"enricher"," runs on every emitted event before it reaches drains. It's the right tool when you want a field on every event without touching every call site — geo, user agent, trace context, deploy id, tenant id…",[525,1337,1339,1342,1425],{":actions":527,"description":1338,"icon":28},"Add a custom evlog enricher",[433,1340,1341],{},"Add a custom enricher so a field appears on every wide event automatically.",[533,1343,1344,1369,1386,1393,1405,1419],{},[536,1345,538,1346,542,1349,1352,1353,1356,1357,1360,1361,1364,1365,1368],{},[516,1347,1348],{},"defineEnricher",[516,1350,1351],{},"evlog\u002Ftoolkit"," and call it with ",[516,1354,1355],{},"{ name, field?, compute }"," — ",[516,1358,1359],{},"compute(ctx)"," returns the value to merge into ",[516,1362,1363],{},"event[field]",", or ",[516,1366,1367],{},"undefined"," to skip",[536,1370,1371,1372,550,1375,550,1378,1381,1382,1385],{},"Read from ",[516,1373,1374],{},"ctx.headers",[516,1376,1377],{},"ctx.env",[516,1379,1380],{},"ctx.request"," — never from ",[516,1383,1384],{},"globalThis"," request state",[536,1387,1388,1389,1392],{},"Keep ",[516,1390,1391],{},"compute"," pure and fast: no awaitable I\u002FO on the hot path; cache anything expensive at module scope",[536,1394,1395,1397,1398,1400,1401,1404],{},[516,1396,1391],{}," is wrapped in try\u002Fcatch by ",[516,1399,1348],{},"; throwing logs ",[516,1402,1403],{},"[evlog\u002F\u003Cname>] enrich failed:"," and skips the enrichment without blocking the request",[536,1406,1407,1408,1410,1411,1414,1415,1418],{},"Wire it on my framework: Nuxt\u002FNitro ",[516,1409,1059],{}," hook, Hono\u002FExpress\u002FFastify\u002FElysia ",[516,1412,1413],{},"{ enrichers: [...] }"," middleware option, or ",[516,1416,1417],{},"initLogger({ enrichers: [...] })"," for standalone",[536,1420,1421,1422,1424],{},"For multi-hook features (enrich + drain side-effect, etc.), use ",[516,1423,541],{}," instead",[433,1426,603,1427],{},[469,1428,606],{"href":606,"rel":1429},[608],[433,1431,1432,1433,1436,1437,783],{},"The full reference — ",[516,1434,1435],{},"defineEnricher()"," API, async enrichers, combining built-in + custom, framework wiring — lives at ",[469,1438,483],{"href":425},[610,1440,1442],{"id":1441},"when-to-reach-for-a-plugin-instead","When to reach for a plugin instead",[433,1444,1445,1446,1449],{},"If your feature mixes enrichment with other hooks (e.g. enrich + tail-sample + side-effect on drain), use a ",[469,1447,1448],{"href":471},"plugin"," instead — one cohesive object covering several lifecycle points.",[507,1451,494],{"id":1452},"tail-sampling",[1454,1455],"tail-sample-decision",{},[433,1457,1458,1460,1461,1465],{},[437,1459,494],{}," is a decision made ",[1462,1463,1464],"em",{},"after"," the request runs, with full knowledge of its outcome (status, duration, errors, custom flags). It's how you keep all errors and slow requests while throwing away the bulk of healthy traffic — the opposite of head sampling, which decides up front before knowing what happens.",[525,1467,1469,1472,1515],{":actions":527,"description":1468,"icon":178},"Configure tail sampling on evlog",[433,1470,1471],{},"Set up tail sampling so I keep all errors and slow requests while dropping healthy noise.",[533,1473,1474,1480,1495,1498,1508],{},[536,1475,1476,1477],{},"Start with the built-in declarative rules: ",[516,1478,1479],{},"evlog.sampling.keep = { status: '>=400', duration: '>1000', path: ['\u002Fapi\u002Fauth\u002F*'] }",[536,1481,1482,1483,1486,1487,1490,1491,1494],{},"For multi-field or derived conditions, register an ",[516,1484,1485],{},"evlog:emit:keep"," hook (Nitro: ",[516,1488,1489],{},"nitroApp.hooks.hook('evlog:emit:keep', (ctx) => ...)","); set ",[516,1492,1493],{},"ctx.shouldKeep = true"," to keep",[536,1496,1497],{},"Keep the hook fast — it runs on every request after enrichment; no I\u002FO, no async work",[536,1499,1500,1501,1504,1505,1507],{},"Combine with head sampling (e.g. 10% of healthy traffic) by setting both ",[516,1502,1503],{},"sample"," (head) and ",[516,1506,562],{}," (tail)",[536,1509,1510,1511,1514],{},"Always keep error events (",[516,1512,1513],{},"level: 'error'",") regardless of sampling; double-check rules don't accidentally drop them",[433,1516,603,1517],{},[469,1518,606],{"href":606,"rel":1519},[608],[433,1521,1522,1523,1525,1526,1528,1529,783],{},"The full theory and config reference — built-in ",[516,1524,562],{}," rules, custom predicates via ",[516,1527,1485],{},", combining head + tail sampling — lives at ",[469,1530,175],{"href":176},[610,1532,1534],{"id":1533},"custom-keep-hook","Custom keep hook",[433,1536,1537,1538,1540],{},"The built-in declarative ",[516,1539,562],{}," rules cover the typical cases. Drop to a custom hook when you need:",[533,1542,1543,1554,1560],{},[536,1544,1545,1546,1549,1550,1553],{},"Conditional logic on more than one field (e.g. \"keep if ",[516,1547,1548],{},"status >= 500"," AND ",[516,1551,1552],{},"user.plan === 'enterprise'","\")",[536,1555,1556,1557,1553],{},"Keep based on a derived value (e.g. \"keep if ",[516,1558,1559],{},"event.audit?.context.actor.role === 'admin'",[536,1561,1562],{},"Stateful decisions (rare; needs care since sampling runs in the hot path)",[615,1564,1566],{"className":617,"code":1565,"language":619,"meta":620,"style":620},"nitroApp.hooks.hook('evlog:emit:keep', (ctx) => {\n  if (ctx.context.user?.plan === 'enterprise' && ctx.status >= 500) {\n    ctx.shouldKeep = true\n  }\n})\n",[516,1567,1568,1602,1658,1674,1679],{"__ignoreMap":620},[624,1569,1570,1572,1574,1576,1578,1580,1582,1584,1586,1588,1590,1592,1595,1597,1600],{"class":626,"line":627},[624,1571,1042],{"class":638},[624,1573,783],{"class":634},[624,1575,1047],{"class":638},[624,1577,783],{"class":634},[624,1579,1052],{"class":680},[624,1581,683],{"class":638},[624,1583,704],{"class":634},[624,1585,1485],{"class":651},[624,1587,704],{"class":634},[624,1589,723],{"class":634},[624,1591,771],{"class":634},[624,1593,1594],{"class":719},"ctx",[624,1596,566],{"class":634},[624,1598,1599],{"class":670}," =>",[624,1601,732],{"class":634},[624,1603,1604,1607,1609,1611,1613,1616,1618,1621,1623,1626,1629,1631,1634,1636,1639,1642,1644,1647,1650,1654,1656],{"class":626,"line":657},[624,1605,1606],{"class":630},"  if",[624,1608,771],{"class":692},[624,1610,1594],{"class":638},[624,1612,783],{"class":634},[624,1614,1615],{"class":638},"context",[624,1617,783],{"class":634},[624,1619,1620],{"class":638},"user",[624,1622,749],{"class":634},[624,1624,1625],{"class":638},"plan",[624,1627,1628],{"class":634}," ===",[624,1630,648],{"class":634},[624,1632,1633],{"class":651},"enterprise",[624,1635,704],{"class":634},[624,1637,1638],{"class":634}," &&",[624,1640,1641],{"class":638}," ctx",[624,1643,783],{"class":634},[624,1645,1646],{"class":638},"status",[624,1648,1649],{"class":634}," >=",[624,1651,1653],{"class":1652},"sbssI"," 500",[624,1655,777],{"class":692},[624,1657,686],{"class":634},[624,1659,1660,1663,1665,1668,1670],{"class":626,"line":664},[624,1661,1662],{"class":638},"    ctx",[624,1664,783],{"class":634},[624,1666,1667],{"class":638},"shouldKeep",[624,1669,744],{"class":634},[624,1671,1673],{"class":1672},"sfNiH"," true\n",[624,1675,1676],{"class":626,"line":689},[624,1677,1678],{"class":634},"  }\n",[624,1680,1681,1683],{"class":626,"line":710},[624,1682,870],{"class":634},[624,1684,812],{"class":638},[433,1686,1687],{},"Or as a plugin (preferred for non-trivial logic):",[615,1689,1691],{"className":617,"code":1690,"language":619,"meta":620,"style":620},"import { definePlugin } from 'evlog\u002Ftoolkit'\n\ndefinePlugin({\n  name: 'keep-enterprise-errors',\n  keep(ctx) {\n    if (ctx.context.user?.plan === 'enterprise' && ctx.status >= 500) {\n      ctx.shouldKeep = true\n    }\n  },\n})\n",[516,1692,1693,1711,1715,1723,1738,1751,1795,1808,1813,1817],{"__ignoreMap":620},[624,1694,1695,1697,1699,1701,1703,1705,1707,1709],{"class":626,"line":627},[624,1696,631],{"class":630},[624,1698,635],{"class":634},[624,1700,639],{"class":638},[624,1702,642],{"class":634},[624,1704,645],{"class":630},[624,1706,648],{"class":634},[624,1708,1351],{"class":651},[624,1710,654],{"class":634},[624,1712,1713],{"class":626,"line":657},[624,1714,661],{"emptyLinePlaceholder":660},[624,1716,1717,1719,1721],{"class":626,"line":664},[624,1718,541],{"class":680},[624,1720,683],{"class":638},[624,1722,686],{"class":634},[624,1724,1725,1727,1729,1731,1734,1736],{"class":626,"line":689},[624,1726,693],{"class":692},[624,1728,696],{"class":634},[624,1730,648],{"class":634},[624,1732,1733],{"class":651},"keep-enterprise-errors",[624,1735,704],{"class":634},[624,1737,707],{"class":634},[624,1739,1740,1743,1745,1747,1749],{"class":626,"line":710},[624,1741,1742],{"class":692},"  keep",[624,1744,683],{"class":634},[624,1746,1594],{"class":719},[624,1748,566],{"class":634},[624,1750,732],{"class":634},[624,1752,1753,1755,1757,1759,1761,1763,1765,1767,1769,1771,1773,1775,1777,1779,1781,1783,1785,1787,1789,1791,1793],{"class":626,"line":735},[624,1754,768],{"class":630},[624,1756,771],{"class":692},[624,1758,1594],{"class":638},[624,1760,783],{"class":634},[624,1762,1615],{"class":638},[624,1764,783],{"class":634},[624,1766,1620],{"class":638},[624,1768,749],{"class":634},[624,1770,1625],{"class":638},[624,1772,1628],{"class":634},[624,1774,648],{"class":634},[624,1776,1633],{"class":651},[624,1778,704],{"class":634},[624,1780,1638],{"class":634},[624,1782,1641],{"class":638},[624,1784,783],{"class":634},[624,1786,1646],{"class":638},[624,1788,1649],{"class":634},[624,1790,1653],{"class":1652},[624,1792,777],{"class":692},[624,1794,686],{"class":634},[624,1796,1797,1800,1802,1804,1806],{"class":626,"line":765},[624,1798,1799],{"class":638},"      ctx",[624,1801,783],{"class":634},[624,1803,1667],{"class":638},[624,1805,744],{"class":634},[624,1807,1673],{"class":1672},[624,1809,1810],{"class":626,"line":815},[624,1811,1812],{"class":634},"    }\n",[624,1814,1815],{"class":626,"line":821},[624,1816,818],{"class":634},[624,1818,1819,1821],{"class":626,"line":836},[624,1820,870],{"class":634},[624,1822,812],{"class":638},[507,1824,505],{"id":1825},"identity-headers",[433,1827,1828],{},"Every drain request sent by evlog is tagged with two identity headers so receivers can identify the traffic:",[442,1830,1831,1841],{},[445,1832,1833],{},[448,1834,1835,1838],{},[451,1836,1837],{},"Header",[451,1839,1840],{},"Value",[458,1842,1843,1856],{},[448,1844,1845,1850],{},[463,1846,1847],{},[516,1848,1849],{},"User-Agent",[463,1851,1852,1855],{},[516,1853,1854],{},"evlog\u002F\u003Cversion>"," (Node \u002F server runtimes only — browsers strip this header)",[448,1857,1858,1863],{},[463,1859,1860],{},[516,1861,1862],{},"X-Evlog-Source",[463,1864,1865,1866,550,1869,550,1872,550,1875,550,1878,550,1881,550,1884,1191],{},"The adapter name (",[516,1867,1868],{},"axiom",[516,1870,1871],{},"datadog",[516,1873,1874],{},"otlp",[516,1876,1877],{},"posthog",[516,1879,1880],{},"sentry",[516,1882,1883],{},"better-stack",[516,1885,1886],{},"client",[433,1888,1889,1890,1893,1894,1897,1898,783],{},"The browser-side ",[516,1891,1892],{},"evlog\u002Fhttp"," drain (used by the client transport) sets ",[516,1895,1896],{},"X-Evlog-Source: client"," instead, since browsers cannot override ",[516,1899,1849],{},[610,1901,1903],{"id":1902},"why","Why",[533,1905,1906,1909,1912],{},[536,1907,1908],{},"Quickly distinguish evlog traffic from other clients in the receiving system's logs",[536,1910,1911],{},"Track adapter usage \u002F version drift centrally",[536,1913,1914],{},"Identify the source when debugging a specific drain",[610,1916,1918],{"id":1917},"reading-the-version","Reading the version",[433,1920,1921,1922,696],{},"Both constants are exported from ",[516,1923,1351],{},[615,1925,1927],{"className":617,"code":1926,"language":619,"meta":620,"style":620},"import { EVLOG_USER_AGENT, EVLOG_VERSION } from 'evlog\u002Ftoolkit'\n\nconsole.log(EVLOG_VERSION)    \u002F\u002F → \"2.16.0\"\nconsole.log(EVLOG_USER_AGENT) \u002F\u002F → \"evlog\u002F2.16.0\"\n",[516,1928,1929,1953,1957,1973],{"__ignoreMap":620},[624,1930,1931,1933,1935,1938,1940,1943,1945,1947,1949,1951],{"class":626,"line":627},[624,1932,631],{"class":630},[624,1934,635],{"class":634},[624,1936,1937],{"class":638}," EVLOG_USER_AGENT",[624,1939,723],{"class":634},[624,1941,1942],{"class":638}," EVLOG_VERSION",[624,1944,642],{"class":634},[624,1946,645],{"class":630},[624,1948,648],{"class":634},[624,1950,1351],{"class":651},[624,1952,654],{"class":634},[624,1954,1955],{"class":626,"line":657},[624,1956,661],{"emptyLinePlaceholder":660},[624,1958,1959,1962,1964,1967,1970],{"class":626,"line":664},[624,1960,1961],{"class":638},"console",[624,1963,783],{"class":634},[624,1965,1966],{"class":680},"log",[624,1968,1969],{"class":638},"(EVLOG_VERSION)    ",[624,1971,1972],{"class":1036},"\u002F\u002F → \"2.16.0\"\n",[624,1974,1975,1977,1979,1981,1984],{"class":626,"line":689},[624,1976,1961],{"class":638},[624,1978,783],{"class":634},[624,1980,1966],{"class":680},[624,1982,1983],{"class":638},"(EVLOG_USER_AGENT) ",[624,1985,1986],{"class":1036},"\u002F\u002F → \"evlog\u002F2.16.0\"\n",[610,1988,1990],{"id":1989},"custom-drains","Custom drains",[433,1992,1993,1994,542,1997,1999],{},"When you build a drain on top of ",[516,1995,1996],{},"httpPost",[516,1998,1351],{},", identity headers are injected automatically. To override or suppress them:",[615,2001,2003],{"className":617,"code":2002,"language":619,"meta":620,"style":620},"import { httpPost } from 'evlog\u002Ftoolkit'\n\nawait httpPost({\n  url: 'https:\u002F\u002Fmy-platform.example.com\u002Fingest',\n  headers: { 'Content-Type': 'application\u002Fjson' },\n  body: '[]',\n  timeout: 5000,\n  label: 'my-platform',\n  source: 'my-platform',           \u002F\u002F sent as X-Evlog-Source\n  userAgent: 'my-fork\u002F1.0',        \u002F\u002F overrides the default User-Agent\n  \u002F\u002F userAgent: false,             \u002F\u002F suppress the header entirely\n})\n",[516,2004,2005,2024,2028,2039,2055,2083,2099,2111,2127,2145,2164,2172],{"__ignoreMap":620},[624,2006,2007,2009,2011,2014,2016,2018,2020,2022],{"class":626,"line":627},[624,2008,631],{"class":630},[624,2010,635],{"class":634},[624,2012,2013],{"class":638}," httpPost",[624,2015,642],{"class":634},[624,2017,645],{"class":630},[624,2019,648],{"class":634},[624,2021,1351],{"class":651},[624,2023,654],{"class":634},[624,2025,2026],{"class":626,"line":657},[624,2027,661],{"emptyLinePlaceholder":660},[624,2029,2030,2033,2035,2037],{"class":626,"line":664},[624,2031,2032],{"class":630},"await",[624,2034,2013],{"class":680},[624,2036,683],{"class":638},[624,2038,686],{"class":634},[624,2040,2041,2044,2046,2048,2051,2053],{"class":626,"line":689},[624,2042,2043],{"class":692},"  url",[624,2045,696],{"class":634},[624,2047,648],{"class":634},[624,2049,2050],{"class":651},"https:\u002F\u002Fmy-platform.example.com\u002Fingest",[624,2052,704],{"class":634},[624,2054,707],{"class":634},[624,2056,2057,2060,2062,2064,2066,2069,2071,2073,2075,2078,2080],{"class":626,"line":710},[624,2058,2059],{"class":692},"  headers",[624,2061,696],{"class":634},[624,2063,635],{"class":634},[624,2065,648],{"class":634},[624,2067,2068],{"class":692},"Content-Type",[624,2070,704],{"class":634},[624,2072,696],{"class":634},[624,2074,648],{"class":634},[624,2076,2077],{"class":651},"application\u002Fjson",[624,2079,704],{"class":634},[624,2081,2082],{"class":634}," },\n",[624,2084,2085,2088,2090,2092,2095,2097],{"class":626,"line":735},[624,2086,2087],{"class":692},"  body",[624,2089,696],{"class":634},[624,2091,648],{"class":634},[624,2093,2094],{"class":651},"[]",[624,2096,704],{"class":634},[624,2098,707],{"class":634},[624,2100,2101,2104,2106,2109],{"class":626,"line":765},[624,2102,2103],{"class":692},"  timeout",[624,2105,696],{"class":634},[624,2107,2108],{"class":1652}," 5000",[624,2110,707],{"class":634},[624,2112,2113,2116,2118,2120,2123,2125],{"class":626,"line":815},[624,2114,2115],{"class":692},"  label",[624,2117,696],{"class":634},[624,2119,648],{"class":634},[624,2121,2122],{"class":651},"my-platform",[624,2124,704],{"class":634},[624,2126,707],{"class":634},[624,2128,2129,2132,2134,2136,2138,2140,2142],{"class":626,"line":821},[624,2130,2131],{"class":692},"  source",[624,2133,696],{"class":634},[624,2135,648],{"class":634},[624,2137,2122],{"class":651},[624,2139,704],{"class":634},[624,2141,723],{"class":634},[624,2143,2144],{"class":1036},"           \u002F\u002F sent as X-Evlog-Source\n",[624,2146,2147,2150,2152,2154,2157,2159,2161],{"class":626,"line":836},[624,2148,2149],{"class":692},"  userAgent",[624,2151,696],{"class":634},[624,2153,648],{"class":634},[624,2155,2156],{"class":651},"my-fork\u002F1.0",[624,2158,704],{"class":634},[624,2160,723],{"class":634},[624,2162,2163],{"class":1036},"        \u002F\u002F overrides the default User-Agent\n",[624,2165,2166,2169],{"class":626,"line":862},[624,2167,2168],{"class":1036},"  \u002F\u002F userAgent: false,",[624,2170,2171],{"class":1036},"             \u002F\u002F suppress the header entirely\n",[624,2173,2174,2176],{"class":626,"line":867},[624,2175,870],{"class":634},[624,2177,812],{"class":638},[433,2179,2180,2181,2184,2185,2187,2188,783],{},"Adapters built with ",[516,2182,2183],{},"defineHttpDrain()"," automatically pass the drain ",[516,2186,1318],{}," as ",[516,2189,2190],{},"source",[2192,2193,2194],"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 .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 .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 .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":620,"searchDepth":657,"depth":657,"links":2196},[2197,2202,2205,2208],{"id":509,"depth":657,"text":472,"children":2198},[2199,2200,2201],{"id":612,"depth":664,"text":613},{"id":1047,"depth":664,"text":1110},{"id":1263,"depth":664,"text":1264},{"id":1325,"depth":657,"text":483,"children":2203},[2204],{"id":1441,"depth":664,"text":1442},{"id":1452,"depth":657,"text":494,"children":2206},[2207],{"id":1533,"depth":664,"text":1534},{"id":1825,"depth":657,"text":505,"children":2209},[2210,2211,2212],{"id":1902,"depth":664,"text":1903},{"id":1917,"depth":664,"text":1918},{"id":1989,"depth":664,"text":1990},"Hook into the evlog pipeline — plugins for cross-cutting concerns, enrichers for derived context, tail sampling for outcome-aware keep decisions, identity headers on every drain request.","md",null,{},{"title":312,"icon":288},{"title":312,"description":2213},"b8V-x2i9BOhA75DutTkbZySJm5LFUKa7GQSFeruBCcI",[2221,2223],{"title":156,"path":308,"stem":309,"description":2222,"icon":310,"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":316,"path":317,"stem":318,"description":2224,"icon":319,"children":-1},"Build, batch, and fan out drains — write a custom drain for any backend, wrap it in createDrainPipeline for batch + retry, and compose multiple destinations through one pipeline.",1778349127201]