[{"data":1,"prerenderedAt":1715},["ShallowReactive",2],{"navigation_docs":3,"-adapters-self-hosted-nuxthub":407,"-adapters-self-hosted-nuxthub-surround":1710},[4,35,159,201,289,304,391],{"title":5,"path":6,"stem":7,"children":8,"page":34},"Getting Started","\u002Fgetting-started","1.getting-started",[9,14,19,24,29],{"title":10,"path":11,"stem":12,"icon":13},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-info",{"title":15,"path":16,"stem":17,"icon":18},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":20,"path":21,"stem":22,"icon":23},"Quick Start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-zap",{"title":25,"path":26,"stem":27,"icon":28},"Agent Skills","\u002Fgetting-started\u002Fagent-skills","1.getting-started\u002F4.agent-skills","i-lucide-sparkles",{"title":30,"path":31,"stem":32,"icon":33},"vs Other Loggers","\u002Fgetting-started\u002Fvs-other-loggers","1.getting-started\u002F5.vs-other-loggers","i-lucide-scale",false,{"title":36,"path":37,"stem":38,"children":39,"page":34},"Logging","\u002Flogging","2.logging",[40,45,50,55,60,65,70,99,127],{"title":41,"path":42,"stem":43,"icon":44},"Overview","\u002Flogging\u002Foverview","2.logging\u002F0.overview","i-lucide-list",{"title":46,"path":47,"stem":48,"icon":49},"Simple Logging","\u002Flogging\u002Fsimple-logging","2.logging\u002F1.simple-logging","i-lucide-terminal",{"title":51,"path":52,"stem":53,"icon":54},"Wide Events","\u002Flogging\u002Fwide-events","2.logging\u002F2.wide-events","i-lucide-layers",{"title":56,"path":57,"stem":58,"icon":59},"Structured Errors","\u002Flogging\u002Fstructured-errors","2.logging\u002F3.structured-errors","i-lucide-shield-alert",{"title":61,"path":62,"stem":63,"icon":64},"Catalogs","\u002Flogging\u002Fcatalogs","2.logging\u002F4.catalogs","i-lucide-book-open",{"title":66,"path":67,"stem":68,"icon":69},"Client Logging","\u002Flogging\u002Fclient-logging","2.logging\u002F5.client-logging","i-lucide-monitor",{"title":71,"icon":72,"path":73,"stem":74,"children":75,"page":34},"AI SDK","i-simple-icons-vercel","\u002Flogging\u002Fai-sdk","2.logging\u002F6.ai-sdk",[76,79,84,89,94],{"title":41,"path":77,"stem":78,"icon":44},"\u002Flogging\u002Fai-sdk\u002Foverview","2.logging\u002F6.ai-sdk\u002F01.overview",{"title":80,"path":81,"stem":82,"icon":83},"Usage","\u002Flogging\u002Fai-sdk\u002Fusage","2.logging\u002F6.ai-sdk\u002F02.usage","i-lucide-code",{"title":85,"path":86,"stem":87,"icon":88},"Options","\u002Flogging\u002Fai-sdk\u002Foptions","2.logging\u002F6.ai-sdk\u002F03.options","i-lucide-sliders",{"title":90,"path":91,"stem":92,"icon":93},"Metadata","\u002Flogging\u002Fai-sdk\u002Fmetadata","2.logging\u002F6.ai-sdk\u002F04.metadata","i-lucide-database",{"title":95,"path":96,"stem":97,"icon":98},"Telemetry","\u002Flogging\u002Fai-sdk\u002Ftelemetry","2.logging\u002F6.ai-sdk\u002F05.telemetry","i-lucide-activity",{"title":100,"icon":101,"path":102,"stem":103,"children":104,"page":34},"Better Auth","i-simple-icons-betterauth","\u002Flogging\u002Fbetter-auth","2.logging\u002F7.better-auth",[105,108,113,118,122],{"title":41,"path":106,"stem":107,"icon":44},"\u002Flogging\u002Fbetter-auth\u002Foverview","2.logging\u002F7.better-auth\u002F01.overview",{"title":109,"path":110,"stem":111,"icon":112},"Identify User","\u002Flogging\u002Fbetter-auth\u002Fidentify-user","2.logging\u002F7.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":114,"path":115,"stem":116,"icon":117},"Middleware","\u002Flogging\u002Fbetter-auth\u002Fmiddleware","2.logging\u002F7.better-auth\u002F03.middleware","i-lucide-shield",{"title":119,"path":120,"stem":121,"icon":69},"Client Sync","\u002Flogging\u002Fbetter-auth\u002Fclient-sync","2.logging\u002F7.better-auth\u002F04.client-sync",{"title":123,"path":124,"stem":125,"icon":126},"Performance","\u002Flogging\u002Fbetter-auth\u002Fperformance","2.logging\u002F7.better-auth\u002F05.performance","i-lucide-gauge",{"title":128,"icon":129,"path":130,"stem":131,"children":132,"page":34},"Audit Logs","i-lucide-shield-check","\u002Flogging\u002Faudit","2.logging\u002F8.audit",[133,136,141,146,151,155],{"title":41,"path":134,"stem":135,"icon":44},"\u002Flogging\u002Faudit\u002Foverview","2.logging\u002F8.audit\u002F01.overview",{"title":137,"path":138,"stem":139,"icon":140},"Schema","\u002Flogging\u002Faudit\u002Fschema","2.logging\u002F8.audit\u002F02.schema","i-lucide-file-text",{"title":142,"path":143,"stem":144,"icon":145},"Recording","\u002Flogging\u002Faudit\u002Frecording","2.logging\u002F8.audit\u002F03.recording","i-lucide-pen-line",{"title":147,"path":148,"stem":149,"icon":150},"Drains","\u002Flogging\u002Faudit\u002Fpipeline","2.logging\u002F8.audit\u002F04.pipeline","i-lucide-link",{"title":152,"path":153,"stem":154,"icon":129},"Compliance","\u002Flogging\u002Faudit\u002Fcompliance","2.logging\u002F8.audit\u002F05.compliance",{"title":156,"path":157,"stem":158,"icon":64},"Recipes","\u002Flogging\u002Faudit\u002Frecipes","2.logging\u002F8.audit\u002F06.recipes",{"title":160,"path":161,"stem":162,"children":163,"page":34},"Core Concepts","\u002Fcore-concepts","3.core-concepts",[164,169,174,179,184,188,191,196],{"title":165,"path":166,"stem":167,"icon":168},"Lifecycle","\u002Fcore-concepts\u002Flifecycle","3.core-concepts\u002F0.lifecycle","i-lucide-arrow-right-left",{"title":170,"path":171,"stem":172,"icon":173},"Configuration","\u002Fcore-concepts\u002Fconfiguration","3.core-concepts\u002F1.configuration","i-lucide-settings",{"title":175,"path":176,"stem":177,"icon":178},"Sampling","\u002Fcore-concepts\u002Fsampling","3.core-concepts\u002F2.sampling","i-lucide-filter",{"title":180,"path":181,"stem":182,"icon":183},"Typed Fields","\u002Fcore-concepts\u002Ftyped-fields","3.core-concepts\u002F3.typed-fields","i-simple-icons-typescript",{"title":185,"path":186,"stem":187,"icon":129},"Best Practices","\u002Fcore-concepts\u002Fbest-practices","3.core-concepts\u002F4.best-practices",{"title":123,"path":189,"stem":190,"icon":126},"\u002Fcore-concepts\u002Fperformance","3.core-concepts\u002F5.performance",{"title":192,"path":193,"stem":194,"icon":195},"Vite Plugin","\u002Fcore-concepts\u002Fvite-plugin","3.core-concepts\u002F6.vite-plugin","i-custom-vite",{"title":197,"path":198,"stem":199,"icon":200},"Auto-Redaction","\u002Fcore-concepts\u002Fredaction","3.core-concepts\u002F7.redaction","i-lucide-eye-off",{"title":202,"path":203,"stem":204,"children":205,"page":34},"Frameworks","\u002Fframeworks","4.frameworks",[206,210,215,220,225,230,235,240,245,250,255,260,265,270,274,279,284],{"title":41,"path":207,"stem":208,"icon":209},"\u002Fframeworks\u002Foverview","4.frameworks\u002F00.overview","i-lucide-layout-grid",{"title":211,"path":212,"stem":213,"icon":214},"Nuxt","\u002Fframeworks\u002Fnuxt","4.frameworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":216,"path":217,"stem":218,"icon":219},"Next.js","\u002Fframeworks\u002Fnextjs","4.frameworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":221,"path":222,"stem":223,"icon":224},"SvelteKit","\u002Fframeworks\u002Fsveltekit","4.frameworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":226,"path":227,"stem":228,"icon":229},"Nitro","\u002Fframeworks\u002Fnitro","4.frameworks\u002F04.nitro","i-custom-nitro",{"title":231,"path":232,"stem":233,"icon":234},"TanStack Start","\u002Fframeworks\u002Ftanstack-start","4.frameworks\u002F05.tanstack-start","i-custom-tanstack",{"title":236,"path":237,"stem":238,"icon":239},"NestJS","\u002Fframeworks\u002Fnestjs","4.frameworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":241,"path":242,"stem":243,"icon":244},"Express","\u002Fframeworks\u002Fexpress","4.frameworks\u002F07.express","i-simple-icons-express",{"title":246,"path":247,"stem":248,"icon":249},"Hono","\u002Fframeworks\u002Fhono","4.frameworks\u002F08.hono","i-simple-icons-hono",{"title":251,"path":252,"stem":253,"icon":254},"Fastify","\u002Fframeworks\u002Ffastify","4.frameworks\u002F09.fastify","i-simple-icons-fastify",{"title":256,"path":257,"stem":258,"icon":259},"Elysia","\u002Fframeworks\u002Felysia","4.frameworks\u002F10.elysia","i-custom-elysia",{"title":261,"path":262,"stem":263,"icon":264},"React Router","\u002Fframeworks\u002Freact-router","4.frameworks\u002F11.react-router","i-custom-reactrouter",{"title":266,"path":267,"stem":268,"icon":269},"Cloudflare Workers","\u002Fframeworks\u002Fcloudflare-workers","4.frameworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":271,"path":272,"stem":273,"icon":183},"Standalone","\u002Fframeworks\u002Fstandalone","4.frameworks\u002F13.standalone",{"title":275,"path":276,"stem":277,"icon":278},"Astro","\u002Fframeworks\u002Fastro","4.frameworks\u002F14.astro","i-simple-icons-astro",{"title":280,"path":281,"stem":282,"icon":283},"AWS Lambda","\u002Fframeworks\u002Faws-lambda","4.frameworks\u002F16.aws-lambda","i-custom-lambda",{"title":285,"path":286,"stem":287,"icon":288},"Custom Integration","\u002Fframeworks\u002Fcustom-integration","4.frameworks\u002F17.custom-integration","i-lucide-puzzle",{"title":290,"path":291,"stem":292,"children":293,"page":34},"Build on top","\u002Fbuild-on-top","5.build-on-top",[294,299],{"title":295,"path":296,"stem":297,"icon":298},"Identity headers","\u002Fbuild-on-top\u002Fidentity-headers","5.build-on-top\u002F1.identity-headers","i-lucide-fingerprint",{"title":300,"path":301,"stem":302,"icon":303},"FS reader","\u002Fbuild-on-top\u002Ffs-reader","5.build-on-top\u002F4.fs-reader","i-lucide-folder-search",{"title":305,"path":306,"stem":307,"children":308,"page":34},"Adapters","\u002Fadapters","6.adapters",[309,312,352,367],{"title":41,"path":310,"stem":311,"icon":44},"\u002Fadapters\u002Foverview","6.adapters\u002F01.overview",{"title":313,"path":314,"stem":315,"children":316,"page":34},"Cloud destinations","\u002Fadapters\u002Fcloud","6.adapters\u002F02.cloud",[317,322,327,332,337,342,347],{"title":318,"path":319,"stem":320,"icon":321},"Axiom","\u002Fadapters\u002Fcloud\u002Faxiom","6.adapters\u002F02.cloud\u002F01.axiom","i-custom-axiom",{"title":323,"path":324,"stem":325,"icon":326},"OTLP","\u002Fadapters\u002Fcloud\u002Fotlp","6.adapters\u002F02.cloud\u002F02.otlp","i-simple-icons-opentelemetry",{"title":328,"path":329,"stem":330,"icon":331},"PostHog","\u002Fadapters\u002Fcloud\u002Fposthog","6.adapters\u002F02.cloud\u002F03.posthog","i-simple-icons-posthog",{"title":333,"path":334,"stem":335,"icon":336},"Sentry","\u002Fadapters\u002Fcloud\u002Fsentry","6.adapters\u002F02.cloud\u002F04.sentry","i-simple-icons-sentry",{"title":338,"path":339,"stem":340,"icon":341},"Better Stack","\u002Fadapters\u002Fcloud\u002Fbetter-stack","6.adapters\u002F02.cloud\u002F05.better-stack","i-simple-icons-betterstack",{"title":343,"path":344,"stem":345,"icon":346},"Datadog","\u002Fadapters\u002Fcloud\u002Fdatadog","6.adapters\u002F02.cloud\u002F06.datadog","i-simple-icons-datadog",{"title":348,"path":349,"stem":350,"icon":351},"HyperDX","\u002Fadapters\u002Fcloud\u002Fhyperdx","6.adapters\u002F02.cloud\u002F07.hyperdx","i-custom-hyperdx",{"title":353,"path":354,"stem":355,"children":356,"page":34},"Self-hosted","\u002Fadapters\u002Fself-hosted","6.adapters\u002F03.self-hosted",[357,362],{"title":358,"path":359,"stem":360,"icon":361},"File System","\u002Fadapters\u002Fself-hosted\u002Ffs","6.adapters\u002F03.self-hosted\u002F01.fs","i-lucide-hard-drive",{"title":363,"path":364,"stem":365,"icon":366},"NuxtHub","\u002Fadapters\u002Fself-hosted\u002Fnuxthub","6.adapters\u002F03.self-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":368,"path":369,"stem":370,"children":371,"page":34},"Building blocks","\u002Fadapters\u002Fbuilding-blocks","6.adapters\u002F04.building-blocks",[372,377,382,386],{"title":373,"path":374,"stem":375,"icon":376},"Pipeline","\u002Fadapters\u002Fbuilding-blocks\u002Fpipeline","6.adapters\u002F04.building-blocks\u002F01.pipeline","i-lucide-workflow",{"title":378,"path":379,"stem":380,"icon":381},"HTTP","\u002Fadapters\u002Fbuilding-blocks\u002Fhttp","6.adapters\u002F04.building-blocks\u002F02.http","i-lucide-globe",{"title":383,"path":384,"stem":385,"icon":83},"Custom Adapters","\u002Fadapters\u002Fbuilding-blocks\u002Fcustom","6.adapters\u002F04.building-blocks\u002F03.custom",{"title":387,"path":388,"stem":389,"icon":390},"Toolkit","\u002Fadapters\u002Fbuilding-blocks\u002Ftoolkit","6.adapters\u002F04.building-blocks\u002F04.toolkit","i-lucide-blocks",{"title":392,"path":393,"stem":394,"children":395,"page":34},"Enrichers","\u002Fenrichers","7.enrichers",[396,399,403],{"title":41,"path":397,"stem":398,"icon":28},"\u002Fenrichers\u002Foverview","7.enrichers\u002F1.overview",{"title":400,"path":401,"stem":402,"icon":288},"Built-in","\u002Fenrichers\u002Fbuilt-in","7.enrichers\u002F2.built-in",{"title":404,"path":405,"stem":406,"icon":83},"Custom","\u002Fenrichers\u002Fcustom","7.enrichers\u002F3.custom",{"id":408,"title":409,"body":410,"description":1696,"extension":1697,"links":1698,"meta":1706,"navigation":1707,"path":364,"seo":1708,"stem":365,"__hash__":1709},"docs\u002F6.adapters\u002F03.self-hosted\u002F02.nuxthub.md","NuxtHub Storage",{"type":411,"value":412,"toc":1678},"minimark",[413,421,468,473,476,503,508,512,592,599,622,626,632,746,759,762,792,807,811,819,829,834,844,1063,1080,1084,1087,1105,1112,1116,1124,1227,1231,1236,1239,1244,1326,1329,1392,1396,1403,1473,1482,1486,1489,1502,1509,1538,1541,1545,1556,1641,1647,1651,1658,1662,1674],[414,415,416,420],"p",{},[417,418,419],"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.",[422,423,426,429,454],"prompt",{":actions":424,"description":425,"icon":366},"[\"copy\",\"cursor\",\"windsurf\"]","Store evlog wide events in NuxtHub",[414,427,428],{},"Store evlog wide events in my NuxtHub database (self-hosted log retention).",[430,431,432,436,439,442,445,448,451],"ul",{},[433,434,435],"li",{},"Install both modules: pnpm add @nuxthub\u002Fcore @evlog\u002Fnuxthub",[433,437,438],{},"Add @nuxthub\u002Fcore and @evlog\u002Fnuxthub to nuxt.config.ts modules (in that order)",[433,440,441],{},"Enable hub.database = true in nuxt.config.ts",[433,443,444],{},"Configure evlog.nuxthub: { retentionDays, batchSize, ... } for retention and batching",[433,446,447],{},"Run database migrations so the wide-events table is created",[433,449,450],{},"Confirm wide events are written to my NuxtHub database after triggering a request",[433,452,453],{},"For production at scale, combine with an external drain (Axiom \u002F OTLP) for long-term storage",[414,455,456,457,463,464],{},"Docs: ",[458,459,460],"a",{"href":460,"rel":461},"https:\u002F\u002Fwww.evlog.dev\u002Fadapters\u002Fself-hosted\u002Fnuxthub",[462],"nofollow","\nNuxtHub: ",[458,465,466],{"href":466,"rel":467},"https:\u002F\u002Fhub.nuxt.com",[462],[469,470,472],"h2",{"id":471},"why-self-hosted-logs","Why Self-Hosted Logs?",[414,474,475],{},"External logging services (Axiom, Datadog, etc.) are great for production at scale. But sometimes you want:",[430,477,478,485,491,497],{},[433,479,480,484],{},[481,482,483],"strong",{},"Zero external dependencies"," - logs stored in the same database as your app",[433,486,487,490],{},[481,488,489],{},"Full data ownership"," - no third-party access to your log data",[433,492,493,496],{},[481,494,495],{},"Free tier friendly"," - no per-event pricing, just your existing database",[433,498,499,502],{},[481,500,501],{},"Development & staging"," - full log visibility without paying for a service",[414,504,505,507],{},[417,506,419],{}," works as a drop-in drain. Your existing evlog setup stays the same, you just get a database-backed storage layer on top.",[469,509,511],{"id":510},"install","Install",[513,514,515,543,559,575],"code-group",{},[516,517,523],"pre",{"className":518,"code":519,"filename":520,"language":521,"meta":522,"style":522},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","pnpm","bash","",[417,524,525],{"__ignoreMap":522},[526,527,530,533,537,540],"span",{"class":528,"line":529},"line",1,[526,531,520],{"class":532},"sBMFI",[526,534,536],{"class":535},"sfazB"," add",[526,538,539],{"class":535}," @nuxthub\u002Fcore",[526,541,542],{"class":535}," @evlog\u002Fnuxthub\n",[516,544,547],{"className":518,"code":545,"filename":546,"language":521,"meta":522,"style":522},"bun add @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","bun",[417,548,549],{"__ignoreMap":522},[526,550,551,553,555,557],{"class":528,"line":529},[526,552,546],{"class":532},[526,554,536],{"class":535},[526,556,539],{"class":535},[526,558,542],{"class":535},[516,560,563],{"className":518,"code":561,"filename":562,"language":521,"meta":522,"style":522},"yarn add @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","yarn",[417,564,565],{"__ignoreMap":522},[526,566,567,569,571,573],{"class":528,"line":529},[526,568,562],{"class":532},[526,570,536],{"class":535},[526,572,539],{"class":535},[526,574,542],{"class":535},[516,576,579],{"className":518,"code":577,"filename":578,"language":521,"meta":522,"style":522},"npm install @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","npm",[417,580,581],{"__ignoreMap":522},[526,582,583,585,588,590],{"class":528,"line":529},[526,584,578],{"class":532},[526,586,587],{"class":535}," install",[526,589,539],{"class":535},[526,591,542],{"class":535},[414,593,594,595,598],{},"Or with ",[417,596,597],{},"nuxi",":",[516,600,603],{"className":518,"code":601,"filename":602,"language":521,"meta":522,"style":522},"npx nuxi module add @nuxthub\u002Fcore @evlog\u002Fnuxthub\n","Terminal",[417,604,605],{"__ignoreMap":522},[526,606,607,610,613,616,618,620],{"class":528,"line":529},[526,608,609],{"class":532},"npx",[526,611,612],{"class":535}," nuxi",[526,614,615],{"class":535}," module",[526,617,536],{"class":535},[526,619,539],{"class":535},[526,621,542],{"class":535},[469,623,625],{"id":624},"setup","Setup",[414,627,628,629,598],{},"Add the module to your ",[417,630,631],{},"nuxt.config.ts",[516,633,637],{"className":634,"code":635,"filename":631,"language":636,"meta":522,"style":522},"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",[417,638,639,660,696,703,714,731,737],{"__ignoreMap":522},[526,640,641,645,648,652,656],{"class":528,"line":529},[526,642,644],{"class":643},"s7zQu","export",[526,646,647],{"class":643}," default",[526,649,651],{"class":650},"s2Zo4"," defineNuxtConfig",[526,653,655],{"class":654},"sTEyZ","(",[526,657,659],{"class":658},"sMK4o","{\n",[526,661,663,667,669,672,675,678,680,683,686,688,690,693],{"class":528,"line":662},2,[526,664,666],{"class":665},"swJcz","  modules",[526,668,598],{"class":658},[526,670,671],{"class":654}," [",[526,673,674],{"class":658},"'",[526,676,677],{"class":535},"@nuxthub\u002Fcore",[526,679,674],{"class":658},[526,681,682],{"class":658},",",[526,684,685],{"class":658}," '",[526,687,419],{"class":535},[526,689,674],{"class":658},[526,691,692],{"class":654},"]",[526,694,695],{"class":658},",\n",[526,697,699],{"class":528,"line":698},3,[526,700,702],{"emptyLinePlaceholder":701},true,"\n",[526,704,706,709,711],{"class":528,"line":705},4,[526,707,708],{"class":665},"  evlog",[526,710,598],{"class":658},[526,712,713],{"class":658}," {\n",[526,715,717,720,722,724,727,729],{"class":528,"line":716},5,[526,718,719],{"class":665},"    retention",[526,721,598],{"class":658},[526,723,685],{"class":658},[526,725,726],{"class":535},"7d",[526,728,674],{"class":658},[526,730,695],{"class":658},[526,732,734],{"class":528,"line":733},6,[526,735,736],{"class":658},"  },\n",[526,738,740,743],{"class":528,"line":739},7,[526,741,742],{"class":658},"}",[526,744,745],{"class":654},")\n",[414,747,748,749,751,752,754,755,758],{},"Even if ",[417,750,419],{}," can auto-register missing modules, we recommend explicitly installing ",[417,753,677],{}," and registering it in ",[417,756,757],{},"modules"," for a clearer and more predictable setup.",[414,760,761],{},"That's it. The module automatically:",[763,764,765,775,782,789],"ol",{},[433,766,767,768,771,772,774],{},"Installs ",[417,769,770],{},"evlog\u002Fnuxt"," and ",[417,773,677],{}," if not already registered",[433,776,777,778,781],{},"Registers the ",[417,779,780],{},"evlog_events"," database schema with NuxtHub",[433,783,784,785,788],{},"Hooks into ",[417,786,787],{},"evlog:drain"," to store every event in the database",[433,790,791],{},"Schedules a cleanup task based on your retention policy",[793,794,796,799,800,803,804,806],"callout",{"color":795,"icon":13},"info",[481,797,798],{},"Prerequisites:"," Your project must use ",[458,801,363],{"href":466,"rel":802},[462]," with a database configured. ",[417,805,419],{}," uses Drizzle ORM to interact with the database.",[469,808,810],{"id":809},"how-it-works","How It Works",[516,812,817],{"className":813,"code":815,"language":816},[814],"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",[417,818,815],{"__ignoreMap":522},[414,820,821,822,824,825,828],{},"Every wide event emitted by evlog is stored as a row in the ",[417,823,780],{}," table. The drain plugin handles both single events and batches (when used with the ",[458,826,827],{"href":374},"pipeline",").",[830,831,833],"h3",{"id":832},"database-schema","Database Schema",[414,835,836,837,839,840,843],{},"The ",[417,838,780],{}," table stores indexed columns for fast querying and a ",[417,841,842],{},"data"," JSON column for all remaining fields:",[845,846,847,863],"table",{},[848,849,850],"thead",{},[851,852,853,857,860],"tr",{},[854,855,856],"th",{},"Column",[854,858,859],{},"Type",[854,861,862],{},"Description",[864,865,866,881,895,909,923,937,951,965,980,994,1008,1022,1036,1049],"tbody",{},[851,867,868,874,878],{},[869,870,871],"td",{},[417,872,873],{},"id",[869,875,876],{},[417,877,816],{},[869,879,880],{},"UUID primary key",[851,882,883,888,892],{},[869,884,885],{},[417,886,887],{},"timestamp",[869,889,890],{},[417,891,816],{},[869,893,894],{},"Event timestamp",[851,896,897,902,906],{},[869,898,899],{},[417,900,901],{},"level",[869,903,904],{},[417,905,816],{},[869,907,908],{},"Log level (info, warn, error, debug)",[851,910,911,916,920],{},[869,912,913],{},[417,914,915],{},"service",[869,917,918],{},[417,919,816],{},[869,921,922],{},"Service name",[851,924,925,930,934],{},[869,926,927],{},[417,928,929],{},"environment",[869,931,932],{},[417,933,816],{},[869,935,936],{},"Environment (production, staging, etc.)",[851,938,939,944,948],{},[869,940,941],{},[417,942,943],{},"method",[869,945,946],{},[417,947,816],{},[869,949,950],{},"HTTP method",[851,952,953,958,962],{},[869,954,955],{},[417,956,957],{},"path",[869,959,960],{},[417,961,816],{},[869,963,964],{},"Request path",[851,966,967,972,977],{},[869,968,969],{},[417,970,971],{},"status",[869,973,974],{},[417,975,976],{},"integer",[869,978,979],{},"HTTP status code",[851,981,982,987,991],{},[869,983,984],{},[417,985,986],{},"duration_ms",[869,988,989],{},[417,990,976],{},[869,992,993],{},"Request duration in milliseconds",[851,995,996,1001,1005],{},[869,997,998],{},[417,999,1000],{},"request_id",[869,1002,1003],{},[417,1004,816],{},[869,1006,1007],{},"Request correlation ID",[851,1009,1010,1015,1019],{},[869,1011,1012],{},[417,1013,1014],{},"source",[869,1016,1017],{},[417,1018,816],{},[869,1020,1021],{},"Event source (server, client)",[851,1023,1024,1029,1033],{},[869,1025,1026],{},[417,1027,1028],{},"error",[869,1030,1031],{},[417,1032,816],{},[869,1034,1035],{},"Error details (JSON string)",[851,1037,1038,1042,1046],{},[869,1039,1040],{},[417,1041,842],{},[869,1043,1044],{},[417,1045,816],{},[869,1047,1048],{},"All remaining event fields (JSON)",[851,1050,1051,1056,1060],{},[869,1052,1053],{},[417,1054,1055],{},"created_at",[869,1057,1058],{},[417,1059,816],{},[869,1061,1062],{},"Row insertion timestamp",[414,1064,1065,1066,1068,1069,1068,1071,1068,1073,1068,1075,1068,1077,1079],{},"Indexed columns: ",[417,1067,887],{},", ",[417,1070,901],{},[417,1072,915],{},[417,1074,971],{},[417,1076,1000],{},[417,1078,1055],{},".",[830,1081,1083],{"id":1082},"dialect-support","Dialect Support",[414,1085,1086],{},"The schema is automatically registered for your NuxtHub database dialect:",[430,1088,1089,1095,1100],{},[433,1090,1091,1094],{},[481,1092,1093],{},"SQLite"," (default for Cloudflare D1)",[433,1096,1097],{},[481,1098,1099],{},"MySQL",[433,1101,1102],{},[481,1103,1104],{},"PostgreSQL",[414,1106,1107,1108,1111],{},"The correct schema is selected via the ",[417,1109,1110],{},"hub:db:schema:extend"," hook based on your NuxtHub configuration.",[469,1113,1115],{"id":1114},"combining-with-external-adapters","Combining with External Adapters",[414,1117,1118,1120,1121,1123],{},[417,1119,419],{}," doesn't replace external adapters, you can use both. The module registers its own ",[417,1122,787],{}," hook, so any other drain plugins you have will still work:",[516,1125,1128],{"className":634,"code":1126,"filename":1127,"language":636,"meta":522,"style":522},"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",[417,1129,1130,1155,1159,1185,1191,1221],{"__ignoreMap":522},[526,1131,1132,1135,1138,1141,1144,1147,1149,1152],{"class":528,"line":529},[526,1133,1134],{"class":643},"import",[526,1136,1137],{"class":658}," {",[526,1139,1140],{"class":654}," createAxiomDrain",[526,1142,1143],{"class":658}," }",[526,1145,1146],{"class":643}," from",[526,1148,685],{"class":658},[526,1150,1151],{"class":535},"evlog\u002Faxiom",[526,1153,1154],{"class":658},"'\n",[526,1156,1157],{"class":528,"line":662},[526,1158,702],{"emptyLinePlaceholder":701},[526,1160,1161,1163,1165,1168,1170,1172,1176,1179,1183],{"class":528,"line":698},[526,1162,644],{"class":643},[526,1164,647],{"class":643},[526,1166,1167],{"class":650}," defineNitroPlugin",[526,1169,655],{"class":654},[526,1171,655],{"class":658},[526,1173,1175],{"class":1174},"sHdIc","nitroApp",[526,1177,1178],{"class":658},")",[526,1180,1182],{"class":1181},"spNyl"," =>",[526,1184,713],{"class":658},[526,1186,1187],{"class":528,"line":705},[526,1188,1190],{"class":1189},"sHwdD","  \u002F\u002F This runs alongside @evlog\u002Fnuxthub's built-in drain\n",[526,1192,1193,1196,1198,1201,1203,1206,1208,1210,1212,1214,1216,1218],{"class":528,"line":716},[526,1194,1195],{"class":654},"  nitroApp",[526,1197,1079],{"class":658},[526,1199,1200],{"class":654},"hooks",[526,1202,1079],{"class":658},[526,1204,1205],{"class":650},"hook",[526,1207,655],{"class":665},[526,1209,674],{"class":658},[526,1211,787],{"class":535},[526,1213,674],{"class":658},[526,1215,682],{"class":658},[526,1217,1140],{"class":650},[526,1219,1220],{"class":665},"())\n",[526,1222,1223,1225],{"class":528,"line":733},[526,1224,742],{"class":658},[526,1226,745],{"class":654},[469,1228,1230],{"id":1229},"retention","Retention",[414,1232,1233,1235],{},[417,1234,419],{}," automatically deletes old events based on your retention policy. No manual cleanup needed.",[830,1237,170],{"id":1238},"configuration",[414,1240,1241,1242,598],{},"Set the retention period in your ",[417,1243,631],{},[516,1245,1247],{"className":634,"code":1246,"filename":631,"language":636,"meta":522,"style":522},"export default defineNuxtConfig({\n  modules: ['@nuxthub\u002Fcore', '@evlog\u002Fnuxthub'],\n\n  evlog: {\n    retention: '7d', \u002F\u002F default\n  },\n})\n",[417,1248,1249,1261,1287,1291,1299,1316,1320],{"__ignoreMap":522},[526,1250,1251,1253,1255,1257,1259],{"class":528,"line":529},[526,1252,644],{"class":643},[526,1254,647],{"class":643},[526,1256,651],{"class":650},[526,1258,655],{"class":654},[526,1260,659],{"class":658},[526,1262,1263,1265,1267,1269,1271,1273,1275,1277,1279,1281,1283,1285],{"class":528,"line":662},[526,1264,666],{"class":665},[526,1266,598],{"class":658},[526,1268,671],{"class":654},[526,1270,674],{"class":658},[526,1272,677],{"class":535},[526,1274,674],{"class":658},[526,1276,682],{"class":658},[526,1278,685],{"class":658},[526,1280,419],{"class":535},[526,1282,674],{"class":658},[526,1284,692],{"class":654},[526,1286,695],{"class":658},[526,1288,1289],{"class":528,"line":698},[526,1290,702],{"emptyLinePlaceholder":701},[526,1292,1293,1295,1297],{"class":528,"line":705},[526,1294,708],{"class":665},[526,1296,598],{"class":658},[526,1298,713],{"class":658},[526,1300,1301,1303,1305,1307,1309,1311,1313],{"class":528,"line":716},[526,1302,719],{"class":665},[526,1304,598],{"class":658},[526,1306,685],{"class":658},[526,1308,726],{"class":535},[526,1310,674],{"class":658},[526,1312,682],{"class":658},[526,1314,1315],{"class":1189}," \u002F\u002F default\n",[526,1317,1318],{"class":528,"line":733},[526,1319,736],{"class":658},[526,1321,1322,1324],{"class":528,"line":739},[526,1323,742],{"class":658},[526,1325,745],{"class":654},[414,1327,1328],{},"The retention value is a number followed by a unit:",[845,1330,1331,1343],{},[848,1332,1333],{},[851,1334,1335,1338,1340],{},[854,1336,1337],{},"Unit",[854,1339,862],{},[854,1341,1342],{},"Example",[864,1344,1345,1360,1376],{},[851,1346,1347,1352,1355],{},[869,1348,1349],{},[417,1350,1351],{},"d",[869,1353,1354],{},"Days",[869,1356,1357,1359],{},[417,1358,726],{}," = 7 days",[851,1361,1362,1367,1370],{},[869,1363,1364],{},[417,1365,1366],{},"h",[869,1368,1369],{},"Hours",[869,1371,1372,1375],{},[417,1373,1374],{},"24h"," = 24 hours",[851,1377,1378,1383,1386],{},[869,1379,1380],{},[417,1381,1382],{},"m",[869,1384,1385],{},"Minutes",[869,1387,1388,1391],{},[417,1389,1390],{},"60m"," = 60 minutes",[830,1393,1395],{"id":1394},"how-cleanup-works","How Cleanup Works",[414,1397,1398,1399,1402],{},"The module registers a Nitro scheduled task (",[417,1400,1401],{},"evlog:cleanup",") that runs on a cron schedule derived from your retention value. The cron frequency is set to roughly half the retention period:",[845,1404,1405,1416],{},[848,1406,1407],{},[851,1408,1409,1411,1414],{},[854,1410,1230],{},[854,1412,1413],{},"Cron Schedule",[854,1415,862],{},[864,1417,1418,1432,1446,1460],{},[851,1419,1420,1424,1429],{},[869,1421,1422],{},[417,1423,1390],{},[869,1425,1426],{},[417,1427,1428],{},"*\u002F30 * * * *",[869,1430,1431],{},"Every 30 minutes",[851,1433,1434,1438,1443],{},[869,1435,1436],{},[417,1437,1374],{},[869,1439,1440],{},[417,1441,1442],{},"0 *\u002F12 * * *",[869,1444,1445],{},"Every 12 hours",[851,1447,1448,1452,1457],{},[869,1449,1450],{},[417,1451,726],{},[869,1453,1454],{},[417,1455,1456],{},"0 3 * * *",[869,1458,1459],{},"Daily at 3:00 AM",[851,1461,1462,1467,1471],{},[869,1463,1464],{},[417,1465,1466],{},"30d",[869,1468,1469],{},[417,1470,1456],{},[869,1472,1459],{},[414,1474,1475,1476,1478,1479,1481],{},"The cleanup task deletes all rows in ",[417,1477,780],{}," where ",[417,1480,1055],{}," is older than the retention period.",[830,1483,1485],{"id":1484},"manual-cleanup","Manual Cleanup",[414,1487,1488],{},"You can trigger cleanup manually via the API endpoint:",[516,1490,1492],{"className":518,"code":1491,"filename":602,"language":521,"meta":522,"style":522},"curl https:\u002F\u002Fyour-app.com\u002Fapi\u002F_cron\u002Fevlog-cleanup\n",[417,1493,1494],{"__ignoreMap":522},[526,1495,1496,1499],{"class":528,"line":529},[526,1497,1498],{"class":532},"curl",[526,1500,1501],{"class":535}," https:\u002F\u002Fyour-app.com\u002Fapi\u002F_cron\u002Fevlog-cleanup\n",[414,1503,1504,1505,1508],{},"If the ",[417,1506,1507],{},"CRON_SECRET"," environment variable is set, the endpoint requires a Bearer token:",[516,1510,1512],{"className":518,"code":1511,"filename":602,"language":521,"meta":522,"style":522},"curl -H \"Authorization: Bearer your-secret\" \\\n  https:\u002F\u002Fyour-app.com\u002Fapi\u002F_cron\u002Fevlog-cleanup\n",[417,1513,1514,1533],{"__ignoreMap":522},[526,1515,1516,1518,1521,1524,1527,1530],{"class":528,"line":529},[526,1517,1498],{"class":532},[526,1519,1520],{"class":535}," -H",[526,1522,1523],{"class":658}," \"",[526,1525,1526],{"class":535},"Authorization: Bearer your-secret",[526,1528,1529],{"class":658},"\"",[526,1531,1532],{"class":654}," \\\n",[526,1534,1535],{"class":528,"line":662},[526,1536,1537],{"class":535},"  https:\u002F\u002Fyour-app.com\u002Fapi\u002F_cron\u002Fevlog-cleanup\n",[414,1539,1540],{},"This is recommended for production deployments to prevent unauthorized cleanup triggers.",[830,1542,1544],{"id":1543},"vercel-cron","Vercel Cron",[414,1546,1547,1548,1551,1552,1555],{},"When installing the module with ",[417,1549,1550],{},"nuxi module add",", you'll be prompted to create a ",[417,1553,1554],{},"vercel.json"," with the appropriate cron schedule:",[516,1557,1561],{"className":1558,"code":1559,"filename":1554,"language":1560,"meta":522,"style":522},"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",[417,1562,1563,1567,1582,1587,1607,1625,1630,1635],{"__ignoreMap":522},[526,1564,1565],{"class":528,"line":529},[526,1566,659],{"class":658},[526,1568,1569,1572,1575,1577,1579],{"class":528,"line":662},[526,1570,1571],{"class":658},"  \"",[526,1573,1574],{"class":1181},"crons",[526,1576,1529],{"class":658},[526,1578,598],{"class":658},[526,1580,1581],{"class":658}," [\n",[526,1583,1584],{"class":528,"line":698},[526,1585,1586],{"class":658},"    {\n",[526,1588,1589,1592,1594,1596,1598,1600,1603,1605],{"class":528,"line":705},[526,1590,1591],{"class":658},"      \"",[526,1593,957],{"class":532},[526,1595,1529],{"class":658},[526,1597,598],{"class":658},[526,1599,1523],{"class":658},[526,1601,1602],{"class":535},"\u002Fapi\u002F_cron\u002Fevlog-cleanup",[526,1604,1529],{"class":658},[526,1606,695],{"class":658},[526,1608,1609,1611,1614,1616,1618,1620,1622],{"class":528,"line":716},[526,1610,1591],{"class":658},[526,1612,1613],{"class":532},"schedule",[526,1615,1529],{"class":658},[526,1617,598],{"class":658},[526,1619,1523],{"class":658},[526,1621,1456],{"class":535},[526,1623,1624],{"class":658},"\"\n",[526,1626,1627],{"class":528,"line":733},[526,1628,1629],{"class":658},"    }\n",[526,1631,1632],{"class":528,"line":739},[526,1633,1634],{"class":658},"  ]\n",[526,1636,1638],{"class":528,"line":1637},8,[526,1639,1640],{"class":658},"}\n",[414,1642,1643,1644,1646],{},"On Vercel, the ",[417,1645,1507],{}," environment variable is automatically set and validated.",[830,1648,1650],{"id":1649},"cloudflare-other-platforms","Cloudflare & Other Platforms",[414,1652,1653,1654,1657],{},"On Cloudflare Workers and other platforms, the Nitro scheduled task handles cleanup automatically without any additional cron configuration. The task is registered with ",[417,1655,1656],{},"experimental.tasks"," enabled in the Nitro config.",[469,1659,1661],{"id":1660},"next-steps","Next Steps",[430,1663,1664,1669],{},[433,1665,1666,1668],{},[458,1667,305],{"href":310}," - Send logs to external services alongside NuxtHub storage",[433,1670,1671,1673],{},[458,1672,373],{"href":374}," - Batch events for better database performance",[1675,1676,1677],"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":522,"searchDepth":662,"depth":662,"links":1679},[1680,1681,1682,1683,1687,1688,1695],{"id":471,"depth":662,"text":472},{"id":510,"depth":662,"text":511},{"id":624,"depth":662,"text":625},{"id":809,"depth":662,"text":810,"children":1684},[1685,1686],{"id":832,"depth":698,"text":833},{"id":1082,"depth":698,"text":1083},{"id":1114,"depth":662,"text":1115},{"id":1229,"depth":662,"text":1230,"children":1689},[1690,1691,1692,1693,1694],{"id":1238,"depth":698,"text":170},{"id":1394,"depth":698,"text":1395},{"id":1484,"depth":698,"text":1485},{"id":1543,"depth":698,"text":1544},{"id":1649,"depth":698,"text":1650},{"id":1660,"depth":662,"text":1661},"Self-hosted log retention for evlog using NuxtHub database storage. Store, query, and automatically clean up your structured logs with zero external dependencies.","md",[1699,1704],{"label":363,"icon":1700,"to":466,"target":1701,"color":1702,"variant":1703},"i-lucide-external-link","_blank","neutral","subtle",{"label":305,"icon":1705,"to":310,"color":1702,"variant":1703},"i-custom-plug",{},{"title":363,"icon":366},{"title":409,"description":1696},"7IAyh9YhgeYDG6zRJWByEW2QvSef3_48EfOsdchlpRY",[1711,1713],{"title":358,"path":359,"stem":360,"description":1712,"icon":361,"children":-1},"Write wide events to the local file system as NDJSON for local debugging, AI agent integration, and production backup.",{"title":373,"path":374,"stem":375,"description":1714,"icon":376,"children":-1},"Batch events, retry on failure, and protect against buffer overflow with the shared drain pipeline. Supports fan-out to multiple adapters.",1778327043010]