[{"data":1,"prerenderedAt":3561},["ShallowReactive",2],{"navigation_docs":3,"-extend-custom-drains":429,"-extend-custom-drains-surround":3556},[4,30,80,235,343,398],{"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,152],{"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],{"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,"children":156,"page":29},"Frameworks","\u002Fintegrate\u002Fframeworks","3.integrate\u002Fframeworks",[157,161,166,171,176,181,186,191,196,201,206,211,216,221,225,230],{"title":36,"path":158,"stem":159,"icon":160},"\u002Fintegrate\u002Fframeworks\u002Foverview","3.integrate\u002Fframeworks\u002F00.overview","i-lucide-layout-grid",{"title":162,"path":163,"stem":164,"icon":165},"Nuxt","\u002Fintegrate\u002Fframeworks\u002Fnuxt","3.integrate\u002Fframeworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":167,"path":168,"stem":169,"icon":170},"Next.js","\u002Fintegrate\u002Fframeworks\u002Fnextjs","3.integrate\u002Fframeworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":172,"path":173,"stem":174,"icon":175},"SvelteKit","\u002Fintegrate\u002Fframeworks\u002Fsveltekit","3.integrate\u002Fframeworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":177,"path":178,"stem":179,"icon":180},"Nitro","\u002Fintegrate\u002Fframeworks\u002Fnitro","3.integrate\u002Fframeworks\u002F04.nitro","i-custom-nitro",{"title":182,"path":183,"stem":184,"icon":185},"TanStack Start","\u002Fintegrate\u002Fframeworks\u002Ftanstack-start","3.integrate\u002Fframeworks\u002F05.tanstack-start","i-custom-tanstack",{"title":187,"path":188,"stem":189,"icon":190},"NestJS","\u002Fintegrate\u002Fframeworks\u002Fnestjs","3.integrate\u002Fframeworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":192,"path":193,"stem":194,"icon":195},"Express","\u002Fintegrate\u002Fframeworks\u002Fexpress","3.integrate\u002Fframeworks\u002F07.express","i-simple-icons-express",{"title":197,"path":198,"stem":199,"icon":200},"Hono","\u002Fintegrate\u002Fframeworks\u002Fhono","3.integrate\u002Fframeworks\u002F08.hono","i-simple-icons-hono",{"title":202,"path":203,"stem":204,"icon":205},"Fastify","\u002Fintegrate\u002Fframeworks\u002Ffastify","3.integrate\u002Fframeworks\u002F09.fastify","i-simple-icons-fastify",{"title":207,"path":208,"stem":209,"icon":210},"Elysia","\u002Fintegrate\u002Fframeworks\u002Felysia","3.integrate\u002Fframeworks\u002F10.elysia","i-custom-elysia",{"title":212,"path":213,"stem":214,"icon":215},"React Router","\u002Fintegrate\u002Fframeworks\u002Freact-router","3.integrate\u002Fframeworks\u002F11.react-router","i-custom-reactrouter",{"title":217,"path":218,"stem":219,"icon":220},"Cloudflare Workers","\u002Fintegrate\u002Fframeworks\u002Fcloudflare-workers","3.integrate\u002Fframeworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":222,"path":223,"stem":224,"icon":74},"Standalone","\u002Fintegrate\u002Fframeworks\u002Fstandalone","3.integrate\u002Fframeworks\u002F13.standalone",{"title":226,"path":227,"stem":228,"icon":229},"Astro","\u002Fintegrate\u002Fframeworks\u002Fastro","3.integrate\u002Fframeworks\u002F14.astro","i-simple-icons-astro",{"title":231,"path":232,"stem":233,"icon":234},"AWS Lambda","\u002Fintegrate\u002Fframeworks\u002Faws-lambda","3.integrate\u002Fframeworks\u002F16.aws-lambda","i-custom-lambda",{"title":236,"path":237,"stem":238,"children":239,"page":29},"Use Cases","\u002Fuse-cases","4.use-cases",[240,244,249,278,306,338],{"title":36,"path":241,"stem":242,"icon":243},"\u002Fuse-cases\u002Foverview","4.use-cases\u002F0.overview","i-lucide-list-checks",{"title":245,"path":246,"stem":247,"icon":248},"Client Logging","\u002Fuse-cases\u002Fclient-logging","4.use-cases\u002F1.client-logging","i-lucide-monitor",{"title":250,"icon":251,"path":252,"stem":253,"children":254,"page":29},"AI SDK","i-simple-icons-vercel","\u002Fuse-cases\u002Fai-sdk","4.use-cases\u002F2.ai-sdk",[255,258,263,268,273],{"title":36,"path":256,"stem":257,"icon":39},"\u002Fuse-cases\u002Fai-sdk\u002Foverview","4.use-cases\u002F2.ai-sdk\u002F01.overview",{"title":259,"path":260,"stem":261,"icon":262},"Usage","\u002Fuse-cases\u002Fai-sdk\u002Fusage","4.use-cases\u002F2.ai-sdk\u002F02.usage","i-lucide-code",{"title":264,"path":265,"stem":266,"icon":267},"Options","\u002Fuse-cases\u002Fai-sdk\u002Foptions","4.use-cases\u002F2.ai-sdk\u002F03.options","i-lucide-sliders",{"title":269,"path":270,"stem":271,"icon":272},"Metadata","\u002Fuse-cases\u002Fai-sdk\u002Fmetadata","4.use-cases\u002F2.ai-sdk\u002F04.metadata","i-lucide-database",{"title":274,"path":275,"stem":276,"icon":277},"Telemetry","\u002Fuse-cases\u002Fai-sdk\u002Ftelemetry","4.use-cases\u002F2.ai-sdk\u002F05.telemetry","i-lucide-activity",{"title":279,"icon":280,"path":281,"stem":282,"children":283,"page":29},"Better Auth","i-simple-icons-betterauth","\u002Fuse-cases\u002Fbetter-auth","4.use-cases\u002F3.better-auth",[284,287,292,297,301],{"title":36,"path":285,"stem":286,"icon":39},"\u002Fuse-cases\u002Fbetter-auth\u002Foverview","4.use-cases\u002F3.better-auth\u002F01.overview",{"title":288,"path":289,"stem":290,"icon":291},"Identify User","\u002Fuse-cases\u002Fbetter-auth\u002Fidentify-user","4.use-cases\u002F3.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":293,"path":294,"stem":295,"icon":296},"Middleware","\u002Fuse-cases\u002Fbetter-auth\u002Fmiddleware","4.use-cases\u002F3.better-auth\u002F03.middleware","i-lucide-shield",{"title":298,"path":299,"stem":300,"icon":248},"Client Sync","\u002Fuse-cases\u002Fbetter-auth\u002Fclient-sync","4.use-cases\u002F3.better-auth\u002F04.client-sync",{"title":302,"path":303,"stem":304,"icon":305},"Performance","\u002Fuse-cases\u002Fbetter-auth\u002Fperformance","4.use-cases\u002F3.better-auth\u002F05.performance","i-lucide-gauge",{"title":307,"icon":308,"path":309,"stem":310,"children":311,"page":29},"Audit Logs","i-lucide-shield-check","\u002Fuse-cases\u002Faudit","4.use-cases\u002F4.audit",[312,315,320,325,330,334],{"title":36,"path":313,"stem":314,"icon":39},"\u002Fuse-cases\u002Faudit\u002Foverview","4.use-cases\u002F4.audit\u002F01.overview",{"title":316,"path":317,"stem":318,"icon":319},"Schema","\u002Fuse-cases\u002Faudit\u002Fschema","4.use-cases\u002F4.audit\u002F02.schema","i-lucide-file-text",{"title":321,"path":322,"stem":323,"icon":324},"Recording","\u002Fuse-cases\u002Faudit\u002Frecording","4.use-cases\u002F4.audit\u002F03.recording","i-lucide-pen-line",{"title":326,"path":327,"stem":328,"icon":329},"Drains","\u002Fuse-cases\u002Faudit\u002Fpipeline","4.use-cases\u002F4.audit\u002F04.pipeline","i-lucide-link",{"title":331,"path":332,"stem":333,"icon":308},"Compliance","\u002Fuse-cases\u002Faudit\u002Fcompliance","4.use-cases\u002F4.audit\u002F05.compliance",{"title":335,"path":336,"stem":337,"icon":79},"Recipes","\u002Fuse-cases\u002Faudit\u002Frecipes","4.use-cases\u002F4.audit\u002F06.recipes",{"title":339,"path":340,"stem":341,"icon":342},"Enrichers","\u002Fuse-cases\u002Fenrichers","4.use-cases\u002F5.enrichers","i-lucide-sparkles",{"title":344,"path":345,"stem":346,"children":347,"page":29},"Extend","\u002Fextend","5.extend",[348,352,357,362,367,371,375,379,383,388,393],{"title":36,"path":349,"stem":350,"icon":351},"\u002Fextend\u002Foverview","5.extend\u002F0.overview","i-lucide-blocks",{"title":353,"path":354,"stem":355,"icon":356},"Stream","\u002Fextend\u002Fstream","5.extend\u002F1.stream","i-lucide-radio-tower",{"title":358,"path":359,"stem":360,"icon":361},"Custom framework","\u002Fextend\u002Fcustom-framework","5.extend\u002F10.custom-framework","i-lucide-puzzle",{"title":363,"path":364,"stem":365,"icon":366},"FS reader","\u002Fextend\u002Ffs-reader","5.extend\u002F2.fs-reader","i-lucide-folder-search",{"title":335,"path":368,"stem":369,"icon":370},"\u002Fextend\u002Fconsumer-recipes","5.extend\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":372,"path":373,"stem":374,"icon":351},"Plugins","\u002Fextend\u002Fplugins","5.extend\u002F4.plugins",{"title":376,"path":377,"stem":378,"icon":342},"Custom enrichers","\u002Fextend\u002Fcustom-enrichers","5.extend\u002F5.custom-enrichers",{"title":380,"path":381,"stem":382,"icon":64},"Tail sampling","\u002Fextend\u002Ftail-sampling","5.extend\u002F6.tail-sampling",{"title":384,"path":385,"stem":386,"icon":387},"Identity headers","\u002Fextend\u002Fidentity-headers","5.extend\u002F7.identity-headers","i-lucide-fingerprint",{"title":389,"path":390,"stem":391,"icon":392},"Custom drains","\u002Fextend\u002Fcustom-drains","5.extend\u002F8.custom-drains","i-lucide-share-2",{"title":394,"path":395,"stem":396,"icon":397},"Drain pipeline","\u002Fextend\u002Fdrain-pipeline","5.extend\u002F9.drain-pipeline","i-lucide-workflow",{"title":399,"path":400,"stem":401,"children":402,"page":29},"Reference","\u002Freference","6.reference",[403,408,411,416,420,425],{"title":404,"path":405,"stem":406,"icon":407},"Configuration","\u002Freference\u002Fconfiguration","6.reference\u002F1.configuration","i-lucide-settings",{"title":302,"path":409,"stem":410,"icon":305},"\u002Freference\u002Fperformance","6.reference\u002F2.performance",{"title":412,"path":413,"stem":414,"icon":415},"Vite Plugin","\u002Freference\u002Fvite-plugin","6.reference\u002F3.vite-plugin","i-custom-vite",{"title":417,"path":418,"stem":419,"icon":308},"Best Practices","\u002Freference\u002Fbest-practices","6.reference\u002F4.best-practices",{"title":421,"path":422,"stem":423,"icon":424},"vs Other Loggers","\u002Freference\u002Fvs-other-loggers","6.reference\u002F5.vs-other-loggers","i-lucide-scale",{"title":426,"path":427,"stem":428,"icon":342},"Agent Skills","\u002Freference\u002Fagent-skills","6.reference\u002F6.agent-skills",{"id":430,"title":431,"body":432,"description":3544,"extension":3545,"links":3546,"meta":3552,"navigation":3553,"path":390,"seo":3554,"stem":391,"__hash__":3555},"docs\u002F5.extend\u002F8.custom-drains.md","Custom Drains",{"type":433,"value":434,"toc":3527},"minimark",[435,449,452,503,510,631,638,651,1315,1329,1334,1337,1813,1817,1822,1854,1884,1888,1895,2330,2338,2342,2354,2710,2716,2722,2908,2925,2929,2939,3198,3215,3219,3224,3330,3333,3338,3379,3388,3392,3397,3439,3445,3449,3452,3460,3474,3486,3490,3523],[436,437,438,439,443,444,448],"p",{},"A ",[440,441,442],"strong",{},"drain"," is the terminal step of evlog's pipeline: a function that receives wide events and ships them somewhere — an HTTP API, a message queue, a database, a webhook, a local file. evlog ships built-in drains for popular providers (",[445,446,447],"a",{"href":95},"Adapters overview","). When you need a destination that isn't covered, you write your own.",[436,450,451],{},"Two factories cover every case:",[453,454,455,468],"table",{},[456,457,458],"thead",{},[459,460,461,465],"tr",{},[462,463,464],"th",{},"You have…",[462,466,467],{},"Use",[469,470,471,490],"tbody",{},[459,472,473,482],{},[474,475,476,477,481],"td",{},"An HTTP backend (REST, JSON ingest, vendor ",[478,479,480],"code",{},"\u002Fv1\u002Flogs"," endpoint)",[474,483,484],{},[445,485,487],{"href":486},"#definehttpdrain-the-http-recipe",[478,488,489],{},"defineHttpDrain",[459,491,492,495],{},[474,493,494],{},"A non-HTTP transport (gRPC, WebSocket, vendor SDK, queue, raw socket)",[474,496,497],{},[445,498,500],{"href":499},"#definedrain-non-http-transports",[478,501,502],{},"defineDrain",[436,504,505,506,509],{},"Both come from ",[478,507,508],{},"evlog\u002Ftoolkit"," and are the exact factories every built-in adapter uses.",[511,512,516,519,618],"prompt",{":actions":513,"description":514,"icon":515},"[\"copy\",\"cursor\",\"windsurf\"]","Build a custom evlog drain","i-lucide-code-2",[436,517,518],{},"Build a custom evlog drain that ships wide events to a backend without a built-in adapter.",[520,521,522,537,548,563,581,596,601,611],"ul",{},[523,524,525,526,529,530,532,533,536],"li",{},"For HTTP backends, use ",[478,527,528],{},"defineHttpDrain({ name, resolve, encode })"," from ",[478,531,508],{}," — never call ",[478,534,535],{},"fetch"," directly",[523,538,539,540,543,544,547],{},"For non-HTTP transports (queue, DB, native SDK, raw socket), use ",[478,541,542],{},"defineDrain({ name, send })"," and implement ",[478,545,546],{},"send(events)"," myself",[523,549,550,551,554,555,558,559,562],{},"Resolve config lazily inside ",[478,552,553],{},"resolve()"," via ",[478,556,557],{},"resolveAdapterConfig(namespace, fields, overrides)"," so users get the standard precedence (overrides → ",[478,560,561],{},"runtimeConfig.evlog.\u003Cns>"," → env)",[523,564,565,566,569,570,573,574,577,578],{},"Use the standardized field names: ",[478,567,568],{},"apiKey"," for bearer secrets, ",[478,571,572],{},"endpoint"," for the base URL, ",[478,575,576],{},"serviceName",", ",[478,579,580],{},"timeout",[523,582,583,584,587,588,591,592,595],{},"Encode batched events into the destination's wire format inside ",[478,585,586],{},"encode(events, config)"," — return ",[478,589,590],{},"{ url, headers, body }"," (or ",[478,593,594],{},"null"," to opt out of the batch)",[523,597,598,600],{},[478,599,489],{}," handles retries, timeouts, error isolation, batching, and identity headers — don't reimplement them",[523,602,603,604,607,608,610],{},"Wire the drain via ",[478,605,606],{},"defineEvlog({ drain: createMyDrain() })"," or my framework's middleware ",[478,609,442],{}," option",[523,612,613,614,617],{},"For production, wrap the result in ",[478,615,616],{},"createDrainPipeline"," for batching + retries",[436,619,620,621,626,627],{},"Docs: ",[445,622,623],{"href":623,"rel":624},"https:\u002F\u002Fwww.evlog.dev\u002Fextend\u002Fcustom-drains",[625],"nofollow","\nPipeline: ",[445,628,629],{"href":629,"rel":630},"https:\u002F\u002Fwww.evlog.dev\u002Fextend\u002Fdrain-pipeline",[625],[632,633,635,637],"h2",{"id":634},"definehttpdrain-the-http-recipe",[478,636,489],{}," (the HTTP recipe)",[436,639,640,641,643,644,646,647,650],{},"The recipe every built-in adapter follows. Two pure functions: ",[478,642,553],{}," returns the config (or ",[478,645,594],{}," to skip), ",[478,648,649],{},"encode()"," returns the HTTP request payload.",[652,653,659],"pre",{"className":654,"code":655,"filename":656,"language":657,"meta":658,"style":658},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import {\n  defineHttpDrain,\n  resolveAdapterConfig,\n  type ConfigField,\n} from 'evlog\u002Ftoolkit'\n\ninterface MyServiceConfig {\n  apiKey: string\n  endpoint?: string\n  timeout?: number\n}\n\nconst FIELDS: ConfigField\u003CMyServiceConfig>[] = [\n  { key: 'apiKey', env: ['MYSERVICE_API_KEY'] },\n  { key: 'endpoint', env: ['MYSERVICE_ENDPOINT'] },\n  { key: 'timeout' },\n]\n\nexport function createMyServiceDrain(overrides?: Partial\u003CMyServiceConfig>) {\n  return defineHttpDrain\u003CMyServiceConfig>({\n    name: 'myservice',\n    resolve: async () => {\n      const cfg = await resolveAdapterConfig\u003CMyServiceConfig>('myservice', FIELDS, overrides)\n      if (!cfg.apiKey) {\n        console.error('[evlog\u002Fmyservice] Missing apiKey')\n        return null\n      }\n      return cfg as MyServiceConfig\n    },\n    encode: (events, cfg) => ({\n      url: `${cfg.endpoint ?? 'https:\u002F\u002Fapi.myservice.com'}\u002Fv1\u002Fingest`,\n      headers: {\n        'Content-Type': 'application\u002Fjson',\n        Authorization: `Bearer ${cfg.apiKey}`,\n      },\n      body: JSON.stringify(events),\n    }),\n  })\n}\n","lib\u002Fmy-drain.ts","typescript","",[478,660,661,674,684,692,703,721,728,741,754,765,776,782,787,818,860,894,912,918,923,957,977,994,1013,1057,1082,1104,1113,1119,1133,1139,1165,1202,1212,1234,1262,1268,1292,1302,1310],{"__ignoreMap":658},[662,663,666,670],"span",{"class":664,"line":665},"line",1,[662,667,669],{"class":668},"s7zQu","import",[662,671,673],{"class":672},"sMK4o"," {\n",[662,675,677,681],{"class":664,"line":676},2,[662,678,680],{"class":679},"sTEyZ","  defineHttpDrain",[662,682,683],{"class":672},",\n",[662,685,687,690],{"class":664,"line":686},3,[662,688,689],{"class":679},"  resolveAdapterConfig",[662,691,683],{"class":672},[662,693,695,698,701],{"class":664,"line":694},4,[662,696,697],{"class":668},"  type",[662,699,700],{"class":679}," ConfigField",[662,702,683],{"class":672},[662,704,706,709,712,715,718],{"class":664,"line":705},5,[662,707,708],{"class":672},"}",[662,710,711],{"class":668}," from",[662,713,714],{"class":672}," '",[662,716,508],{"class":717},"sfazB",[662,719,720],{"class":672},"'\n",[662,722,724],{"class":664,"line":723},6,[662,725,727],{"emptyLinePlaceholder":726},true,"\n",[662,729,731,735,739],{"class":664,"line":730},7,[662,732,734],{"class":733},"spNyl","interface",[662,736,738],{"class":737},"sBMFI"," MyServiceConfig",[662,740,673],{"class":672},[662,742,744,748,751],{"class":664,"line":743},8,[662,745,747],{"class":746},"swJcz","  apiKey",[662,749,750],{"class":672},":",[662,752,753],{"class":737}," string\n",[662,755,757,760,763],{"class":664,"line":756},9,[662,758,759],{"class":746},"  endpoint",[662,761,762],{"class":672},"?:",[662,764,753],{"class":737},[662,766,768,771,773],{"class":664,"line":767},10,[662,769,770],{"class":746},"  timeout",[662,772,762],{"class":672},[662,774,775],{"class":737}," number\n",[662,777,779],{"class":664,"line":778},11,[662,780,781],{"class":672},"}\n",[662,783,785],{"class":664,"line":784},12,[662,786,727],{"emptyLinePlaceholder":726},[662,788,790,793,796,798,800,803,806,809,812,815],{"class":664,"line":789},13,[662,791,792],{"class":733},"const",[662,794,795],{"class":679}," FIELDS",[662,797,750],{"class":672},[662,799,700],{"class":737},[662,801,802],{"class":672},"\u003C",[662,804,805],{"class":737},"MyServiceConfig",[662,807,808],{"class":672},">",[662,810,811],{"class":679},"[] ",[662,813,814],{"class":672},"=",[662,816,817],{"class":679}," [\n",[662,819,821,824,827,829,831,833,836,839,842,844,847,849,852,854,857],{"class":664,"line":820},14,[662,822,823],{"class":672},"  {",[662,825,826],{"class":746}," key",[662,828,750],{"class":672},[662,830,714],{"class":672},[662,832,568],{"class":717},[662,834,835],{"class":672},"'",[662,837,838],{"class":672},",",[662,840,841],{"class":746}," env",[662,843,750],{"class":672},[662,845,846],{"class":679}," [",[662,848,835],{"class":672},[662,850,851],{"class":717},"MYSERVICE_API_KEY",[662,853,835],{"class":672},[662,855,856],{"class":679},"] ",[662,858,859],{"class":672},"},\n",[662,861,863,865,867,869,871,873,875,877,879,881,883,885,888,890,892],{"class":664,"line":862},15,[662,864,823],{"class":672},[662,866,826],{"class":746},[662,868,750],{"class":672},[662,870,714],{"class":672},[662,872,572],{"class":717},[662,874,835],{"class":672},[662,876,838],{"class":672},[662,878,841],{"class":746},[662,880,750],{"class":672},[662,882,846],{"class":679},[662,884,835],{"class":672},[662,886,887],{"class":717},"MYSERVICE_ENDPOINT",[662,889,835],{"class":672},[662,891,856],{"class":679},[662,893,859],{"class":672},[662,895,897,899,901,903,905,907,909],{"class":664,"line":896},16,[662,898,823],{"class":672},[662,900,826],{"class":746},[662,902,750],{"class":672},[662,904,714],{"class":672},[662,906,580],{"class":717},[662,908,835],{"class":672},[662,910,911],{"class":672}," },\n",[662,913,915],{"class":664,"line":914},17,[662,916,917],{"class":679},"]\n",[662,919,921],{"class":664,"line":920},18,[662,922,727],{"emptyLinePlaceholder":726},[662,924,926,929,932,936,939,943,945,948,950,952,955],{"class":664,"line":925},19,[662,927,928],{"class":668},"export",[662,930,931],{"class":733}," function",[662,933,935],{"class":934},"s2Zo4"," createMyServiceDrain",[662,937,938],{"class":672},"(",[662,940,942],{"class":941},"sHdIc","overrides",[662,944,762],{"class":672},[662,946,947],{"class":737}," Partial",[662,949,802],{"class":672},[662,951,805],{"class":737},[662,953,954],{"class":672},">)",[662,956,673],{"class":672},[662,958,960,963,966,968,970,972,974],{"class":664,"line":959},20,[662,961,962],{"class":668},"  return",[662,964,965],{"class":934}," defineHttpDrain",[662,967,802],{"class":672},[662,969,805],{"class":737},[662,971,808],{"class":672},[662,973,938],{"class":746},[662,975,976],{"class":672},"{\n",[662,978,980,983,985,987,990,992],{"class":664,"line":979},21,[662,981,982],{"class":746},"    name",[662,984,750],{"class":672},[662,986,714],{"class":672},[662,988,989],{"class":717},"myservice",[662,991,835],{"class":672},[662,993,683],{"class":672},[662,995,997,1000,1002,1005,1008,1011],{"class":664,"line":996},22,[662,998,999],{"class":934},"    resolve",[662,1001,750],{"class":672},[662,1003,1004],{"class":733}," async",[662,1006,1007],{"class":672}," ()",[662,1009,1010],{"class":733}," =>",[662,1012,673],{"class":672},[662,1014,1016,1019,1022,1025,1028,1031,1033,1035,1037,1039,1041,1043,1045,1047,1049,1051,1054],{"class":664,"line":1015},23,[662,1017,1018],{"class":733},"      const",[662,1020,1021],{"class":679}," cfg",[662,1023,1024],{"class":672}," =",[662,1026,1027],{"class":668}," await",[662,1029,1030],{"class":934}," resolveAdapterConfig",[662,1032,802],{"class":672},[662,1034,805],{"class":737},[662,1036,808],{"class":672},[662,1038,938],{"class":746},[662,1040,835],{"class":672},[662,1042,989],{"class":717},[662,1044,835],{"class":672},[662,1046,838],{"class":672},[662,1048,795],{"class":679},[662,1050,838],{"class":672},[662,1052,1053],{"class":679}," overrides",[662,1055,1056],{"class":746},")\n",[662,1058,1060,1063,1066,1069,1072,1075,1077,1080],{"class":664,"line":1059},24,[662,1061,1062],{"class":668},"      if",[662,1064,1065],{"class":746}," (",[662,1067,1068],{"class":672},"!",[662,1070,1071],{"class":679},"cfg",[662,1073,1074],{"class":672},".",[662,1076,568],{"class":679},[662,1078,1079],{"class":746},") ",[662,1081,976],{"class":672},[662,1083,1085,1088,1090,1093,1095,1097,1100,1102],{"class":664,"line":1084},25,[662,1086,1087],{"class":679},"        console",[662,1089,1074],{"class":672},[662,1091,1092],{"class":934},"error",[662,1094,938],{"class":746},[662,1096,835],{"class":672},[662,1098,1099],{"class":717},"[evlog\u002Fmyservice] Missing apiKey",[662,1101,835],{"class":672},[662,1103,1056],{"class":746},[662,1105,1107,1110],{"class":664,"line":1106},26,[662,1108,1109],{"class":668},"        return",[662,1111,1112],{"class":672}," null\n",[662,1114,1116],{"class":664,"line":1115},27,[662,1117,1118],{"class":672},"      }\n",[662,1120,1122,1125,1127,1130],{"class":664,"line":1121},28,[662,1123,1124],{"class":668},"      return",[662,1126,1021],{"class":679},[662,1128,1129],{"class":668}," as",[662,1131,1132],{"class":737}," MyServiceConfig\n",[662,1134,1136],{"class":664,"line":1135},29,[662,1137,1138],{"class":672},"    },\n",[662,1140,1142,1145,1147,1149,1152,1154,1156,1159,1161,1163],{"class":664,"line":1141},30,[662,1143,1144],{"class":934},"    encode",[662,1146,750],{"class":672},[662,1148,1065],{"class":672},[662,1150,1151],{"class":941},"events",[662,1153,838],{"class":672},[662,1155,1021],{"class":941},[662,1157,1158],{"class":672},")",[662,1160,1010],{"class":733},[662,1162,1065],{"class":746},[662,1164,976],{"class":672},[662,1166,1168,1171,1173,1176,1178,1180,1183,1186,1188,1191,1194,1197,1200],{"class":664,"line":1167},31,[662,1169,1170],{"class":746},"      url",[662,1172,750],{"class":672},[662,1174,1175],{"class":672}," `${",[662,1177,1071],{"class":679},[662,1179,1074],{"class":672},[662,1181,1182],{"class":679},"endpoint ",[662,1184,1185],{"class":672},"??",[662,1187,714],{"class":672},[662,1189,1190],{"class":717},"https:\u002F\u002Fapi.myservice.com",[662,1192,1193],{"class":672},"'}",[662,1195,1196],{"class":717},"\u002Fv1\u002Fingest",[662,1198,1199],{"class":672},"`",[662,1201,683],{"class":672},[662,1203,1205,1208,1210],{"class":664,"line":1204},32,[662,1206,1207],{"class":746},"      headers",[662,1209,750],{"class":672},[662,1211,673],{"class":672},[662,1213,1215,1218,1221,1223,1225,1227,1230,1232],{"class":664,"line":1214},33,[662,1216,1217],{"class":672},"        '",[662,1219,1220],{"class":746},"Content-Type",[662,1222,835],{"class":672},[662,1224,750],{"class":672},[662,1226,714],{"class":672},[662,1228,1229],{"class":717},"application\u002Fjson",[662,1231,835],{"class":672},[662,1233,683],{"class":672},[662,1235,1237,1240,1242,1245,1248,1251,1253,1255,1257,1260],{"class":664,"line":1236},34,[662,1238,1239],{"class":746},"        Authorization",[662,1241,750],{"class":672},[662,1243,1244],{"class":672}," `",[662,1246,1247],{"class":717},"Bearer ",[662,1249,1250],{"class":672},"${",[662,1252,1071],{"class":679},[662,1254,1074],{"class":672},[662,1256,568],{"class":679},[662,1258,1259],{"class":672},"}`",[662,1261,683],{"class":672},[662,1263,1265],{"class":664,"line":1264},35,[662,1266,1267],{"class":672},"      },\n",[662,1269,1271,1274,1276,1279,1281,1284,1286,1288,1290],{"class":664,"line":1270},36,[662,1272,1273],{"class":746},"      body",[662,1275,750],{"class":672},[662,1277,1278],{"class":679}," JSON",[662,1280,1074],{"class":672},[662,1282,1283],{"class":934},"stringify",[662,1285,938],{"class":746},[662,1287,1151],{"class":679},[662,1289,1158],{"class":746},[662,1291,683],{"class":672},[662,1293,1295,1298,1300],{"class":664,"line":1294},37,[662,1296,1297],{"class":672},"    }",[662,1299,1158],{"class":746},[662,1301,683],{"class":672},[662,1303,1305,1308],{"class":664,"line":1304},38,[662,1306,1307],{"class":672},"  }",[662,1309,1056],{"class":746},[662,1311,1313],{"class":664,"line":1312},39,[662,1314,781],{"class":672},[436,1316,1317,1318,1320,1321,1324,1325,1328],{},"That's it. ",[478,1319,489],{}," handles batching, retries (default 2), timeouts (default 5000ms), error isolation, and the identity headers (",[478,1322,1323],{},"User-Agent: evlog\u002F\u003Cversion>"," + ",[478,1326,1327],{},"X-Evlog-Source: \u003Cname>","). Your app pipeline keeps running even if your destination is down.",[1330,1331,1333],"h3",{"id":1332},"a-5-minute-example-internal-loki-drain","A 5-minute example — internal Loki drain",[436,1335,1336],{},"A complete working drain in 25 lines, with no external config helper:",[652,1338,1343],{"className":1339,"code":1340,"filename":1341,"language":1342,"meta":658,"style":658},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { defineHttpDrain } from 'evlog\u002Ftoolkit'\n\nexport function createLokiDrain(overrides?: { url?: string, token?: string }) {\n  return defineHttpDrain\u003C{ url: string, token: string }>({\n    name: 'loki',\n    resolve: () => ({\n      url: overrides?.url ?? process.env.LOKI_URL!,\n      token: overrides?.token ?? process.env.LOKI_TOKEN!,\n    }),\n    encode: (events, config) => ({\n      url: `${config.url}\u002Floki\u002Fapi\u002Fv1\u002Fpush`,\n      headers: {\n        'Content-Type': 'application\u002Fjson',\n        Authorization: `Bearer ${config.token}`,\n      },\n      body: JSON.stringify({\n        streams: events.map(e => ({\n          stream: { service: e.service, level: e.level },\n          values: [[String(Date.parse(e.timestamp) * 1e6), JSON.stringify(e)]],\n        })),\n      }),\n    }),\n  })\n}\n","lib\u002Floki-drain.ts","ts",[478,1344,1345,1365,1369,1408,1438,1453,1467,1500,1529,1537,1560,1584,1592,1610,1632,1636,1652,1678,1716,1776,1786,1795,1803,1809],{"__ignoreMap":658},[662,1346,1347,1349,1352,1354,1357,1359,1361,1363],{"class":664,"line":665},[662,1348,669],{"class":668},[662,1350,1351],{"class":672}," {",[662,1353,965],{"class":679},[662,1355,1356],{"class":672}," }",[662,1358,711],{"class":668},[662,1360,714],{"class":672},[662,1362,508],{"class":717},[662,1364,720],{"class":672},[662,1366,1367],{"class":664,"line":676},[662,1368,727],{"emptyLinePlaceholder":726},[662,1370,1371,1373,1375,1378,1380,1382,1384,1386,1389,1391,1394,1396,1399,1401,1403,1406],{"class":664,"line":686},[662,1372,928],{"class":668},[662,1374,931],{"class":733},[662,1376,1377],{"class":934}," createLokiDrain",[662,1379,938],{"class":672},[662,1381,942],{"class":941},[662,1383,762],{"class":672},[662,1385,1351],{"class":672},[662,1387,1388],{"class":746}," url",[662,1390,762],{"class":672},[662,1392,1393],{"class":737}," string",[662,1395,838],{"class":672},[662,1397,1398],{"class":746}," token",[662,1400,762],{"class":672},[662,1402,1393],{"class":737},[662,1404,1405],{"class":672}," })",[662,1407,673],{"class":672},[662,1409,1410,1412,1414,1417,1419,1421,1423,1425,1427,1429,1431,1434,1436],{"class":664,"line":694},[662,1411,962],{"class":668},[662,1413,965],{"class":934},[662,1415,1416],{"class":672},"\u003C{",[662,1418,1388],{"class":746},[662,1420,750],{"class":672},[662,1422,1393],{"class":737},[662,1424,838],{"class":672},[662,1426,1398],{"class":746},[662,1428,750],{"class":672},[662,1430,1393],{"class":737},[662,1432,1433],{"class":672}," }>",[662,1435,938],{"class":746},[662,1437,976],{"class":672},[662,1439,1440,1442,1444,1446,1449,1451],{"class":664,"line":705},[662,1441,982],{"class":746},[662,1443,750],{"class":672},[662,1445,714],{"class":672},[662,1447,1448],{"class":717},"loki",[662,1450,835],{"class":672},[662,1452,683],{"class":672},[662,1454,1455,1457,1459,1461,1463,1465],{"class":664,"line":723},[662,1456,999],{"class":934},[662,1458,750],{"class":672},[662,1460,1007],{"class":672},[662,1462,1010],{"class":733},[662,1464,1065],{"class":746},[662,1466,976],{"class":672},[662,1468,1469,1471,1473,1475,1478,1481,1484,1487,1489,1492,1494,1497],{"class":664,"line":730},[662,1470,1170],{"class":746},[662,1472,750],{"class":672},[662,1474,1053],{"class":679},[662,1476,1477],{"class":672},"?.",[662,1479,1480],{"class":679},"url",[662,1482,1483],{"class":672}," ??",[662,1485,1486],{"class":679}," process",[662,1488,1074],{"class":672},[662,1490,1491],{"class":679},"env",[662,1493,1074],{"class":672},[662,1495,1496],{"class":679},"LOKI_URL",[662,1498,1499],{"class":672},"!,\n",[662,1501,1502,1505,1507,1509,1511,1514,1516,1518,1520,1522,1524,1527],{"class":664,"line":743},[662,1503,1504],{"class":746},"      token",[662,1506,750],{"class":672},[662,1508,1053],{"class":679},[662,1510,1477],{"class":672},[662,1512,1513],{"class":679},"token",[662,1515,1483],{"class":672},[662,1517,1486],{"class":679},[662,1519,1074],{"class":672},[662,1521,1491],{"class":679},[662,1523,1074],{"class":672},[662,1525,1526],{"class":679},"LOKI_TOKEN",[662,1528,1499],{"class":672},[662,1530,1531,1533,1535],{"class":664,"line":756},[662,1532,1297],{"class":672},[662,1534,1158],{"class":746},[662,1536,683],{"class":672},[662,1538,1539,1541,1543,1545,1547,1549,1552,1554,1556,1558],{"class":664,"line":767},[662,1540,1144],{"class":934},[662,1542,750],{"class":672},[662,1544,1065],{"class":672},[662,1546,1151],{"class":941},[662,1548,838],{"class":672},[662,1550,1551],{"class":941}," config",[662,1553,1158],{"class":672},[662,1555,1010],{"class":733},[662,1557,1065],{"class":746},[662,1559,976],{"class":672},[662,1561,1562,1564,1566,1568,1571,1573,1575,1577,1580,1582],{"class":664,"line":778},[662,1563,1170],{"class":746},[662,1565,750],{"class":672},[662,1567,1175],{"class":672},[662,1569,1570],{"class":679},"config",[662,1572,1074],{"class":672},[662,1574,1480],{"class":679},[662,1576,708],{"class":672},[662,1578,1579],{"class":717},"\u002Floki\u002Fapi\u002Fv1\u002Fpush",[662,1581,1199],{"class":672},[662,1583,683],{"class":672},[662,1585,1586,1588,1590],{"class":664,"line":784},[662,1587,1207],{"class":746},[662,1589,750],{"class":672},[662,1591,673],{"class":672},[662,1593,1594,1596,1598,1600,1602,1604,1606,1608],{"class":664,"line":789},[662,1595,1217],{"class":672},[662,1597,1220],{"class":746},[662,1599,835],{"class":672},[662,1601,750],{"class":672},[662,1603,714],{"class":672},[662,1605,1229],{"class":717},[662,1607,835],{"class":672},[662,1609,683],{"class":672},[662,1611,1612,1614,1616,1618,1620,1622,1624,1626,1628,1630],{"class":664,"line":820},[662,1613,1239],{"class":746},[662,1615,750],{"class":672},[662,1617,1244],{"class":672},[662,1619,1247],{"class":717},[662,1621,1250],{"class":672},[662,1623,1570],{"class":679},[662,1625,1074],{"class":672},[662,1627,1513],{"class":679},[662,1629,1259],{"class":672},[662,1631,683],{"class":672},[662,1633,1634],{"class":664,"line":862},[662,1635,1267],{"class":672},[662,1637,1638,1640,1642,1644,1646,1648,1650],{"class":664,"line":896},[662,1639,1273],{"class":746},[662,1641,750],{"class":672},[662,1643,1278],{"class":679},[662,1645,1074],{"class":672},[662,1647,1283],{"class":934},[662,1649,938],{"class":746},[662,1651,976],{"class":672},[662,1653,1654,1657,1659,1662,1664,1667,1669,1672,1674,1676],{"class":664,"line":914},[662,1655,1656],{"class":746},"        streams",[662,1658,750],{"class":672},[662,1660,1661],{"class":679}," events",[662,1663,1074],{"class":672},[662,1665,1666],{"class":934},"map",[662,1668,938],{"class":746},[662,1670,1671],{"class":941},"e",[662,1673,1010],{"class":733},[662,1675,1065],{"class":746},[662,1677,976],{"class":672},[662,1679,1680,1683,1685,1687,1690,1692,1695,1697,1700,1702,1705,1707,1709,1711,1714],{"class":664,"line":920},[662,1681,1682],{"class":746},"          stream",[662,1684,750],{"class":672},[662,1686,1351],{"class":672},[662,1688,1689],{"class":746}," service",[662,1691,750],{"class":672},[662,1693,1694],{"class":679}," e",[662,1696,1074],{"class":672},[662,1698,1699],{"class":679},"service",[662,1701,838],{"class":672},[662,1703,1704],{"class":746}," level",[662,1706,750],{"class":672},[662,1708,1694],{"class":679},[662,1710,1074],{"class":672},[662,1712,1713],{"class":679},"level",[662,1715,911],{"class":672},[662,1717,1718,1721,1723,1726,1729,1731,1734,1736,1739,1741,1743,1745,1748,1750,1753,1757,1759,1761,1763,1765,1767,1769,1771,1774],{"class":664,"line":925},[662,1719,1720],{"class":746},"          values",[662,1722,750],{"class":672},[662,1724,1725],{"class":746}," [[",[662,1727,1728],{"class":934},"String",[662,1730,938],{"class":746},[662,1732,1733],{"class":679},"Date",[662,1735,1074],{"class":672},[662,1737,1738],{"class":934},"parse",[662,1740,938],{"class":746},[662,1742,1671],{"class":679},[662,1744,1074],{"class":672},[662,1746,1747],{"class":679},"timestamp",[662,1749,1079],{"class":746},[662,1751,1752],{"class":672},"*",[662,1754,1756],{"class":1755},"sbssI"," 1e6",[662,1758,1158],{"class":746},[662,1760,838],{"class":672},[662,1762,1278],{"class":679},[662,1764,1074],{"class":672},[662,1766,1283],{"class":934},[662,1768,938],{"class":746},[662,1770,1671],{"class":679},[662,1772,1773],{"class":746},")]]",[662,1775,683],{"class":672},[662,1777,1778,1781,1784],{"class":664,"line":959},[662,1779,1780],{"class":672},"        }",[662,1782,1783],{"class":746},"))",[662,1785,683],{"class":672},[662,1787,1788,1791,1793],{"class":664,"line":979},[662,1789,1790],{"class":672},"      }",[662,1792,1158],{"class":746},[662,1794,683],{"class":672},[662,1796,1797,1799,1801],{"class":664,"line":996},[662,1798,1297],{"class":672},[662,1800,1158],{"class":746},[662,1802,683],{"class":672},[662,1804,1805,1807],{"class":664,"line":1015},[662,1806,1307],{"class":672},[662,1808,1056],{"class":746},[662,1810,1811],{"class":664,"line":1059},[662,1812,781],{"class":672},[632,1814,1816],{"id":1815},"standardized-config-priority","Standardized config priority",[436,1818,1819,1821],{},[478,1820,557],{}," walks the standard chain so users get the same configuration UX as built-in adapters:",[1823,1824,1825,1831,1837,1843,1849],"ol",{},[523,1826,1827,1828,1830],{},"Explicit ",[478,1829,942],{}," passed to your factory",[523,1832,1833,1836],{},[478,1834,1835],{},"runtimeConfig.evlog.\u003Cnamespace>"," (Nuxt\u002FNitro)",[523,1838,1839,1842],{},[478,1840,1841],{},"runtimeConfig.\u003Cnamespace>"," (legacy Nuxt\u002FNitro)",[523,1844,1845,1848],{},[478,1846,1847],{},"NUXT_\u003CNS>_\u003CFIELD>"," env vars",[523,1850,1851,1848],{},[478,1852,1853],{},"\u003CNS>_\u003CFIELD>",[436,1855,1856,1857,577,1859,577,1861,577,1863,1865,1866,1868,1869,1871,1872,1875,1876,1879,1880,1883],{},"Field names should follow the project conventions: ",[478,1858,568],{},[478,1860,572],{},[478,1862,576],{},[478,1864,580],{},". If you're renaming an existing field (e.g. ",[478,1867,1513],{}," → ",[478,1870,568],{},"), keep both as ",[478,1873,1874],{},"ConfigField"," entries for one major version — see ",[478,1877,1878],{},"axiom.ts"," and ",[478,1881,1882],{},"better-stack.ts"," for the deprecation pattern.",[632,1885,1887],{"id":1886},"wiring-the-drain-into-your-framework","Wiring the drain into your framework",[436,1889,1890,1891,1894],{},"Once ",[478,1892,1893],{},"createMyServiceDrain()"," returns the drain, wire it like any other:",[1896,1897,1898,2011,2137,2195,2232,2263],"code-group",{},[652,1899,1902],{"className":654,"code":1900,"filename":1901,"language":657,"meta":658,"style":658},"\u002F\u002F server\u002Fplugins\u002Fevlog-drain.ts\nimport { createMyServiceDrain } from '~\u002Fserver\u002Futils\u002Fmy-drain'\n\nconst drain = createMyServiceDrain()\n\nexport default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook('evlog:drain', drain)\n})\n","Nuxt \u002F Nitro",[478,1903,1904,1910,1929,1933,1947,1951,1974,2005],{"__ignoreMap":658},[662,1905,1906],{"class":664,"line":665},[662,1907,1909],{"class":1908},"sHwdD","\u002F\u002F server\u002Fplugins\u002Fevlog-drain.ts\n",[662,1911,1912,1914,1916,1918,1920,1922,1924,1927],{"class":664,"line":676},[662,1913,669],{"class":668},[662,1915,1351],{"class":672},[662,1917,935],{"class":679},[662,1919,1356],{"class":672},[662,1921,711],{"class":668},[662,1923,714],{"class":672},[662,1925,1926],{"class":717},"~\u002Fserver\u002Futils\u002Fmy-drain",[662,1928,720],{"class":672},[662,1930,1931],{"class":664,"line":686},[662,1932,727],{"emptyLinePlaceholder":726},[662,1934,1935,1937,1940,1942,1944],{"class":664,"line":694},[662,1936,792],{"class":733},[662,1938,1939],{"class":679}," drain ",[662,1941,814],{"class":672},[662,1943,935],{"class":934},[662,1945,1946],{"class":679},"()\n",[662,1948,1949],{"class":664,"line":705},[662,1950,727],{"emptyLinePlaceholder":726},[662,1952,1953,1955,1958,1961,1963,1965,1968,1970,1972],{"class":664,"line":723},[662,1954,928],{"class":668},[662,1956,1957],{"class":668}," default",[662,1959,1960],{"class":934}," defineNitroPlugin",[662,1962,938],{"class":679},[662,1964,938],{"class":672},[662,1966,1967],{"class":941},"nitroApp",[662,1969,1158],{"class":672},[662,1971,1010],{"class":733},[662,1973,673],{"class":672},[662,1975,1976,1979,1981,1984,1986,1989,1991,1993,1996,1998,2000,2003],{"class":664,"line":730},[662,1977,1978],{"class":679},"  nitroApp",[662,1980,1074],{"class":672},[662,1982,1983],{"class":679},"hooks",[662,1985,1074],{"class":672},[662,1987,1988],{"class":934},"hook",[662,1990,938],{"class":746},[662,1992,835],{"class":672},[662,1994,1995],{"class":717},"evlog:drain",[662,1997,835],{"class":672},[662,1999,838],{"class":672},[662,2001,2002],{"class":679}," drain",[662,2004,1056],{"class":746},[662,2006,2007,2009],{"class":664,"line":743},[662,2008,708],{"class":672},[662,2010,1056],{"class":679},[652,2012,2014],{"className":654,"code":2013,"filename":167,"language":657,"meta":658,"style":658},"\u002F\u002F lib\u002Fevlog.ts\nimport { createEvlog } from 'evlog\u002Fnext'\nimport { createMyServiceDrain } from '.\u002Fmy-drain'\n\nexport const { withEvlog, useLogger, log, createError } = createEvlog({\n  service: 'my-app',\n  drain: createMyServiceDrain(),\n})\n",[478,2015,2016,2021,2041,2060,2064,2101,2117,2131],{"__ignoreMap":658},[662,2017,2018],{"class":664,"line":665},[662,2019,2020],{"class":1908},"\u002F\u002F lib\u002Fevlog.ts\n",[662,2022,2023,2025,2027,2030,2032,2034,2036,2039],{"class":664,"line":676},[662,2024,669],{"class":668},[662,2026,1351],{"class":672},[662,2028,2029],{"class":679}," createEvlog",[662,2031,1356],{"class":672},[662,2033,711],{"class":668},[662,2035,714],{"class":672},[662,2037,2038],{"class":717},"evlog\u002Fnext",[662,2040,720],{"class":672},[662,2042,2043,2045,2047,2049,2051,2053,2055,2058],{"class":664,"line":686},[662,2044,669],{"class":668},[662,2046,1351],{"class":672},[662,2048,935],{"class":679},[662,2050,1356],{"class":672},[662,2052,711],{"class":668},[662,2054,714],{"class":672},[662,2056,2057],{"class":717},".\u002Fmy-drain",[662,2059,720],{"class":672},[662,2061,2062],{"class":664,"line":694},[662,2063,727],{"emptyLinePlaceholder":726},[662,2065,2066,2068,2071,2073,2076,2078,2081,2083,2086,2088,2091,2093,2095,2097,2099],{"class":664,"line":705},[662,2067,928],{"class":668},[662,2069,2070],{"class":733}," const",[662,2072,1351],{"class":672},[662,2074,2075],{"class":679}," withEvlog",[662,2077,838],{"class":672},[662,2079,2080],{"class":679}," useLogger",[662,2082,838],{"class":672},[662,2084,2085],{"class":679}," log",[662,2087,838],{"class":672},[662,2089,2090],{"class":679}," createError ",[662,2092,708],{"class":672},[662,2094,1024],{"class":672},[662,2096,2029],{"class":934},[662,2098,938],{"class":679},[662,2100,976],{"class":672},[662,2102,2103,2106,2108,2110,2113,2115],{"class":664,"line":723},[662,2104,2105],{"class":746},"  service",[662,2107,750],{"class":672},[662,2109,714],{"class":672},[662,2111,2112],{"class":717},"my-app",[662,2114,835],{"class":672},[662,2116,683],{"class":672},[662,2118,2119,2122,2124,2126,2129],{"class":664,"line":730},[662,2120,2121],{"class":746},"  drain",[662,2123,750],{"class":672},[662,2125,935],{"class":934},[662,2127,2128],{"class":679},"()",[662,2130,683],{"class":672},[662,2132,2133,2135],{"class":664,"line":743},[662,2134,708],{"class":672},[662,2136,1056],{"class":679},[652,2138,2141],{"className":654,"code":2139,"filename":2140,"language":657,"meta":658,"style":658},"import { createMyServiceDrain } from '.\u002Fmy-drain'\napp.use(evlog({ drain: createMyServiceDrain() }))\n","Hono \u002F Express \u002F Elysia",[478,2142,2143,2161],{"__ignoreMap":658},[662,2144,2145,2147,2149,2151,2153,2155,2157,2159],{"class":664,"line":665},[662,2146,669],{"class":668},[662,2148,1351],{"class":672},[662,2150,935],{"class":679},[662,2152,1356],{"class":672},[662,2154,711],{"class":668},[662,2156,714],{"class":672},[662,2158,2057],{"class":717},[662,2160,720],{"class":672},[662,2162,2163,2166,2168,2171,2173,2176,2178,2181,2183,2185,2187,2190,2192],{"class":664,"line":676},[662,2164,2165],{"class":679},"app",[662,2167,1074],{"class":672},[662,2169,2170],{"class":934},"use",[662,2172,938],{"class":679},[662,2174,2175],{"class":934},"evlog",[662,2177,938],{"class":679},[662,2179,2180],{"class":672},"{",[662,2182,2002],{"class":746},[662,2184,750],{"class":672},[662,2186,935],{"class":934},[662,2188,2189],{"class":679},"() ",[662,2191,708],{"class":672},[662,2193,2194],{"class":679},"))\n",[652,2196,2198],{"className":654,"code":2197,"filename":202,"language":657,"meta":658,"style":658},"await app.register(evlog, { drain: createMyServiceDrain() })\n",[478,2199,2200],{"__ignoreMap":658},[662,2201,2202,2205,2208,2210,2213,2216,2218,2220,2222,2224,2226,2228,2230],{"class":664,"line":665},[662,2203,2204],{"class":668},"await",[662,2206,2207],{"class":679}," app",[662,2209,1074],{"class":672},[662,2211,2212],{"class":934},"register",[662,2214,2215],{"class":679},"(evlog",[662,2217,838],{"class":672},[662,2219,1351],{"class":672},[662,2221,2002],{"class":746},[662,2223,750],{"class":672},[662,2225,935],{"class":934},[662,2227,2189],{"class":679},[662,2229,708],{"class":672},[662,2231,1056],{"class":679},[652,2233,2235],{"className":654,"code":2234,"filename":187,"language":657,"meta":658,"style":658},"EvlogModule.forRoot({ drain: createMyServiceDrain() })\n",[478,2236,2237],{"__ignoreMap":658},[662,2238,2239,2242,2244,2247,2249,2251,2253,2255,2257,2259,2261],{"class":664,"line":665},[662,2240,2241],{"class":679},"EvlogModule",[662,2243,1074],{"class":672},[662,2245,2246],{"class":934},"forRoot",[662,2248,938],{"class":679},[662,2250,2180],{"class":672},[662,2252,2002],{"class":746},[662,2254,750],{"class":672},[662,2256,935],{"class":934},[662,2258,2189],{"class":679},[662,2260,708],{"class":672},[662,2262,1056],{"class":679},[652,2264,2266],{"className":654,"code":2265,"filename":222,"language":657,"meta":658,"style":658},"import { initLogger } from 'evlog'\nimport { createMyServiceDrain } from '.\u002Fmy-drain'\n\ninitLogger({ drain: createMyServiceDrain() })\n",[478,2267,2268,2287,2305,2309],{"__ignoreMap":658},[662,2269,2270,2272,2274,2277,2279,2281,2283,2285],{"class":664,"line":665},[662,2271,669],{"class":668},[662,2273,1351],{"class":672},[662,2275,2276],{"class":679}," initLogger",[662,2278,1356],{"class":672},[662,2280,711],{"class":668},[662,2282,714],{"class":672},[662,2284,2175],{"class":717},[662,2286,720],{"class":672},[662,2288,2289,2291,2293,2295,2297,2299,2301,2303],{"class":664,"line":676},[662,2290,669],{"class":668},[662,2292,1351],{"class":672},[662,2294,935],{"class":679},[662,2296,1356],{"class":672},[662,2298,711],{"class":668},[662,2300,714],{"class":672},[662,2302,2057],{"class":717},[662,2304,720],{"class":672},[662,2306,2307],{"class":664,"line":686},[662,2308,727],{"emptyLinePlaceholder":726},[662,2310,2311,2314,2316,2318,2320,2322,2324,2326,2328],{"class":664,"line":694},[662,2312,2313],{"class":934},"initLogger",[662,2315,938],{"class":679},[662,2317,2180],{"class":672},[662,2319,2002],{"class":746},[662,2321,750],{"class":672},[662,2323,935],{"class":934},[662,2325,2189],{"class":679},[662,2327,708],{"class":672},[662,2329,1056],{"class":679},[436,2331,2332,2333,2337],{},"For production, wrap it once in ",[445,2334,2335],{"href":395},[478,2336,616],{}," so events are batched and retried.",[632,2339,2341],{"id":2340},"filtering-and-transforming-events","Filtering and transforming events",[436,2343,2344,2346,2347,2350,2351,2353],{},[478,2345,649],{}," receives the full batch of ",[478,2348,2349],{},"WideEvent[]"," plus the resolved config. Filter or transform inline — returning ",[478,2352,594],{}," is a clean opt-out for that batch:",[652,2355,2357],{"className":654,"code":2356,"language":657,"meta":658,"style":658},"encode: (events, cfg) => {\n  const filtered = events.filter(e => e.level === 'error' && e.path !== '\u002Fhealth')\n  if (filtered.length === 0) return null\n\n  const payload = filtered.map(e => ({\n    ts: new Date(e.timestamp).getTime(),\n    severity: e.level.toUpperCase(),\n    attributes: { method: e.method, path: e.path, status: e.status, duration: e.duration },\n  }))\n\n  return {\n    url: `${cfg.endpoint}\u002Fv1\u002Fpush`,\n    headers: { 'Content-Type': 'application\u002Fjson' },\n    body: JSON.stringify(payload),\n  }\n}\n",[478,2358,2359,2380,2440,2467,2471,2496,2528,2550,2614,2620,2624,2630,2654,2679,2701,2706],{"__ignoreMap":658},[662,2360,2361,2364,2366,2368,2370,2372,2374,2376,2378],{"class":664,"line":665},[662,2362,2363],{"class":737},"encode",[662,2365,750],{"class":672},[662,2367,1065],{"class":672},[662,2369,1151],{"class":941},[662,2371,838],{"class":672},[662,2373,1021],{"class":941},[662,2375,1158],{"class":672},[662,2377,1010],{"class":733},[662,2379,673],{"class":672},[662,2381,2382,2385,2388,2390,2392,2394,2397,2399,2401,2403,2405,2407,2409,2412,2414,2416,2418,2421,2423,2425,2428,2431,2433,2436,2438],{"class":664,"line":676},[662,2383,2384],{"class":733},"  const",[662,2386,2387],{"class":679}," filtered",[662,2389,1024],{"class":672},[662,2391,1661],{"class":679},[662,2393,1074],{"class":672},[662,2395,2396],{"class":934},"filter",[662,2398,938],{"class":746},[662,2400,1671],{"class":941},[662,2402,1010],{"class":733},[662,2404,1694],{"class":679},[662,2406,1074],{"class":672},[662,2408,1713],{"class":679},[662,2410,2411],{"class":672}," ===",[662,2413,714],{"class":672},[662,2415,1092],{"class":717},[662,2417,835],{"class":672},[662,2419,2420],{"class":672}," &&",[662,2422,1694],{"class":679},[662,2424,1074],{"class":672},[662,2426,2427],{"class":679},"path",[662,2429,2430],{"class":672}," !==",[662,2432,714],{"class":672},[662,2434,2435],{"class":717},"\u002Fhealth",[662,2437,835],{"class":672},[662,2439,1056],{"class":746},[662,2441,2442,2445,2447,2450,2452,2455,2457,2460,2462,2465],{"class":664,"line":686},[662,2443,2444],{"class":668},"  if",[662,2446,1065],{"class":746},[662,2448,2449],{"class":679},"filtered",[662,2451,1074],{"class":672},[662,2453,2454],{"class":679},"length",[662,2456,2411],{"class":672},[662,2458,2459],{"class":1755}," 0",[662,2461,1079],{"class":746},[662,2463,2464],{"class":668},"return",[662,2466,1112],{"class":672},[662,2468,2469],{"class":664,"line":694},[662,2470,727],{"emptyLinePlaceholder":726},[662,2472,2473,2475,2478,2480,2482,2484,2486,2488,2490,2492,2494],{"class":664,"line":705},[662,2474,2384],{"class":733},[662,2476,2477],{"class":679}," payload",[662,2479,1024],{"class":672},[662,2481,2387],{"class":679},[662,2483,1074],{"class":672},[662,2485,1666],{"class":934},[662,2487,938],{"class":746},[662,2489,1671],{"class":941},[662,2491,1010],{"class":733},[662,2493,1065],{"class":746},[662,2495,976],{"class":672},[662,2497,2498,2501,2503,2506,2509,2511,2513,2515,2517,2519,2521,2524,2526],{"class":664,"line":723},[662,2499,2500],{"class":746},"    ts",[662,2502,750],{"class":672},[662,2504,2505],{"class":672}," new",[662,2507,2508],{"class":934}," Date",[662,2510,938],{"class":746},[662,2512,1671],{"class":679},[662,2514,1074],{"class":672},[662,2516,1747],{"class":679},[662,2518,1158],{"class":746},[662,2520,1074],{"class":672},[662,2522,2523],{"class":934},"getTime",[662,2525,2128],{"class":746},[662,2527,683],{"class":672},[662,2529,2530,2533,2535,2537,2539,2541,2543,2546,2548],{"class":664,"line":730},[662,2531,2532],{"class":746},"    severity",[662,2534,750],{"class":672},[662,2536,1694],{"class":679},[662,2538,1074],{"class":672},[662,2540,1713],{"class":679},[662,2542,1074],{"class":672},[662,2544,2545],{"class":934},"toUpperCase",[662,2547,2128],{"class":746},[662,2549,683],{"class":672},[662,2551,2552,2555,2557,2559,2562,2564,2566,2568,2571,2573,2576,2578,2580,2582,2584,2586,2589,2591,2593,2595,2598,2600,2603,2605,2607,2609,2612],{"class":664,"line":743},[662,2553,2554],{"class":746},"    attributes",[662,2556,750],{"class":672},[662,2558,1351],{"class":672},[662,2560,2561],{"class":746}," method",[662,2563,750],{"class":672},[662,2565,1694],{"class":679},[662,2567,1074],{"class":672},[662,2569,2570],{"class":679},"method",[662,2572,838],{"class":672},[662,2574,2575],{"class":746}," path",[662,2577,750],{"class":672},[662,2579,1694],{"class":679},[662,2581,1074],{"class":672},[662,2583,2427],{"class":679},[662,2585,838],{"class":672},[662,2587,2588],{"class":746}," status",[662,2590,750],{"class":672},[662,2592,1694],{"class":679},[662,2594,1074],{"class":672},[662,2596,2597],{"class":679},"status",[662,2599,838],{"class":672},[662,2601,2602],{"class":746}," duration",[662,2604,750],{"class":672},[662,2606,1694],{"class":679},[662,2608,1074],{"class":672},[662,2610,2611],{"class":679},"duration",[662,2613,911],{"class":672},[662,2615,2616,2618],{"class":664,"line":756},[662,2617,1307],{"class":672},[662,2619,2194],{"class":746},[662,2621,2622],{"class":664,"line":767},[662,2623,727],{"emptyLinePlaceholder":726},[662,2625,2626,2628],{"class":664,"line":778},[662,2627,962],{"class":668},[662,2629,673],{"class":672},[662,2631,2632,2635,2637,2639,2641,2643,2645,2647,2650,2652],{"class":664,"line":784},[662,2633,2634],{"class":746},"    url",[662,2636,750],{"class":672},[662,2638,1175],{"class":672},[662,2640,1071],{"class":679},[662,2642,1074],{"class":672},[662,2644,572],{"class":679},[662,2646,708],{"class":672},[662,2648,2649],{"class":717},"\u002Fv1\u002Fpush",[662,2651,1199],{"class":672},[662,2653,683],{"class":672},[662,2655,2656,2659,2661,2663,2665,2667,2669,2671,2673,2675,2677],{"class":664,"line":789},[662,2657,2658],{"class":746},"    headers",[662,2660,750],{"class":672},[662,2662,1351],{"class":672},[662,2664,714],{"class":672},[662,2666,1220],{"class":746},[662,2668,835],{"class":672},[662,2670,750],{"class":672},[662,2672,714],{"class":672},[662,2674,1229],{"class":717},[662,2676,835],{"class":672},[662,2678,911],{"class":672},[662,2680,2681,2684,2686,2688,2690,2692,2694,2697,2699],{"class":664,"line":820},[662,2682,2683],{"class":746},"    body",[662,2685,750],{"class":672},[662,2687,1278],{"class":679},[662,2689,1074],{"class":672},[662,2691,1283],{"class":934},[662,2693,938],{"class":746},[662,2695,2696],{"class":679},"payload",[662,2698,1158],{"class":746},[662,2700,683],{"class":672},[662,2702,2703],{"class":664,"line":862},[662,2704,2705],{"class":672},"  }\n",[662,2707,2708],{"class":664,"line":896},[662,2709,781],{"class":672},[632,2711,2713,2715],{"id":2712},"definedrain-non-http-transports",[478,2714,502],{}," (non-HTTP transports)",[436,2717,2718,2719,2721],{},"If your destination requires gRPC, a vendor SDK, a queue client, a WebSocket, or a raw socket, drop one level lower with ",[478,2720,502],{},". You own the transport; the toolkit still gives you config resolution, error isolation, and a consistent shape.",[652,2723,2725],{"className":654,"code":2724,"language":657,"meta":658,"style":658},"import { defineDrain } from 'evlog\u002Ftoolkit'\n\nexport const createCustomTransportDrain = () =>\n  defineDrain\u003C{ apiKey: string }>({\n    name: 'custom',\n    resolve: async () => ({ apiKey: process.env.MY_KEY! }),\n    send: async (events, cfg) => {\n      await myVendorSdk.publish(events, { token: cfg.apiKey })\n    },\n  })\n",[478,2726,2727,2746,2750,2766,2786,2801,2840,2863,2898,2902],{"__ignoreMap":658},[662,2728,2729,2731,2733,2736,2738,2740,2742,2744],{"class":664,"line":665},[662,2730,669],{"class":668},[662,2732,1351],{"class":672},[662,2734,2735],{"class":679}," defineDrain",[662,2737,1356],{"class":672},[662,2739,711],{"class":668},[662,2741,714],{"class":672},[662,2743,508],{"class":717},[662,2745,720],{"class":672},[662,2747,2748],{"class":664,"line":676},[662,2749,727],{"emptyLinePlaceholder":726},[662,2751,2752,2754,2756,2759,2761,2763],{"class":664,"line":686},[662,2753,928],{"class":668},[662,2755,2070],{"class":733},[662,2757,2758],{"class":679}," createCustomTransportDrain ",[662,2760,814],{"class":672},[662,2762,1007],{"class":672},[662,2764,2765],{"class":733}," =>\n",[662,2767,2768,2771,2773,2776,2778,2780,2782,2784],{"class":664,"line":694},[662,2769,2770],{"class":934},"  defineDrain",[662,2772,1416],{"class":672},[662,2774,2775],{"class":746}," apiKey",[662,2777,750],{"class":672},[662,2779,1393],{"class":737},[662,2781,1433],{"class":672},[662,2783,938],{"class":679},[662,2785,976],{"class":672},[662,2787,2788,2790,2792,2794,2797,2799],{"class":664,"line":705},[662,2789,982],{"class":746},[662,2791,750],{"class":672},[662,2793,714],{"class":672},[662,2795,2796],{"class":717},"custom",[662,2798,835],{"class":672},[662,2800,683],{"class":672},[662,2802,2803,2805,2807,2809,2811,2813,2815,2817,2819,2821,2823,2825,2827,2829,2832,2834,2836,2838],{"class":664,"line":723},[662,2804,999],{"class":934},[662,2806,750],{"class":672},[662,2808,1004],{"class":733},[662,2810,1007],{"class":672},[662,2812,1010],{"class":733},[662,2814,1065],{"class":679},[662,2816,2180],{"class":672},[662,2818,2775],{"class":746},[662,2820,750],{"class":672},[662,2822,1486],{"class":679},[662,2824,1074],{"class":672},[662,2826,1491],{"class":679},[662,2828,1074],{"class":672},[662,2830,2831],{"class":679},"MY_KEY",[662,2833,1068],{"class":672},[662,2835,1356],{"class":672},[662,2837,1158],{"class":679},[662,2839,683],{"class":672},[662,2841,2842,2845,2847,2849,2851,2853,2855,2857,2859,2861],{"class":664,"line":730},[662,2843,2844],{"class":934},"    send",[662,2846,750],{"class":672},[662,2848,1004],{"class":733},[662,2850,1065],{"class":672},[662,2852,1151],{"class":941},[662,2854,838],{"class":672},[662,2856,1021],{"class":941},[662,2858,1158],{"class":672},[662,2860,1010],{"class":733},[662,2862,673],{"class":672},[662,2864,2865,2868,2871,2873,2876,2878,2880,2882,2884,2886,2888,2890,2892,2894,2896],{"class":664,"line":743},[662,2866,2867],{"class":668},"      await",[662,2869,2870],{"class":679}," myVendorSdk",[662,2872,1074],{"class":672},[662,2874,2875],{"class":934},"publish",[662,2877,938],{"class":746},[662,2879,1151],{"class":679},[662,2881,838],{"class":672},[662,2883,1351],{"class":672},[662,2885,1398],{"class":746},[662,2887,750],{"class":672},[662,2889,1021],{"class":679},[662,2891,1074],{"class":672},[662,2893,568],{"class":679},[662,2895,1356],{"class":672},[662,2897,1056],{"class":746},[662,2899,2900],{"class":664,"line":756},[662,2901,1138],{"class":672},[662,2903,2904,2906],{"class":664,"line":767},[662,2905,1307],{"class":672},[662,2907,1056],{"class":679},[436,2909,2910,2911,2913,2914,2916,2917,2920,2921,2924],{},"When you fall back to ",[478,2912,502],{},", follow the same rules manually that ",[478,2915,489],{}," enforces: wrap the transport in ",[478,2918,2919],{},"try\u002Fcatch",", log with ",[478,2922,2923],{},"console.error('[evlog\u002F\u003Cname>] …')",", and never re-throw.",[632,2926,2928],{"id":2927},"draincontext-reference","DrainContext reference",[436,2930,2931,2932,2934,2935,2938],{},"When evlog calls your drain through ",[478,2933,1995],{},", it passes a ",[478,2936,2937],{},"DrainContext"," per event:",[652,2940,2943],{"className":654,"code":2941,"filename":2942,"language":657,"meta":658,"style":658},"interface DrainContext {\n  \u002F** The complete wide event with all accumulated context *\u002F\n  event: WideEvent\n\n  \u002F** Request metadata *\u002F\n  request?: {\n    method: string\n    path: string\n    requestId: string\n  }\n\n  \u002F** Safe HTTP headers (sensitive headers filtered) *\u002F\n  headers?: Record\u003Cstring, string>\n}\n\ninterface WideEvent {\n  timestamp: string\n  level: 'debug' | 'info' | 'warn' | 'error'\n  service: string\n  environment?: string\n  version?: string\n  region?: string\n  commitHash?: string\n  requestId?: string\n  \u002F\u002F ... plus all fields added via log.set()\n  [key: string]: unknown\n}\n","types.ts",[478,2944,2945,2954,2959,2969,2973,2978,2987,2996,3005,3014,3018,3022,3027,3049,3053,3057,3066,3075,3116,3124,3133,3142,3151,3160,3169,3174,3194],{"__ignoreMap":658},[662,2946,2947,2949,2952],{"class":664,"line":665},[662,2948,734],{"class":733},[662,2950,2951],{"class":737}," DrainContext",[662,2953,673],{"class":672},[662,2955,2956],{"class":664,"line":676},[662,2957,2958],{"class":1908},"  \u002F** The complete wide event with all accumulated context *\u002F\n",[662,2960,2961,2964,2966],{"class":664,"line":686},[662,2962,2963],{"class":746},"  event",[662,2965,750],{"class":672},[662,2967,2968],{"class":737}," WideEvent\n",[662,2970,2971],{"class":664,"line":694},[662,2972,727],{"emptyLinePlaceholder":726},[662,2974,2975],{"class":664,"line":705},[662,2976,2977],{"class":1908},"  \u002F** Request metadata *\u002F\n",[662,2979,2980,2983,2985],{"class":664,"line":723},[662,2981,2982],{"class":746},"  request",[662,2984,762],{"class":672},[662,2986,673],{"class":672},[662,2988,2989,2992,2994],{"class":664,"line":730},[662,2990,2991],{"class":746},"    method",[662,2993,750],{"class":672},[662,2995,753],{"class":737},[662,2997,2998,3001,3003],{"class":664,"line":743},[662,2999,3000],{"class":746},"    path",[662,3002,750],{"class":672},[662,3004,753],{"class":737},[662,3006,3007,3010,3012],{"class":664,"line":756},[662,3008,3009],{"class":746},"    requestId",[662,3011,750],{"class":672},[662,3013,753],{"class":737},[662,3015,3016],{"class":664,"line":767},[662,3017,2705],{"class":672},[662,3019,3020],{"class":664,"line":778},[662,3021,727],{"emptyLinePlaceholder":726},[662,3023,3024],{"class":664,"line":784},[662,3025,3026],{"class":1908},"  \u002F** Safe HTTP headers (sensitive headers filtered) *\u002F\n",[662,3028,3029,3032,3034,3037,3039,3042,3044,3046],{"class":664,"line":789},[662,3030,3031],{"class":746},"  headers",[662,3033,762],{"class":672},[662,3035,3036],{"class":737}," Record",[662,3038,802],{"class":672},[662,3040,3041],{"class":737},"string",[662,3043,838],{"class":672},[662,3045,1393],{"class":737},[662,3047,3048],{"class":672},">\n",[662,3050,3051],{"class":664,"line":820},[662,3052,781],{"class":672},[662,3054,3055],{"class":664,"line":862},[662,3056,727],{"emptyLinePlaceholder":726},[662,3058,3059,3061,3064],{"class":664,"line":896},[662,3060,734],{"class":733},[662,3062,3063],{"class":737}," WideEvent",[662,3065,673],{"class":672},[662,3067,3068,3071,3073],{"class":664,"line":914},[662,3069,3070],{"class":746},"  timestamp",[662,3072,750],{"class":672},[662,3074,753],{"class":737},[662,3076,3077,3080,3082,3084,3087,3089,3092,3094,3097,3099,3101,3103,3106,3108,3110,3112,3114],{"class":664,"line":920},[662,3078,3079],{"class":746},"  level",[662,3081,750],{"class":672},[662,3083,714],{"class":672},[662,3085,3086],{"class":717},"debug",[662,3088,835],{"class":672},[662,3090,3091],{"class":672}," |",[662,3093,714],{"class":672},[662,3095,3096],{"class":717},"info",[662,3098,835],{"class":672},[662,3100,3091],{"class":672},[662,3102,714],{"class":672},[662,3104,3105],{"class":717},"warn",[662,3107,835],{"class":672},[662,3109,3091],{"class":672},[662,3111,714],{"class":672},[662,3113,1092],{"class":717},[662,3115,720],{"class":672},[662,3117,3118,3120,3122],{"class":664,"line":925},[662,3119,2105],{"class":746},[662,3121,750],{"class":672},[662,3123,753],{"class":737},[662,3125,3126,3129,3131],{"class":664,"line":959},[662,3127,3128],{"class":746},"  environment",[662,3130,762],{"class":672},[662,3132,753],{"class":737},[662,3134,3135,3138,3140],{"class":664,"line":979},[662,3136,3137],{"class":746},"  version",[662,3139,762],{"class":672},[662,3141,753],{"class":737},[662,3143,3144,3147,3149],{"class":664,"line":996},[662,3145,3146],{"class":746},"  region",[662,3148,762],{"class":672},[662,3150,753],{"class":737},[662,3152,3153,3156,3158],{"class":664,"line":1015},[662,3154,3155],{"class":746},"  commitHash",[662,3157,762],{"class":672},[662,3159,753],{"class":737},[662,3161,3162,3165,3167],{"class":664,"line":1059},[662,3163,3164],{"class":746},"  requestId",[662,3166,762],{"class":672},[662,3168,753],{"class":737},[662,3170,3171],{"class":664,"line":1084},[662,3172,3173],{"class":1908},"  \u002F\u002F ... plus all fields added via log.set()\n",[662,3175,3176,3179,3182,3184,3186,3189,3191],{"class":664,"line":1106},[662,3177,3178],{"class":679},"  [",[662,3180,3181],{"class":941},"key",[662,3183,750],{"class":672},[662,3185,1393],{"class":737},[662,3187,3188],{"class":679},"]",[662,3190,750],{"class":672},[662,3192,3193],{"class":737}," unknown\n",[662,3195,3196],{"class":664,"line":1115},[662,3197,781],{"class":672},[436,3199,3200,3201,3203,3204,3207,3208,3210,3211,3214],{},"In the batched form your ",[478,3202,649],{}," \u002F ",[478,3205,3206],{},"send()"," receives, you get ",[478,3209,2349],{}," directly (the toolkit unwraps ",[478,3212,3213],{},"event"," from each context).",[632,3216,3218],{"id":3217},"toolkit-helpers","Toolkit helpers",[436,3220,3221,3223],{},[478,3222,508],{}," exposes the same helpers every built-in adapter uses. The ones relevant to drains:",[453,3225,3226,3236],{},[456,3227,3228],{},[459,3229,3230,3233],{},[462,3231,3232],{},"Export",[462,3234,3235],{},"Purpose",[469,3237,3238,3248,3258,3270,3280,3293,3303,3317],{},[459,3239,3240,3245],{},[474,3241,3242],{},[478,3243,3244],{},"defineHttpDrain(spec)",[474,3246,3247],{},"The HTTP recipe — auto retries, timeouts, identity headers, error isolation",[459,3249,3250,3255],{},[474,3251,3252],{},[478,3253,3254],{},"defineDrain(spec)",[474,3256,3257],{},"Same contract for non-HTTP transports",[459,3259,3260,3265],{},[474,3261,3262],{},[478,3263,3264],{},"resolveAdapterConfig(ns, fields, overrides)",[474,3266,3267,3268,562],{},"Standard config priority chain (overrides → ",[478,3269,561],{},[459,3271,3272,3277],{},[474,3273,3274],{},[478,3275,3276],{},"httpPost(opts)",[474,3278,3279],{},"The retried POST helper used by every built-in HTTP adapter — handles timeout, retries, redacted error messages",[459,3281,3282,3287],{},[474,3283,3284],{},[478,3285,3286],{},"composeDrains(drains)",[474,3288,3289,3290,1158],{},"Combine multiple drains into one (errors isolated, runs concurrently with ",[478,3291,3292],{},"Promise.allSettled",[459,3294,3295,3300],{},[474,3296,3297],{},[478,3298,3299],{},"toTypedAttributeValue(value)",[474,3301,3302],{},"Convert any value to the typed attribute shape used by Axiom \u002F Sentry",[459,3304,3305,3310],{},[474,3306,3307],{},[478,3308,3309],{},"toOtlpAttributeValue(value)",[474,3311,3312,3313,3316],{},"Convert any value to the OTLP ",[478,3314,3315],{},"AnyValue"," shape (used by OTLP \u002F HyperDX \u002F PostHog logs)",[459,3318,3319,3327],{},[474,3320,3321,577,3324],{},[478,3322,3323],{},"OTEL_SEVERITY_NUMBER",[478,3325,3326],{},"OTEL_SEVERITY_TEXT",[474,3328,3329],{},"OTEL log severity tables",[632,3331,384],{"id":3332},"identity-headers",[436,3334,3335,3337],{},[478,3336,489],{}," automatically tags every request with two headers so receivers can identify the traffic:",[453,3339,3340,3350],{},[456,3341,3342],{},[459,3343,3344,3347],{},[462,3345,3346],{},"Header",[462,3348,3349],{},"Value",[469,3351,3352,3365],{},[459,3353,3354,3359],{},[474,3355,3356],{},[478,3357,3358],{},"User-Agent",[474,3360,3361,3364],{},[478,3362,3363],{},"evlog\u002F\u003Cversion>"," (Node \u002F server runtimes only — browsers strip this header)",[459,3366,3367,3372],{},[474,3368,3369],{},[478,3370,3371],{},"X-Evlog-Source",[474,3373,3374,3375,3378],{},"The drain ",[478,3376,3377],{},"name"," you provided",[436,3380,3381,3382,3385,3386,1074],{},"If you build a drain on top of ",[478,3383,3384],{},"httpPost"," directly, you can override or suppress them — see ",[445,3387,384],{"href":385},[632,3389,3391],{"id":3390},"error-handling-already-done-for-you","Error handling — already done for you",[436,3393,3394,3396],{},[478,3395,489],{}," enforces every best practice automatically:",[1823,3398,3399,3409,3419,3427],{},[523,3400,3401,3404,3405,3408],{},[440,3402,3403],{},"Never throws"," — failures are caught and logged with the ",[478,3406,3407],{},"[evlog\u002F\u003Cname>]"," prefix.",[523,3410,3411,3414,3415,3418],{},[440,3412,3413],{},"Retries"," — defaults to 2 attempts on transient errors (configurable via ",[478,3416,3417],{},"retries",").",[523,3420,3421,3424,3425,3418],{},[440,3422,3423],{},"Timeouts"," — defaults to 5000ms (configurable via ",[478,3426,580],{},[523,3428,3429,3432,3433,3435,3436,3438],{},[440,3430,3431],{},"Graceful degradation"," — ",[478,3434,553],{}," returning ",[478,3437,594],{}," makes the drain a no-op.",[436,3440,3441,3442,3444],{},"If you fall back to ",[478,3443,502],{},", follow the same rules manually.",[632,3446,3448],{"id":3447},"publishing-as-a-community-package","Publishing as a community package",[436,3450,3451],{},"Recommended structure for a community drain:",[652,3453,3458],{"className":3454,"code":3456,"language":3457,"meta":658},[3455],"language-text","my-evlog-drain\u002F\n├─ src\u002F\n│  ├─ drain.ts        # createMyDrain via defineHttpDrain\n│  └─ index.ts        # re-exports\n├─ test\u002F              # vitest, mock fetch\n├─ package.json       # peerDependency: \"evlog\"\n└─ README.md\n","text",[478,3459,3456],{"__ignoreMap":658},[436,3461,3462,3463,3465,3466,3469,3470,3473],{},"Add ",[478,3464,2175],{}," as a ",[478,3467,3468],{},"peerDependency"," (not a ",[478,3471,3472],{},"dependency",") — your package shouldn't pull in a copy of evlog at install time.",[3475,3476,3479,3480,3485],"callout",{"color":3477,"icon":3478},"neutral","i-lucide-heart","Built something great? ",[445,3481,3484],{"href":3482,"rel":3483},"https:\u002F\u002Fgithub.com\u002Fhugorcd\u002Fevlog\u002Fpulls",[625],"Open a PR"," to add a row to the Adapters table — the community will thank you.",[632,3487,3489],{"id":3488},"next-steps","Next steps",[520,3491,3492,3498,3506,3512,3518],{},[523,3493,3494,3497],{},[445,3495,3496],{"href":395},"Drain Pipeline"," — wrap your drain in batch + retry + fanout for production",[523,3499,3500,3503,3504],{},[445,3501,3502],{"href":95},"Adapters Overview"," — see how the built-in adapters use ",[478,3505,489],{},[523,3507,3508,3511],{},[445,3509,3510],{"href":377},"Custom Enrichers"," — same toolkit shape for derived event fields",[523,3513,3514,3517],{},[445,3515,3516],{"href":359},"Custom Framework Integration"," — same toolkit shape for HTTP frameworks",[523,3519,3520,3522],{},[445,3521,417],{"href":418}," — security and production tips",[3524,3525,3526],"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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html .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 .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":658,"searchDepth":676,"depth":676,"links":3528},[3529,3533,3534,3535,3536,3538,3539,3540,3541,3542,3543],{"id":634,"depth":676,"text":3530,"children":3531},"defineHttpDrain (the HTTP recipe)",[3532],{"id":1332,"depth":686,"text":1333},{"id":1815,"depth":676,"text":1816},{"id":1886,"depth":676,"text":1887},{"id":2340,"depth":676,"text":2341},{"id":2712,"depth":676,"text":3537},"defineDrain (non-HTTP transports)",{"id":2927,"depth":676,"text":2928},{"id":3217,"depth":676,"text":3218},{"id":3332,"depth":676,"text":384},{"id":3390,"depth":676,"text":3391},{"id":3447,"depth":676,"text":3448},{"id":3488,"depth":676,"text":3489},"Build a drain for any backend without a built-in adapter — defineHttpDrain for HTTP destinations, defineDrain for any other transport. Standardized config resolution, retries, timeouts, and identity headers handled for you.","md",[3547,3549,3551],{"label":3496,"icon":397,"to":395,"color":3477,"variant":3548},"subtle",{"label":3502,"icon":3550,"to":95,"color":3477,"variant":3548},"i-custom-plug",{"label":417,"icon":308,"to":418,"color":3477,"variant":3548},{},{"title":389,"icon":392},{"title":431,"description":3544},"LS9jVdPQXcB5-cwN6Z-lOIv8uLJCxtiwqW7pdH-BjEI",[3557,3559],{"title":384,"path":385,"stem":386,"description":3558,"icon":387,"children":-1},"Every drain request sent by evlog is tagged with User-Agent and X-Evlog-Source headers so receivers can identify and triage the traffic. Override or suppress them when your custom drain needs different identity.",{"title":394,"path":395,"stem":396,"description":3560,"icon":397,"children":-1},"Batch events, retry on failure, fan out to multiple destinations, and ship browser logs to your server. The shared pipeline that wraps every drain in production.",1778440099419]