[{"data":1,"prerenderedAt":1700},["ShallowReactive",2],{"navigation_docs":3,"-adapters-self-hosted-nuxthub":392,"-adapters-self-hosted-nuxthub-surround":1695},[4,35,159,201,289,376],{"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},"Adapters","\u002Fadapters","6.adapters",[294,297,337,352],{"title":41,"path":295,"stem":296,"icon":44},"\u002Fadapters\u002Foverview","6.adapters\u002F01.overview",{"title":298,"path":299,"stem":300,"children":301,"page":34},"Cloud destinations","\u002Fadapters\u002Fcloud","6.adapters\u002F02.cloud",[302,307,312,317,322,327,332],{"title":303,"path":304,"stem":305,"icon":306},"Axiom","\u002Fadapters\u002Fcloud\u002Faxiom","6.adapters\u002F02.cloud\u002F01.axiom","i-custom-axiom",{"title":308,"path":309,"stem":310,"icon":311},"OTLP","\u002Fadapters\u002Fcloud\u002Fotlp","6.adapters\u002F02.cloud\u002F02.otlp","i-simple-icons-opentelemetry",{"title":313,"path":314,"stem":315,"icon":316},"PostHog","\u002Fadapters\u002Fcloud\u002Fposthog","6.adapters\u002F02.cloud\u002F03.posthog","i-simple-icons-posthog",{"title":318,"path":319,"stem":320,"icon":321},"Sentry","\u002Fadapters\u002Fcloud\u002Fsentry","6.adapters\u002F02.cloud\u002F04.sentry","i-simple-icons-sentry",{"title":323,"path":324,"stem":325,"icon":326},"Better Stack","\u002Fadapters\u002Fcloud\u002Fbetter-stack","6.adapters\u002F02.cloud\u002F05.better-stack","i-simple-icons-betterstack",{"title":328,"path":329,"stem":330,"icon":331},"Datadog","\u002Fadapters\u002Fcloud\u002Fdatadog","6.adapters\u002F02.cloud\u002F06.datadog","i-simple-icons-datadog",{"title":333,"path":334,"stem":335,"icon":336},"HyperDX","\u002Fadapters\u002Fcloud\u002Fhyperdx","6.adapters\u002F02.cloud\u002F07.hyperdx","i-custom-hyperdx",{"title":338,"path":339,"stem":340,"children":341,"page":34},"Self-hosted","\u002Fadapters\u002Fself-hosted","6.adapters\u002F03.self-hosted",[342,347],{"title":343,"path":344,"stem":345,"icon":346},"File System","\u002Fadapters\u002Fself-hosted\u002Ffs","6.adapters\u002F03.self-hosted\u002F01.fs","i-lucide-hard-drive",{"title":348,"path":349,"stem":350,"icon":351},"NuxtHub","\u002Fadapters\u002Fself-hosted\u002Fnuxthub","6.adapters\u002F03.self-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":353,"path":354,"stem":355,"children":356,"page":34},"Building blocks","\u002Fadapters\u002Fbuilding-blocks","6.adapters\u002F04.building-blocks",[357,362,367,371],{"title":358,"path":359,"stem":360,"icon":361},"Pipeline","\u002Fadapters\u002Fbuilding-blocks\u002Fpipeline","6.adapters\u002F04.building-blocks\u002F01.pipeline","i-lucide-workflow",{"title":363,"path":364,"stem":365,"icon":366},"HTTP","\u002Fadapters\u002Fbuilding-blocks\u002Fhttp","6.adapters\u002F04.building-blocks\u002F02.http","i-lucide-globe",{"title":368,"path":369,"stem":370,"icon":83},"Custom Adapters","\u002Fadapters\u002Fbuilding-blocks\u002Fcustom","6.adapters\u002F04.building-blocks\u002F03.custom",{"title":372,"path":373,"stem":374,"icon":375},"Toolkit","\u002Fadapters\u002Fbuilding-blocks\u002Ftoolkit","6.adapters\u002F04.building-blocks\u002F04.toolkit","i-lucide-blocks",{"title":377,"path":378,"stem":379,"children":380,"page":34},"Enrichers","\u002Fenrichers","7.enrichers",[381,384,388],{"title":41,"path":382,"stem":383,"icon":28},"\u002Fenrichers\u002Foverview","7.enrichers\u002F1.overview",{"title":385,"path":386,"stem":387,"icon":288},"Built-in","\u002Fenrichers\u002Fbuilt-in","7.enrichers\u002F2.built-in",{"title":389,"path":390,"stem":391,"icon":83},"Custom","\u002Fenrichers\u002Fcustom","7.enrichers\u002F3.custom",{"id":393,"title":394,"body":395,"description":1681,"extension":1682,"links":1683,"meta":1691,"navigation":1692,"path":349,"seo":1693,"stem":350,"__hash__":1694},"docs\u002F6.adapters\u002F03.self-hosted\u002F02.nuxthub.md","NuxtHub Storage",{"type":396,"value":397,"toc":1663},"minimark",[398,406,453,458,461,488,493,497,577,584,607,611,617,731,744,747,777,792,796,804,814,819,829,1048,1065,1069,1072,1090,1097,1101,1109,1212,1216,1221,1224,1229,1311,1314,1377,1381,1388,1458,1467,1471,1474,1487,1494,1523,1526,1530,1541,1626,1632,1636,1643,1647,1659],[399,400,401,405],"p",{},[402,403,404],"code",{},"@evlog\u002Fnuxthub"," stores your evlog wide events directly in your NuxtHub database. No external logging service needed. Your logs live next to your data, with automatic cleanup based on a retention policy.",[407,408,411,414,439],"prompt",{":actions":409,"description":410,"icon":351},"[\"copy\",\"cursor\",\"windsurf\"]","Store evlog wide events in NuxtHub",[399,412,413],{},"Store evlog wide events in my NuxtHub database (self-hosted log retention).",[415,416,417,421,424,427,430,433,436],"ul",{},[418,419,420],"li",{},"Install both modules: pnpm add @nuxthub\u002Fcore @evlog\u002Fnuxthub",[418,422,423],{},"Add @nuxthub\u002Fcore and @evlog\u002Fnuxthub to nuxt.config.ts modules (in that order)",[418,425,426],{},"Enable hub.database = true in nuxt.config.ts",[418,428,429],{},"Configure evlog.nuxthub: { retentionDays, batchSize, ... } for retention and batching",[418,431,432],{},"Run database migrations so the wide-events table is created",[418,434,435],{},"Confirm wide events are written to my NuxtHub database after triggering a request",[418,437,438],{},"For production at scale, combine with an external drain (Axiom \u002F OTLP) for long-term storage",[399,440,441,442,448,449],{},"Docs: ",[443,444,445],"a",{"href":445,"rel":446},"https:\u002F\u002Fwww.evlog.dev\u002Fadapters\u002Fself-hosted\u002Fnuxthub",[447],"nofollow","\nNuxtHub: ",[443,450,451],{"href":451,"rel":452},"https:\u002F\u002Fhub.nuxt.com",[447],[454,455,457],"h2",{"id":456},"why-self-hosted-logs","Why Self-Hosted Logs?",[399,459,460],{},"External logging services (Axiom, Datadog, etc.) are great for production at scale. But sometimes you want:",[415,462,463,470,476,482],{},[418,464,465,469],{},[466,467,468],"strong",{},"Zero external dependencies"," - logs stored in the same database as your app",[418,471,472,475],{},[466,473,474],{},"Full data ownership"," - no third-party access to your log data",[418,477,478,481],{},[466,479,480],{},"Free tier friendly"," - no per-event pricing, just your existing database",[418,483,484,487],{},[466,485,486],{},"Development & staging"," - full log visibility without paying for a service",[399,489,490,492],{},[402,491,404],{}," works as a drop-in drain. Your existing evlog setup stays the same, you just get a database-backed storage layer on top.",[454,494,496],{"id":495},"install","Install",[498,499,500,528,544,560],"code-group",{},[501,502,508],"pre",{"className":503,"code":504,"filename":505,"language":506,"meta":507,"style":507},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","pnpm","bash","",[402,509,510],{"__ignoreMap":507},[511,512,515,518,522,525],"span",{"class":513,"line":514},"line",1,[511,516,505],{"class":517},"sBMFI",[511,519,521],{"class":520},"sfazB"," add",[511,523,524],{"class":520}," @nuxthub\u002Fcore",[511,526,527],{"class":520}," @evlog\u002Fnuxthub\n",[501,529,532],{"className":503,"code":530,"filename":531,"language":506,"meta":507,"style":507},"bun add @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","bun",[402,533,534],{"__ignoreMap":507},[511,535,536,538,540,542],{"class":513,"line":514},[511,537,531],{"class":517},[511,539,521],{"class":520},[511,541,524],{"class":520},[511,543,527],{"class":520},[501,545,548],{"className":503,"code":546,"filename":547,"language":506,"meta":507,"style":507},"yarn add @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","yarn",[402,549,550],{"__ignoreMap":507},[511,551,552,554,556,558],{"class":513,"line":514},[511,553,547],{"class":517},[511,555,521],{"class":520},[511,557,524],{"class":520},[511,559,527],{"class":520},[501,561,564],{"className":503,"code":562,"filename":563,"language":506,"meta":507,"style":507},"npm install @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","npm",[402,565,566],{"__ignoreMap":507},[511,567,568,570,573,575],{"class":513,"line":514},[511,569,563],{"class":517},[511,571,572],{"class":520}," install",[511,574,524],{"class":520},[511,576,527],{"class":520},[399,578,579,580,583],{},"Or with ",[402,581,582],{},"nuxi",":",[501,585,588],{"className":503,"code":586,"filename":587,"language":506,"meta":507,"style":507},"npx nuxi module add @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","Terminal",[402,589,590],{"__ignoreMap":507},[511,591,592,595,598,601,603,605],{"class":513,"line":514},[511,593,594],{"class":517},"npx",[511,596,597],{"class":520}," nuxi",[511,599,600],{"class":520}," module",[511,602,521],{"class":520},[511,604,524],{"class":520},[511,606,527],{"class":520},[454,608,610],{"id":609},"setup","Setup",[399,612,613,614,583],{},"Add the module to your ",[402,615,616],{},"nuxt.config.ts",[501,618,622],{"className":619,"code":620,"filename":616,"language":621,"meta":507,"style":507},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: ['@nuxthub\u002Fcore', '@evlog\u002Fnuxthub'],\n\n  evlog: {\n    retention: '7d',\n  },\n})\n","typescript",[402,623,624,645,681,688,699,716,722],{"__ignoreMap":507},[511,625,626,630,633,637,641],{"class":513,"line":514},[511,627,629],{"class":628},"s7zQu","export",[511,631,632],{"class":628}," default",[511,634,636],{"class":635},"s2Zo4"," defineNuxtConfig",[511,638,640],{"class":639},"sTEyZ","(",[511,642,644],{"class":643},"sMK4o","{\n",[511,646,648,652,654,657,660,663,665,668,671,673,675,678],{"class":513,"line":647},2,[511,649,651],{"class":650},"swJcz","  modules",[511,653,583],{"class":643},[511,655,656],{"class":639}," [",[511,658,659],{"class":643},"'",[511,661,662],{"class":520},"@nuxthub\u002Fcore",[511,664,659],{"class":643},[511,666,667],{"class":643},",",[511,669,670],{"class":643}," '",[511,672,404],{"class":520},[511,674,659],{"class":643},[511,676,677],{"class":639},"]",[511,679,680],{"class":643},",\n",[511,682,684],{"class":513,"line":683},3,[511,685,687],{"emptyLinePlaceholder":686},true,"\n",[511,689,691,694,696],{"class":513,"line":690},4,[511,692,693],{"class":650},"  evlog",[511,695,583],{"class":643},[511,697,698],{"class":643}," {\n",[511,700,702,705,707,709,712,714],{"class":513,"line":701},5,[511,703,704],{"class":650},"    retention",[511,706,583],{"class":643},[511,708,670],{"class":643},[511,710,711],{"class":520},"7d",[511,713,659],{"class":643},[511,715,680],{"class":643},[511,717,719],{"class":513,"line":718},6,[511,720,721],{"class":643},"  },\n",[511,723,725,728],{"class":513,"line":724},7,[511,726,727],{"class":643},"}",[511,729,730],{"class":639},")\n",[399,732,733,734,736,737,739,740,743],{},"Even if ",[402,735,404],{}," can auto-register missing modules, we recommend explicitly installing ",[402,738,662],{}," and registering it in ",[402,741,742],{},"modules"," for a clearer and more predictable setup.",[399,745,746],{},"That's it. The module automatically:",[748,749,750,760,767,774],"ol",{},[418,751,752,753,756,757,759],{},"Installs ",[402,754,755],{},"evlog\u002Fnuxt"," and ",[402,758,662],{}," if not already registered",[418,761,762,763,766],{},"Registers the ",[402,764,765],{},"evlog_events"," database schema with NuxtHub",[418,768,769,770,773],{},"Hooks into ",[402,771,772],{},"evlog:drain"," to store every event in the database",[418,775,776],{},"Schedules a cleanup task based on your retention policy",[778,779,781,784,785,788,789,791],"callout",{"color":780,"icon":13},"info",[466,782,783],{},"Prerequisites:"," Your project must use ",[443,786,348],{"href":451,"rel":787},[447]," with a database configured. ",[402,790,404],{}," uses Drizzle ORM to interact with the database.",[454,793,795],{"id":794},"how-it-works","How It Works",[501,797,802],{"className":798,"code":800,"language":801},[799],"language-text","Request → evlog wide event → evlog:drain hook → INSERT into evlog_events table\n                                                          ↓\n                          Cron task (automatic) → DELETE events older than retention\n","text",[402,803,800],{"__ignoreMap":507},[399,805,806,807,809,810,813],{},"Every wide event emitted by evlog is stored as a row in the ",[402,808,765],{}," table. The drain plugin handles both single events and batches (when used with the ",[443,811,812],{"href":359},"pipeline",").",[815,816,818],"h3",{"id":817},"database-schema","Database Schema",[399,820,821,822,824,825,828],{},"The ",[402,823,765],{}," table stores indexed columns for fast querying and a ",[402,826,827],{},"data"," JSON column for all remaining fields:",[830,831,832,848],"table",{},[833,834,835],"thead",{},[836,837,838,842,845],"tr",{},[839,840,841],"th",{},"Column",[839,843,844],{},"Type",[839,846,847],{},"Description",[849,850,851,866,880,894,908,922,936,950,965,979,993,1007,1021,1034],"tbody",{},[836,852,853,859,863],{},[854,855,856],"td",{},[402,857,858],{},"id",[854,860,861],{},[402,862,801],{},[854,864,865],{},"UUID primary key",[836,867,868,873,877],{},[854,869,870],{},[402,871,872],{},"timestamp",[854,874,875],{},[402,876,801],{},[854,878,879],{},"Event timestamp",[836,881,882,887,891],{},[854,883,884],{},[402,885,886],{},"level",[854,888,889],{},[402,890,801],{},[854,892,893],{},"Log level (info, warn, error, debug)",[836,895,896,901,905],{},[854,897,898],{},[402,899,900],{},"service",[854,902,903],{},[402,904,801],{},[854,906,907],{},"Service name",[836,909,910,915,919],{},[854,911,912],{},[402,913,914],{},"environment",[854,916,917],{},[402,918,801],{},[854,920,921],{},"Environment (production, staging, etc.)",[836,923,924,929,933],{},[854,925,926],{},[402,927,928],{},"method",[854,930,931],{},[402,932,801],{},[854,934,935],{},"HTTP method",[836,937,938,943,947],{},[854,939,940],{},[402,941,942],{},"path",[854,944,945],{},[402,946,801],{},[854,948,949],{},"Request path",[836,951,952,957,962],{},[854,953,954],{},[402,955,956],{},"status",[854,958,959],{},[402,960,961],{},"integer",[854,963,964],{},"HTTP status code",[836,966,967,972,976],{},[854,968,969],{},[402,970,971],{},"duration_ms",[854,973,974],{},[402,975,961],{},[854,977,978],{},"Request duration in milliseconds",[836,980,981,986,990],{},[854,982,983],{},[402,984,985],{},"request_id",[854,987,988],{},[402,989,801],{},[854,991,992],{},"Request correlation ID",[836,994,995,1000,1004],{},[854,996,997],{},[402,998,999],{},"source",[854,1001,1002],{},[402,1003,801],{},[854,1005,1006],{},"Event source (server, client)",[836,1008,1009,1014,1018],{},[854,1010,1011],{},[402,1012,1013],{},"error",[854,1015,1016],{},[402,1017,801],{},[854,1019,1020],{},"Error details (JSON string)",[836,1022,1023,1027,1031],{},[854,1024,1025],{},[402,1026,827],{},[854,1028,1029],{},[402,1030,801],{},[854,1032,1033],{},"All remaining event fields (JSON)",[836,1035,1036,1041,1045],{},[854,1037,1038],{},[402,1039,1040],{},"created_at",[854,1042,1043],{},[402,1044,801],{},[854,1046,1047],{},"Row insertion timestamp",[399,1049,1050,1051,1053,1054,1053,1056,1053,1058,1053,1060,1053,1062,1064],{},"Indexed columns: ",[402,1052,872],{},", ",[402,1055,886],{},[402,1057,900],{},[402,1059,956],{},[402,1061,985],{},[402,1063,1040],{},".",[815,1066,1068],{"id":1067},"dialect-support","Dialect Support",[399,1070,1071],{},"The schema is automatically registered for your NuxtHub database dialect:",[415,1073,1074,1080,1085],{},[418,1075,1076,1079],{},[466,1077,1078],{},"SQLite"," (default for Cloudflare D1)",[418,1081,1082],{},[466,1083,1084],{},"MySQL",[418,1086,1087],{},[466,1088,1089],{},"PostgreSQL",[399,1091,1092,1093,1096],{},"The correct schema is selected via the ",[402,1094,1095],{},"hub:db:schema:extend"," hook based on your NuxtHub configuration.",[454,1098,1100],{"id":1099},"combining-with-external-adapters","Combining with External Adapters",[399,1102,1103,1105,1106,1108],{},[402,1104,404],{}," doesn't replace external adapters, you can use both. The module registers its own ",[402,1107,772],{}," hook, so any other drain plugins you have will still work:",[501,1110,1113],{"className":619,"code":1111,"filename":1112,"language":621,"meta":507,"style":507},"import { createAxiomDrain } from 'evlog\u002Faxiom'\n\nexport default defineNitroPlugin((nitroApp) => {\n  \u002F\u002F This runs alongside @evlog\u002Fnuxthub's built-in drain\n  nitroApp.hooks.hook('evlog:drain', createAxiomDrain())\n})\n","server\u002Fplugins\u002Fevlog-drain.ts",[402,1114,1115,1140,1144,1170,1176,1206],{"__ignoreMap":507},[511,1116,1117,1120,1123,1126,1129,1132,1134,1137],{"class":513,"line":514},[511,1118,1119],{"class":628},"import",[511,1121,1122],{"class":643}," {",[511,1124,1125],{"class":639}," createAxiomDrain",[511,1127,1128],{"class":643}," }",[511,1130,1131],{"class":628}," from",[511,1133,670],{"class":643},[511,1135,1136],{"class":520},"evlog\u002Faxiom",[511,1138,1139],{"class":643},"'\n",[511,1141,1142],{"class":513,"line":647},[511,1143,687],{"emptyLinePlaceholder":686},[511,1145,1146,1148,1150,1153,1155,1157,1161,1164,1168],{"class":513,"line":683},[511,1147,629],{"class":628},[511,1149,632],{"class":628},[511,1151,1152],{"class":635}," defineNitroPlugin",[511,1154,640],{"class":639},[511,1156,640],{"class":643},[511,1158,1160],{"class":1159},"sHdIc","nitroApp",[511,1162,1163],{"class":643},")",[511,1165,1167],{"class":1166},"spNyl"," =>",[511,1169,698],{"class":643},[511,1171,1172],{"class":513,"line":690},[511,1173,1175],{"class":1174},"sHwdD","  \u002F\u002F This runs alongside @evlog\u002Fnuxthub's built-in drain\n",[511,1177,1178,1181,1183,1186,1188,1191,1193,1195,1197,1199,1201,1203],{"class":513,"line":701},[511,1179,1180],{"class":639},"  nitroApp",[511,1182,1064],{"class":643},[511,1184,1185],{"class":639},"hooks",[511,1187,1064],{"class":643},[511,1189,1190],{"class":635},"hook",[511,1192,640],{"class":650},[511,1194,659],{"class":643},[511,1196,772],{"class":520},[511,1198,659],{"class":643},[511,1200,667],{"class":643},[511,1202,1125],{"class":635},[511,1204,1205],{"class":650},"())\n",[511,1207,1208,1210],{"class":513,"line":718},[511,1209,727],{"class":643},[511,1211,730],{"class":639},[454,1213,1215],{"id":1214},"retention","Retention",[399,1217,1218,1220],{},[402,1219,404],{}," automatically deletes old events based on your retention policy. No manual cleanup needed.",[815,1222,170],{"id":1223},"configuration",[399,1225,1226,1227,583],{},"Set the retention period in your ",[402,1228,616],{},[501,1230,1232],{"className":619,"code":1231,"filename":616,"language":621,"meta":507,"style":507},"export default defineNuxtConfig({\n  modules: ['@nuxthub\u002Fcore', '@evlog\u002Fnuxthub'],\n\n  evlog: {\n    retention: '7d', \u002F\u002F default\n  },\n})\n",[402,1233,1234,1246,1272,1276,1284,1301,1305],{"__ignoreMap":507},[511,1235,1236,1238,1240,1242,1244],{"class":513,"line":514},[511,1237,629],{"class":628},[511,1239,632],{"class":628},[511,1241,636],{"class":635},[511,1243,640],{"class":639},[511,1245,644],{"class":643},[511,1247,1248,1250,1252,1254,1256,1258,1260,1262,1264,1266,1268,1270],{"class":513,"line":647},[511,1249,651],{"class":650},[511,1251,583],{"class":643},[511,1253,656],{"class":639},[511,1255,659],{"class":643},[511,1257,662],{"class":520},[511,1259,659],{"class":643},[511,1261,667],{"class":643},[511,1263,670],{"class":643},[511,1265,404],{"class":520},[511,1267,659],{"class":643},[511,1269,677],{"class":639},[511,1271,680],{"class":643},[511,1273,1274],{"class":513,"line":683},[511,1275,687],{"emptyLinePlaceholder":686},[511,1277,1278,1280,1282],{"class":513,"line":690},[511,1279,693],{"class":650},[511,1281,583],{"class":643},[511,1283,698],{"class":643},[511,1285,1286,1288,1290,1292,1294,1296,1298],{"class":513,"line":701},[511,1287,704],{"class":650},[511,1289,583],{"class":643},[511,1291,670],{"class":643},[511,1293,711],{"class":520},[511,1295,659],{"class":643},[511,1297,667],{"class":643},[511,1299,1300],{"class":1174}," \u002F\u002F default\n",[511,1302,1303],{"class":513,"line":718},[511,1304,721],{"class":643},[511,1306,1307,1309],{"class":513,"line":724},[511,1308,727],{"class":643},[511,1310,730],{"class":639},[399,1312,1313],{},"The retention value is a number followed by a unit:",[830,1315,1316,1328],{},[833,1317,1318],{},[836,1319,1320,1323,1325],{},[839,1321,1322],{},"Unit",[839,1324,847],{},[839,1326,1327],{},"Example",[849,1329,1330,1345,1361],{},[836,1331,1332,1337,1340],{},[854,1333,1334],{},[402,1335,1336],{},"d",[854,1338,1339],{},"Days",[854,1341,1342,1344],{},[402,1343,711],{}," = 7 days",[836,1346,1347,1352,1355],{},[854,1348,1349],{},[402,1350,1351],{},"h",[854,1353,1354],{},"Hours",[854,1356,1357,1360],{},[402,1358,1359],{},"24h"," = 24 hours",[836,1362,1363,1368,1371],{},[854,1364,1365],{},[402,1366,1367],{},"m",[854,1369,1370],{},"Minutes",[854,1372,1373,1376],{},[402,1374,1375],{},"60m"," = 60 minutes",[815,1378,1380],{"id":1379},"how-cleanup-works","How Cleanup Works",[399,1382,1383,1384,1387],{},"The module registers a Nitro scheduled task (",[402,1385,1386],{},"evlog:cleanup",") that runs on a cron schedule derived from your retention value. The cron frequency is set to roughly half the retention period:",[830,1389,1390,1401],{},[833,1391,1392],{},[836,1393,1394,1396,1399],{},[839,1395,1215],{},[839,1397,1398],{},"Cron Schedule",[839,1400,847],{},[849,1402,1403,1417,1431,1445],{},[836,1404,1405,1409,1414],{},[854,1406,1407],{},[402,1408,1375],{},[854,1410,1411],{},[402,1412,1413],{},"*\u002F30 * * * *",[854,1415,1416],{},"Every 30 minutes",[836,1418,1419,1423,1428],{},[854,1420,1421],{},[402,1422,1359],{},[854,1424,1425],{},[402,1426,1427],{},"0 *\u002F12 * * *",[854,1429,1430],{},"Every 12 hours",[836,1432,1433,1437,1442],{},[854,1434,1435],{},[402,1436,711],{},[854,1438,1439],{},[402,1440,1441],{},"0 3 * * *",[854,1443,1444],{},"Daily at 3:00 AM",[836,1446,1447,1452,1456],{},[854,1448,1449],{},[402,1450,1451],{},"30d",[854,1453,1454],{},[402,1455,1441],{},[854,1457,1444],{},[399,1459,1460,1461,1463,1464,1466],{},"The cleanup task deletes all rows in ",[402,1462,765],{}," where ",[402,1465,1040],{}," is older than the retention period.",[815,1468,1470],{"id":1469},"manual-cleanup","Manual Cleanup",[399,1472,1473],{},"You can trigger cleanup manually via the API endpoint:",[501,1475,1477],{"className":503,"code":1476,"filename":587,"language":506,"meta":507,"style":507},"curl https:\u002F\u002Fyour-app.com\u002Fapi\u002F_cron\u002Fevlog-cleanup\n",[402,1478,1479],{"__ignoreMap":507},[511,1480,1481,1484],{"class":513,"line":514},[511,1482,1483],{"class":517},"curl",[511,1485,1486],{"class":520}," https:\u002F\u002Fyour-app.com\u002Fapi\u002F_cron\u002Fevlog-cleanup\n",[399,1488,1489,1490,1493],{},"If the ",[402,1491,1492],{},"CRON_SECRET"," environment variable is set, the endpoint requires a Bearer token:",[501,1495,1497],{"className":503,"code":1496,"filename":587,"language":506,"meta":507,"style":507},"curl -H \"Authorization: Bearer your-secret\" \\\n  https:\u002F\u002Fyour-app.com\u002Fapi\u002F_cron\u002Fevlog-cleanup\n",[402,1498,1499,1518],{"__ignoreMap":507},[511,1500,1501,1503,1506,1509,1512,1515],{"class":513,"line":514},[511,1502,1483],{"class":517},[511,1504,1505],{"class":520}," -H",[511,1507,1508],{"class":643}," \"",[511,1510,1511],{"class":520},"Authorization: Bearer your-secret",[511,1513,1514],{"class":643},"\"",[511,1516,1517],{"class":639}," \\\n",[511,1519,1520],{"class":513,"line":647},[511,1521,1522],{"class":520},"  https:\u002F\u002Fyour-app.com\u002Fapi\u002F_cron\u002Fevlog-cleanup\n",[399,1524,1525],{},"This is recommended for production deployments to prevent unauthorized cleanup triggers.",[815,1527,1529],{"id":1528},"vercel-cron","Vercel Cron",[399,1531,1532,1533,1536,1537,1540],{},"When installing the module with ",[402,1534,1535],{},"nuxi module add",", you'll be prompted to create a ",[402,1538,1539],{},"vercel.json"," with the appropriate cron schedule:",[501,1542,1546],{"className":1543,"code":1544,"filename":1539,"language":1545,"meta":507,"style":507},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"crons\": [\n    {\n      \"path\": \"\u002Fapi\u002F_cron\u002Fevlog-cleanup\",\n      \"schedule\": \"0 3 * * *\"\n    }\n  ]\n}\n","json",[402,1547,1548,1552,1567,1572,1592,1610,1615,1620],{"__ignoreMap":507},[511,1549,1550],{"class":513,"line":514},[511,1551,644],{"class":643},[511,1553,1554,1557,1560,1562,1564],{"class":513,"line":647},[511,1555,1556],{"class":643},"  \"",[511,1558,1559],{"class":1166},"crons",[511,1561,1514],{"class":643},[511,1563,583],{"class":643},[511,1565,1566],{"class":643}," [\n",[511,1568,1569],{"class":513,"line":683},[511,1570,1571],{"class":643},"    {\n",[511,1573,1574,1577,1579,1581,1583,1585,1588,1590],{"class":513,"line":690},[511,1575,1576],{"class":643},"      \"",[511,1578,942],{"class":517},[511,1580,1514],{"class":643},[511,1582,583],{"class":643},[511,1584,1508],{"class":643},[511,1586,1587],{"class":520},"\u002Fapi\u002F_cron\u002Fevlog-cleanup",[511,1589,1514],{"class":643},[511,1591,680],{"class":643},[511,1593,1594,1596,1599,1601,1603,1605,1607],{"class":513,"line":701},[511,1595,1576],{"class":643},[511,1597,1598],{"class":517},"schedule",[511,1600,1514],{"class":643},[511,1602,583],{"class":643},[511,1604,1508],{"class":643},[511,1606,1441],{"class":520},[511,1608,1609],{"class":643},"\"\n",[511,1611,1612],{"class":513,"line":718},[511,1613,1614],{"class":643},"    }\n",[511,1616,1617],{"class":513,"line":724},[511,1618,1619],{"class":643},"  ]\n",[511,1621,1623],{"class":513,"line":1622},8,[511,1624,1625],{"class":643},"}\n",[399,1627,1628,1629,1631],{},"On Vercel, the ",[402,1630,1492],{}," environment variable is automatically set and validated.",[815,1633,1635],{"id":1634},"cloudflare-other-platforms","Cloudflare & Other Platforms",[399,1637,1638,1639,1642],{},"On Cloudflare Workers and other platforms, the Nitro scheduled task handles cleanup automatically without any additional cron configuration. The task is registered with ",[402,1640,1641],{},"experimental.tasks"," enabled in the Nitro config.",[454,1644,1646],{"id":1645},"next-steps","Next Steps",[415,1648,1649,1654],{},[418,1650,1651,1653],{},[443,1652,290],{"href":295}," - Send logs to external services alongside NuxtHub storage",[418,1655,1656,1658],{},[443,1657,358],{"href":359}," - Batch events for better database performance",[1660,1661,1662],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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":507,"searchDepth":647,"depth":647,"links":1664},[1665,1666,1667,1668,1672,1673,1680],{"id":456,"depth":647,"text":457},{"id":495,"depth":647,"text":496},{"id":609,"depth":647,"text":610},{"id":794,"depth":647,"text":795,"children":1669},[1670,1671],{"id":817,"depth":683,"text":818},{"id":1067,"depth":683,"text":1068},{"id":1099,"depth":647,"text":1100},{"id":1214,"depth":647,"text":1215,"children":1674},[1675,1676,1677,1678,1679],{"id":1223,"depth":683,"text":170},{"id":1379,"depth":683,"text":1380},{"id":1469,"depth":683,"text":1470},{"id":1528,"depth":683,"text":1529},{"id":1634,"depth":683,"text":1635},{"id":1645,"depth":647,"text":1646},"Self-hosted log retention for evlog using NuxtHub database storage. Store, query, and automatically clean up your structured logs with zero external dependencies.","md",[1684,1689],{"label":348,"icon":1685,"to":451,"target":1686,"color":1687,"variant":1688},"i-lucide-external-link","_blank","neutral","subtle",{"label":290,"icon":1690,"to":295,"color":1687,"variant":1688},"i-custom-plug",{},{"title":348,"icon":351},{"title":394,"description":1681},"7IAyh9YhgeYDG6zRJWByEW2QvSef3_48EfOsdchlpRY",[1696,1698],{"title":343,"path":344,"stem":345,"description":1697,"icon":346,"children":-1},"Write wide events to the local file system as NDJSON for local debugging, AI agent integration, and production backup.",{"title":358,"path":359,"stem":360,"description":1699,"icon":361,"children":-1},"Batch events, retry on failure, and protect against buffer overflow with the shared drain pipeline. Supports fan-out to multiple adapters.",1778106403884]