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