[{"data":1,"prerenderedAt":3435},["ShallowReactive",2],{"navigation_docs":3,"-integrate-adapters-hybrid-clickhouse":538,"-integrate-adapters-hybrid-clickhouse-surround":3430},[4,30,80,128,308,440,499],{"title":5,"path":6,"stem":7,"children":8,"page":29},"Start","\u002Fstart","1.start",[9,14,19,24],{"title":10,"path":11,"stem":12,"icon":13},"Introduction","\u002Fstart\u002Fintroduction","1.start\u002F1.introduction","i-lucide-info",{"title":15,"path":16,"stem":17,"icon":18},"Why start with evlog","\u002Fstart\u002Fwhy-evlog","1.start\u002F2.why-evlog","i-lucide-rocket",{"title":20,"path":21,"stem":22,"icon":23},"Installation","\u002Fstart\u002Finstallation","1.start\u002F3.installation","i-lucide-download",{"title":25,"path":26,"stem":27,"icon":28},"Quick Start","\u002Fstart\u002Fquick-start","1.start\u002F4.quick-start","i-lucide-zap",false,{"title":31,"path":32,"stem":33,"children":34,"page":29},"Learn","\u002Flearn","2.learn",[35,40,45,50,55,60,65,70,75],{"title":36,"path":37,"stem":38,"icon":39},"Overview","\u002Flearn\u002Foverview","2.learn\u002F0.overview","i-lucide-list",{"title":41,"path":42,"stem":43,"icon":44},"Simple Logging","\u002Flearn\u002Fsimple-logging","2.learn\u002F1.simple-logging","i-lucide-terminal",{"title":46,"path":47,"stem":48,"icon":49},"Wide Events","\u002Flearn\u002Fwide-events","2.learn\u002F2.wide-events","i-lucide-layers",{"title":51,"path":52,"stem":53,"icon":54},"Structured Errors","\u002Flearn\u002Fstructured-errors","2.learn\u002F3.structured-errors","i-lucide-shield-alert",{"title":56,"path":57,"stem":58,"icon":59},"Lifecycle","\u002Flearn\u002Flifecycle","2.learn\u002F4.lifecycle","i-lucide-arrow-right-left",{"title":61,"path":62,"stem":63,"icon":64},"Sampling","\u002Flearn\u002Fsampling","2.learn\u002F5.sampling","i-lucide-filter",{"title":66,"path":67,"stem":68,"icon":69},"Auto-Redaction","\u002Flearn\u002Fredaction","2.learn\u002F6.redaction","i-lucide-eye-off",{"title":71,"path":72,"stem":73,"icon":74},"Typed Fields","\u002Flearn\u002Ftyped-fields","2.learn\u002F7.typed-fields","i-simple-icons-typescript",{"title":76,"path":77,"stem":78,"icon":79},"Catalogs","\u002Flearn\u002Fcatalogs","2.learn\u002F8.catalogs","i-lucide-book-open",{"title":81,"path":82,"stem":83,"children":84,"page":29},"CLI","\u002Fcli","3.cli",[85,88,93,98,103,108,113,118,123],{"title":36,"path":86,"stem":87,"icon":44},"\u002Fcli\u002Foverview","3.cli\u002F0.overview",{"title":89,"path":90,"stem":91,"icon":92},"init","\u002Fcli\u002Finit","3.cli\u002F1.init","i-lucide-wand-sparkles",{"title":94,"path":95,"stem":96,"icon":97},"map","\u002Fcli\u002Fmap","3.cli\u002F2.map","i-lucide-radar",{"title":99,"path":100,"stem":101,"icon":102},"Rules","\u002Fcli\u002Frules","3.cli\u002F3.rules","i-lucide-list-checks",{"title":104,"path":105,"stem":106,"icon":107},"Scoring","\u002Fcli\u002Fscoring","3.cli\u002F4.scoring","i-lucide-gauge",{"title":109,"path":110,"stem":111,"icon":112},"CI","\u002Fcli\u002Fci","3.cli\u002F5.ci","i-lucide-git-pull-request",{"title":114,"path":115,"stem":116,"icon":117},"doctor","\u002Fcli\u002Fdoctor","3.cli\u002F6.doctor","i-lucide-stethoscope",{"title":119,"path":120,"stem":121,"icon":122},"telemetry","\u002Fcli\u002Ftelemetry","3.cli\u002F7.telemetry","i-lucide-bar-chart-3",{"title":124,"path":125,"stem":126,"icon":127},"agents","\u002Fcli\u002Fagents","3.cli\u002F8.agents","i-lucide-bot",{"title":129,"path":130,"stem":131,"children":132,"page":29},"Integrate","\u002Fintegrate","4.integrate",[133,137,220],{"title":36,"path":134,"stem":135,"icon":136},"\u002Fintegrate\u002Foverview","4.integrate\u002F0.overview","i-lucide-plug",{"title":138,"path":139,"stem":140,"children":141,"page":29},"Adapters","\u002Fintegrate\u002Fadapters","4.integrate\u002Fadapters",[142,145,175,200],{"title":36,"path":143,"stem":144,"icon":39},"\u002Fintegrate\u002Fadapters\u002Foverview","4.integrate\u002Fadapters\u002F01.overview",{"title":146,"path":147,"stem":148,"children":149,"page":29},"Cloud","\u002Fintegrate\u002Fadapters\u002Fcloud","4.integrate\u002Fadapters\u002Fcloud",[150,155,160,165,170],{"title":151,"path":152,"stem":153,"icon":154},"Axiom","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Faxiom","4.integrate\u002Fadapters\u002Fcloud\u002F01.axiom","i-custom-axiom",{"title":156,"path":157,"stem":158,"icon":159},"PostHog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fposthog","4.integrate\u002Fadapters\u002Fcloud\u002F02.posthog","i-simple-icons-posthog",{"title":161,"path":162,"stem":163,"icon":164},"Sentry","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fsentry","4.integrate\u002Fadapters\u002Fcloud\u002F03.sentry","i-simple-icons-sentry",{"title":166,"path":167,"stem":168,"icon":169},"Better Stack","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fbetter-stack","4.integrate\u002Fadapters\u002Fcloud\u002F04.better-stack","i-simple-icons-betterstack",{"title":171,"path":172,"stem":173,"icon":174},"Datadog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fdatadog","4.integrate\u002Fadapters\u002Fcloud\u002F05.datadog","i-simple-icons-datadog",{"title":176,"path":177,"stem":178,"children":179,"page":29},"Cloud or Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fhybrid","4.integrate\u002Fadapters\u002Fhybrid",[180,185,190,195],{"title":181,"path":182,"stem":183,"icon":184},"Grafana Loki","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Floki","4.integrate\u002Fadapters\u002Fhybrid\u002F01.loki","i-simple-icons-grafana",{"title":186,"path":187,"stem":188,"icon":189},"ClickHouse","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fclickhouse","4.integrate\u002Fadapters\u002Fhybrid\u002F02.clickhouse","i-simple-icons-clickhouse",{"title":191,"path":192,"stem":193,"icon":194},"OTLP","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fotlp","4.integrate\u002Fadapters\u002Fhybrid\u002F03.otlp","i-simple-icons-opentelemetry",{"title":196,"path":197,"stem":198,"icon":199},"HyperDX","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fhyperdx","4.integrate\u002Fadapters\u002Fhybrid\u002F04.hyperdx","i-custom-hyperdx",{"title":201,"path":202,"stem":203,"children":204,"page":29},"Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fself-hosted","4.integrate\u002Fadapters\u002Fself-hosted",[205,210,215],{"title":206,"path":207,"stem":208,"icon":209},"File System","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Ffs","4.integrate\u002Fadapters\u002Fself-hosted\u002F01.fs","i-lucide-hard-drive",{"title":211,"path":212,"stem":213,"icon":214},"NuxtHub","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fnuxthub","4.integrate\u002Fadapters\u002Fself-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":216,"path":217,"stem":218,"icon":219},"Memory","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fmemory","4.integrate\u002Fadapters\u002Fself-hosted\u002F03.memory","i-lucide-cpu",{"title":221,"path":222,"stem":223,"children":224,"page":29},"Frameworks","\u002Fintegrate\u002Fframeworks","4.integrate\u002Fframeworks",[225,229,234,239,244,249,254,259,264,269,274,279,284,289,293,298,303],{"title":36,"path":226,"stem":227,"icon":228},"\u002Fintegrate\u002Fframeworks\u002Foverview","4.integrate\u002Fframeworks\u002F00.overview","i-lucide-layout-grid",{"title":230,"path":231,"stem":232,"icon":233},"Nuxt","\u002Fintegrate\u002Fframeworks\u002Fnuxt","4.integrate\u002Fframeworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":235,"path":236,"stem":237,"icon":238},"Next.js","\u002Fintegrate\u002Fframeworks\u002Fnextjs","4.integrate\u002Fframeworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":240,"path":241,"stem":242,"icon":243},"SvelteKit","\u002Fintegrate\u002Fframeworks\u002Fsveltekit","4.integrate\u002Fframeworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":245,"path":246,"stem":247,"icon":248},"Nitro","\u002Fintegrate\u002Fframeworks\u002Fnitro","4.integrate\u002Fframeworks\u002F04.nitro","i-custom-nitro",{"title":250,"path":251,"stem":252,"icon":253},"TanStack Start","\u002Fintegrate\u002Fframeworks\u002Ftanstack-start","4.integrate\u002Fframeworks\u002F05.tanstack-start","i-custom-tanstack",{"title":255,"path":256,"stem":257,"icon":258},"NestJS","\u002Fintegrate\u002Fframeworks\u002Fnestjs","4.integrate\u002Fframeworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":260,"path":261,"stem":262,"icon":263},"Express","\u002Fintegrate\u002Fframeworks\u002Fexpress","4.integrate\u002Fframeworks\u002F07.express","i-simple-icons-express",{"title":265,"path":266,"stem":267,"icon":268},"Hono","\u002Fintegrate\u002Fframeworks\u002Fhono","4.integrate\u002Fframeworks\u002F08.hono","i-simple-icons-hono",{"title":270,"path":271,"stem":272,"icon":273},"Fastify","\u002Fintegrate\u002Fframeworks\u002Ffastify","4.integrate\u002Fframeworks\u002F09.fastify","i-simple-icons-fastify",{"title":275,"path":276,"stem":277,"icon":278},"Elysia","\u002Fintegrate\u002Fframeworks\u002Felysia","4.integrate\u002Fframeworks\u002F10.elysia","i-custom-elysia",{"title":280,"path":281,"stem":282,"icon":283},"React Router","\u002Fintegrate\u002Fframeworks\u002Freact-router","4.integrate\u002Fframeworks\u002F11.react-router","i-custom-reactrouter",{"title":285,"path":286,"stem":287,"icon":288},"Cloudflare Workers","\u002Fintegrate\u002Fframeworks\u002Fcloudflare-workers","4.integrate\u002Fframeworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":290,"path":291,"stem":292,"icon":74},"Standalone","\u002Fintegrate\u002Fframeworks\u002Fstandalone","4.integrate\u002Fframeworks\u002F13.standalone",{"title":294,"path":295,"stem":296,"icon":297},"Astro","\u002Fintegrate\u002Fframeworks\u002Fastro","4.integrate\u002Fframeworks\u002F14.astro","i-simple-icons-astro",{"title":299,"path":300,"stem":301,"icon":302},"oRPC","\u002Fintegrate\u002Fframeworks\u002Forpc","4.integrate\u002Fframeworks\u002F15.orpc","i-lucide-network",{"title":304,"path":305,"stem":306,"icon":307},"AWS Lambda","\u002Fintegrate\u002Fframeworks\u002Faws-lambda","4.integrate\u002Fframeworks\u002F16.aws-lambda","i-custom-lambda",{"title":309,"path":310,"stem":311,"children":312,"page":29},"Use Cases","\u002Fuse-cases","5.use-cases",[313,316,321,350,377,409,430,435],{"title":36,"path":314,"stem":315,"icon":102},"\u002Fuse-cases\u002Foverview","5.use-cases\u002F0.overview",{"title":317,"path":318,"stem":319,"icon":320},"Client Logging","\u002Fuse-cases\u002Fclient-logging","5.use-cases\u002F1.client-logging","i-lucide-monitor",{"title":322,"icon":323,"path":324,"stem":325,"children":326,"page":29},"AI SDK","i-simple-icons-vercel","\u002Fuse-cases\u002Fai-sdk","5.use-cases\u002F2.ai-sdk",[327,330,335,340,345],{"title":36,"path":328,"stem":329,"icon":39},"\u002Fuse-cases\u002Fai-sdk\u002Foverview","5.use-cases\u002F2.ai-sdk\u002F01.overview",{"title":331,"path":332,"stem":333,"icon":334},"Usage","\u002Fuse-cases\u002Fai-sdk\u002Fusage","5.use-cases\u002F2.ai-sdk\u002F02.usage","i-lucide-code",{"title":336,"path":337,"stem":338,"icon":339},"Options","\u002Fuse-cases\u002Fai-sdk\u002Foptions","5.use-cases\u002F2.ai-sdk\u002F03.options","i-lucide-sliders",{"title":341,"path":342,"stem":343,"icon":344},"Metadata","\u002Fuse-cases\u002Fai-sdk\u002Fmetadata","5.use-cases\u002F2.ai-sdk\u002F04.metadata","i-lucide-database",{"title":346,"path":347,"stem":348,"icon":349},"Telemetry","\u002Fuse-cases\u002Fai-sdk\u002Ftelemetry","5.use-cases\u002F2.ai-sdk\u002F05.telemetry","i-lucide-activity",{"title":351,"icon":352,"path":353,"stem":354,"children":355,"page":29},"Better Auth","i-simple-icons-betterauth","\u002Fuse-cases\u002Fbetter-auth","5.use-cases\u002F3.better-auth",[356,359,364,369,373],{"title":36,"path":357,"stem":358,"icon":39},"\u002Fuse-cases\u002Fbetter-auth\u002Foverview","5.use-cases\u002F3.better-auth\u002F01.overview",{"title":360,"path":361,"stem":362,"icon":363},"Identify User","\u002Fuse-cases\u002Fbetter-auth\u002Fidentify-user","5.use-cases\u002F3.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":365,"path":366,"stem":367,"icon":368},"Middleware","\u002Fuse-cases\u002Fbetter-auth\u002Fmiddleware","5.use-cases\u002F3.better-auth\u002F03.middleware","i-lucide-shield",{"title":370,"path":371,"stem":372,"icon":320},"Client Sync","\u002Fuse-cases\u002Fbetter-auth\u002Fclient-sync","5.use-cases\u002F3.better-auth\u002F04.client-sync",{"title":374,"path":375,"stem":376,"icon":107},"Performance","\u002Fuse-cases\u002Fbetter-auth\u002Fperformance","5.use-cases\u002F3.better-auth\u002F05.performance",{"title":378,"icon":379,"path":380,"stem":381,"children":382,"page":29},"Audit Logs","i-lucide-shield-check","\u002Fuse-cases\u002Faudit","5.use-cases\u002F4.audit",[383,386,391,396,401,405],{"title":36,"path":384,"stem":385,"icon":39},"\u002Fuse-cases\u002Faudit\u002Foverview","5.use-cases\u002F4.audit\u002F01.overview",{"title":387,"path":388,"stem":389,"icon":390},"Schema","\u002Fuse-cases\u002Faudit\u002Fschema","5.use-cases\u002F4.audit\u002F02.schema","i-lucide-file-text",{"title":392,"path":393,"stem":394,"icon":395},"Recording","\u002Fuse-cases\u002Faudit\u002Frecording","5.use-cases\u002F4.audit\u002F03.recording","i-lucide-pen-line",{"title":397,"path":398,"stem":399,"icon":400},"Drains","\u002Fuse-cases\u002Faudit\u002Fpipeline","5.use-cases\u002F4.audit\u002F04.pipeline","i-lucide-link",{"title":402,"path":403,"stem":404,"icon":379},"Compliance","\u002Fuse-cases\u002Faudit\u002Fcompliance","5.use-cases\u002F4.audit\u002F05.compliance",{"title":406,"path":407,"stem":408,"icon":79},"Recipes","\u002Fuse-cases\u002Faudit\u002Frecipes","5.use-cases\u002F4.audit\u002F06.recipes",{"title":346,"icon":107,"path":410,"stem":411,"children":412,"page":29},"\u002Fuse-cases\u002Ftelemetry","5.use-cases\u002F4.telemetry",[413,416,421,426],{"title":36,"path":414,"stem":415,"icon":39},"\u002Fuse-cases\u002Ftelemetry\u002Foverview","5.use-cases\u002F4.telemetry\u002F01.overview",{"title":417,"path":418,"stem":419,"icon":420},"Setup","\u002Fuse-cases\u002Ftelemetry\u002Fsetup","5.use-cases\u002F4.telemetry\u002F02.setup","i-lucide-wrench",{"title":422,"path":423,"stem":424,"icon":425},"Ingest","\u002Fuse-cases\u002Ftelemetry\u002Fingest","5.use-cases\u002F4.telemetry\u002F03.ingest","i-lucide-server",{"title":427,"path":428,"stem":429,"icon":79},"Reference","\u002Fuse-cases\u002Ftelemetry\u002Freference","5.use-cases\u002F4.telemetry\u002F04.reference",{"title":431,"path":432,"stem":433,"icon":434},"Enrichers","\u002Fuse-cases\u002Fenrichers","5.use-cases\u002F5.enrichers","i-lucide-sparkles",{"title":436,"path":437,"stem":438,"icon":439},"eve","\u002Fuse-cases\u002Feve","5.use-cases\u002F5.eve","i-custom-eve",{"title":441,"path":442,"stem":443,"children":444,"page":29},"Extend","\u002Fextend","6.extend",[445,449,454,459,463,468,472,476,480,484,489,494],{"title":36,"path":446,"stem":447,"icon":448},"\u002Fextend\u002Foverview","6.extend\u002F0.overview","i-lucide-blocks",{"title":450,"path":451,"stem":452,"icon":453},"Stream","\u002Fextend\u002Fstream","6.extend\u002F1.stream","i-lucide-radio-tower",{"title":455,"path":456,"stem":457,"icon":458},"Custom framework","\u002Fextend\u002Fcustom-framework","6.extend\u002F10.custom-framework","i-lucide-puzzle",{"title":460,"path":461,"stem":462,"icon":453},"Diagnostics channel","\u002Fextend\u002Fdiagnostics-channel","6.extend\u002F11.diagnostics-channel",{"title":464,"path":465,"stem":466,"icon":467},"FS reader","\u002Fextend\u002Ffs-reader","6.extend\u002F2.fs-reader","i-lucide-folder-search",{"title":406,"path":469,"stem":470,"icon":471},"\u002Fextend\u002Fconsumer-recipes","6.extend\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":473,"path":474,"stem":475,"icon":448},"Plugins","\u002Fextend\u002Fplugins","6.extend\u002F4.plugins",{"title":477,"path":478,"stem":479,"icon":434},"Custom enrichers","\u002Fextend\u002Fcustom-enrichers","6.extend\u002F5.custom-enrichers",{"title":481,"path":482,"stem":483,"icon":64},"Tail sampling","\u002Fextend\u002Ftail-sampling","6.extend\u002F6.tail-sampling",{"title":485,"path":486,"stem":487,"icon":488},"Identity headers","\u002Fextend\u002Fidentity-headers","6.extend\u002F7.identity-headers","i-lucide-fingerprint",{"title":490,"path":491,"stem":492,"icon":493},"Custom drains","\u002Fextend\u002Fcustom-drains","6.extend\u002F8.custom-drains","i-lucide-share-2",{"title":495,"path":496,"stem":497,"icon":498},"Drain pipeline","\u002Fextend\u002Fdrain-pipeline","6.extend\u002F9.drain-pipeline","i-lucide-workflow",{"title":427,"path":500,"stem":501,"children":502,"page":29},"\u002Freference","7.reference",[503,507,512,515,520,524,529,533],{"title":36,"path":504,"stem":505,"icon":506},"\u002Freference\u002Foverview","7.reference\u002F0.overview","i-lucide-book-marked",{"title":508,"path":509,"stem":510,"icon":511},"Configuration","\u002Freference\u002Fconfiguration","7.reference\u002F1.configuration","i-lucide-settings",{"title":374,"path":513,"stem":514,"icon":107},"\u002Freference\u002Fperformance","7.reference\u002F2.performance",{"title":516,"path":517,"stem":518,"icon":519},"Vite Plugin","\u002Freference\u002Fvite-plugin","7.reference\u002F3.vite-plugin","i-custom-vite",{"title":521,"path":522,"stem":523,"icon":379},"Best Practices","\u002Freference\u002Fbest-practices","7.reference\u002F4.best-practices",{"title":525,"path":526,"stem":527,"icon":528},"vs Other Loggers","\u002Freference\u002Fvs-other-loggers","7.reference\u002F5.vs-other-loggers","i-lucide-scale",{"title":530,"path":531,"stem":532,"icon":434},"Agent Skills","\u002Freference\u002Fagent-skills","7.reference\u002F6.agent-skills",{"title":534,"path":535,"stem":536,"icon":537},"Cost","\u002Freference\u002Fcost","7.reference\u002F7.cost","i-lucide-receipt",{"id":539,"title":540,"body":541,"description":3415,"extension":3416,"links":3417,"meta":3426,"navigation":3427,"path":187,"seo":3428,"stem":188,"__hash__":3429},"docs\u002F4.integrate\u002Fadapters\u002Fhybrid\u002F02.clickhouse.md","ClickHouse Adapter",{"type":542,"value":543,"toc":3394},"minimark",[544,561,573,623,627,630,673,677,680,922,934,937,1716,1719,1724,1821,1824,2028,2032,2035,2039,2042,2072,2112,2127,2131,2134,2206,2238,2253,2273,2277,2280,2339,2359,2366,2395,2406,2410,2423,2431,2434,2448,2452,2458,2549,2681,2746,2829,2833,2839,2986,2992,2996,2999,3188,3192,3209,3229,3241,3256,3260,3348,3361,3365,3390],[545,546,547,548,555,556,560],"p",{},"The ClickHouse adapter inserts wide events over the ",[549,550,554],"a",{"href":551,"rel":552},"https:\u002F\u002Fclickhouse.com\u002Fdocs\u002Fen\u002Finterfaces\u002Fhttp",[553],"nofollow","HTTP interface"," in ",[557,558,559],"code",{},"JSONEachRow"," format. It works with a local instance, a self-managed cluster, and ClickHouse Cloud.",[545,562,563,564,568,569,572],{},"The default schema gives you ",[565,566,567],"strong",{},"typed columns"," for the fields you filter and aggregate on, plus the complete wide event as JSON in ",[557,570,571],{},"data",", so no field is ever lost, and adding a field to your events never requires a migration.",[574,575,578,581,611],"prompt",{":actions":576,"description":577,"icon":189},"[\"copy\",\"cursor\",\"claude\"]","Add the ClickHouse drain adapter",[545,579,580],{},"Add the ClickHouse drain adapter to store evlog wide events in ClickHouse.",[582,583,584,588,591,594,597,600,608],"ol",{},[585,586,587],"li",{},"Identify which framework I'm using and follow its evlog integration pattern",[585,589,590],{},"Install evlog if not already installed",[585,592,593],{},"Create the evlog_events table using the CREATE TABLE from the adapter docs",[585,595,596],{},"Import createClickHouseDrain from 'evlog\u002Fclickhouse'",[585,598,599],{},"Wire createClickHouseDrain() into my framework's drain configuration",[585,601,602,603,607],{},"Set CLICKHOUSE_ENDPOINT (e.g. ",[549,604,605],{"href":605,"rel":606},"http:\u002F\u002Flocalhost:8123",[553],"), plus CLICKHOUSE_USER \u002F CLICKHOUSE_PASSWORD if authenticated",[585,609,610],{},"Test by triggering a request and running SELECT * FROM evlog_events ORDER BY timestamp DESC LIMIT 10",[545,612,613,614,618,619],{},"Adapter docs: ",[549,615,616],{"href":616,"rel":617},"https:\u002F\u002Fwww.evlog.dev\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fclickhouse",[553],"\nFramework setup: ",[549,620,621],{"href":621,"rel":622},"https:\u002F\u002Fwww.evlog.dev\u002Fintegrate\u002Fframeworks\u002Foverview",[553],[624,625,20],"h2",{"id":626},"installation",[545,628,629],{},"The ClickHouse adapter comes bundled with evlog:",[631,632,638],"pre",{"className":633,"code":634,"filename":635,"language":636,"meta":637,"style":637},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { createClickHouseDrain } from 'evlog\u002Fclickhouse'\n","src\u002Findex.ts","typescript","",[557,639,640],{"__ignoreMap":637},[641,642,645,649,653,657,660,663,666,670],"span",{"class":643,"line":644},"line",1,[641,646,648],{"class":647},"s7zQu","import",[641,650,652],{"class":651},"sMK4o"," {",[641,654,656],{"class":655},"sTEyZ"," createClickHouseDrain",[641,658,659],{"class":651}," }",[641,661,662],{"class":647}," from",[641,664,665],{"class":651}," '",[641,667,669],{"class":668},"sfazB","evlog\u002Fclickhouse",[641,671,672],{"class":651},"'\n",[624,674,676],{"id":675},"create-the-table","Create the table",[545,678,679],{},"Run this once before wiring the drain:",[631,681,686],{"className":682,"code":683,"filename":684,"language":685,"meta":637,"style":637},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","CREATE TABLE IF NOT EXISTS evlog_events\n(\n  timestamp     DateTime64(3, 'UTC'),\n  level         LowCardinality(String),\n  service       LowCardinality(String),\n  environment   LowCardinality(String),\n  request_id    String,\n  trace_id      String,\n  span_id       String,\n  method        LowCardinality(String),\n  path          String,\n  status        Nullable(UInt16),\n  duration      String,\n  duration_ms   Nullable(UInt32),\n  error_name    String,\n  error_message String,\n  data          String\n)\nENGINE = MergeTree\nPARTITION BY toYYYYMM(timestamp)\nORDER BY (service, environment, timestamp)\nTTL toDateTime(timestamp) + INTERVAL 30 DAY;\n","schema.sql","sql",[557,687,688,710,716,743,752,761,767,773,779,785,791,800,809,815,821,827,833,842,848,860,877,896],{"__ignoreMap":637},[641,689,690,694,697,701,704,707],{"class":643,"line":644},[641,691,693],{"class":692},"sbssI","CREATE",[641,695,696],{"class":692}," TABLE",[641,698,700],{"class":699},"s2Zo4"," IF",[641,702,703],{"class":692}," NOT",[641,705,706],{"class":692}," EXISTS",[641,708,709],{"class":655}," evlog_events\n",[641,711,713],{"class":643,"line":712},2,[641,714,715],{"class":655},"(\n",[641,717,719,723,726,729,732,735,738,740],{"class":643,"line":718},3,[641,720,722],{"class":721},"spNyl","  timestamp",[641,724,725],{"class":655},"     DateTime64(",[641,727,728],{"class":692},"3",[641,730,731],{"class":655},", ",[641,733,734],{"class":651},"'",[641,736,737],{"class":668},"UTC",[641,739,734],{"class":651},[641,741,742],{"class":655},"),\n",[641,744,746,749],{"class":643,"line":745},4,[641,747,748],{"class":692},"  level",[641,750,751],{"class":655},"         LowCardinality(String),\n",[641,753,755,758],{"class":643,"line":754},5,[641,756,757],{"class":692},"  service",[641,759,760],{"class":655},"       LowCardinality(String),\n",[641,762,764],{"class":643,"line":763},6,[641,765,766],{"class":655},"  environment   LowCardinality(String),\n",[641,768,770],{"class":643,"line":769},7,[641,771,772],{"class":655},"  request_id    String,\n",[641,774,776],{"class":643,"line":775},8,[641,777,778],{"class":655},"  trace_id      String,\n",[641,780,782],{"class":643,"line":781},9,[641,783,784],{"class":655},"  span_id       String,\n",[641,786,788],{"class":643,"line":787},10,[641,789,790],{"class":655},"  method        LowCardinality(String),\n",[641,792,794,797],{"class":643,"line":793},11,[641,795,796],{"class":721},"  path",[641,798,799],{"class":655},"          String,\n",[641,801,803,806],{"class":643,"line":802},12,[641,804,805],{"class":692},"  status",[641,807,808],{"class":655},"        Nullable(UInt16),\n",[641,810,812],{"class":643,"line":811},13,[641,813,814],{"class":655},"  duration      String,\n",[641,816,818],{"class":643,"line":817},14,[641,819,820],{"class":655},"  duration_ms   Nullable(UInt32),\n",[641,822,824],{"class":643,"line":823},15,[641,825,826],{"class":655},"  error_name    String,\n",[641,828,830],{"class":643,"line":829},16,[641,831,832],{"class":655},"  error_message String,\n",[641,834,836,839],{"class":643,"line":835},17,[641,837,838],{"class":692},"  data",[641,840,841],{"class":655},"          String\n",[641,843,845],{"class":643,"line":844},18,[641,846,847],{"class":655},")\n",[641,849,851,854,857],{"class":643,"line":850},19,[641,852,853],{"class":655},"ENGINE ",[641,855,856],{"class":651},"=",[641,858,859],{"class":655}," MergeTree\n",[641,861,863,866,869,872,875],{"class":643,"line":862},20,[641,864,865],{"class":692},"PARTITION",[641,867,868],{"class":692}," BY",[641,870,871],{"class":655}," toYYYYMM(",[641,873,874],{"class":721},"timestamp",[641,876,847],{"class":655},[641,878,880,883,886,889,892,894],{"class":643,"line":879},21,[641,881,882],{"class":692},"ORDER BY",[641,884,885],{"class":655}," (",[641,887,888],{"class":692},"service",[641,890,891],{"class":655},", environment, ",[641,893,874],{"class":721},[641,895,847],{"class":655},[641,897,899,902,904,907,910,913,916,919],{"class":643,"line":898},22,[641,900,901],{"class":655},"TTL toDateTime(",[641,903,874],{"class":721},[641,905,906],{"class":655},") ",[641,908,909],{"class":651},"+",[641,911,912],{"class":655}," INTERVAL ",[641,914,915],{"class":692},"30",[641,917,918],{"class":692}," DAY",[641,920,921],{"class":655},";\n",[923,924,926,929,930,933],"callout",{"color":925,"icon":13},"info",[557,927,928],{},"ORDER BY (service, environment, timestamp)"," matches how you'll filter most often. Adjust the ",[557,931,932],{},"TTL"," to your retention policy, and drop the clause entirely to keep events forever.",[624,935,25],{"id":936},"quick-start",[938,939,940,1046,1167,1271,1378,1483,1618],"code-group",{},[631,941,944],{"className":633,"code":942,"filename":943,"language":636,"meta":637,"style":637},"\u002F\u002F server\u002Fplugins\u002Fevlog.ts\nimport { createClickHouseDrain } from 'evlog\u002Fclickhouse'\n\nexport default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook('evlog:drain', createClickHouseDrain())\n})\n","Nuxt \u002F Nitro",[557,945,946,952,970,976,1005,1039],{"__ignoreMap":637},[641,947,948],{"class":643,"line":644},[641,949,951],{"class":950},"sHwdD","\u002F\u002F server\u002Fplugins\u002Fevlog.ts\n",[641,953,954,956,958,960,962,964,966,968],{"class":643,"line":712},[641,955,648],{"class":647},[641,957,652],{"class":651},[641,959,656],{"class":655},[641,961,659],{"class":651},[641,963,662],{"class":647},[641,965,665],{"class":651},[641,967,669],{"class":668},[641,969,672],{"class":651},[641,971,972],{"class":643,"line":718},[641,973,975],{"emptyLinePlaceholder":974},true,"\n",[641,977,978,981,984,987,990,992,996,999,1002],{"class":643,"line":745},[641,979,980],{"class":647},"export",[641,982,983],{"class":647}," default",[641,985,986],{"class":699}," defineNitroPlugin",[641,988,989],{"class":655},"(",[641,991,989],{"class":651},[641,993,995],{"class":994},"sHdIc","nitroApp",[641,997,998],{"class":651},")",[641,1000,1001],{"class":721}," =>",[641,1003,1004],{"class":651}," {\n",[641,1006,1007,1010,1013,1016,1018,1021,1024,1026,1029,1031,1034,1036],{"class":643,"line":754},[641,1008,1009],{"class":655},"  nitroApp",[641,1011,1012],{"class":651},".",[641,1014,1015],{"class":655},"hooks",[641,1017,1012],{"class":651},[641,1019,1020],{"class":699},"hook",[641,1022,989],{"class":1023},"swJcz",[641,1025,734],{"class":651},[641,1027,1028],{"class":668},"evlog:drain",[641,1030,734],{"class":651},[641,1032,1033],{"class":651},",",[641,1035,656],{"class":699},[641,1037,1038],{"class":1023},"())\n",[641,1040,1041,1044],{"class":643,"line":763},[641,1042,1043],{"class":651},"}",[641,1045,847],{"class":655},[631,1047,1049],{"className":633,"code":1048,"filename":265,"language":636,"meta":637,"style":637},"import { Hono } from 'hono'\nimport { evlog } from 'evlog\u002Fhono'\nimport { createClickHouseDrain } from 'evlog\u002Fclickhouse'\n\nconst app = new Hono()\napp.use(evlog({ drain: createClickHouseDrain() }))\n",[557,1050,1051,1071,1091,1109,1113,1131],{"__ignoreMap":637},[641,1052,1053,1055,1057,1060,1062,1064,1066,1069],{"class":643,"line":644},[641,1054,648],{"class":647},[641,1056,652],{"class":651},[641,1058,1059],{"class":655}," Hono",[641,1061,659],{"class":651},[641,1063,662],{"class":647},[641,1065,665],{"class":651},[641,1067,1068],{"class":668},"hono",[641,1070,672],{"class":651},[641,1072,1073,1075,1077,1080,1082,1084,1086,1089],{"class":643,"line":712},[641,1074,648],{"class":647},[641,1076,652],{"class":651},[641,1078,1079],{"class":655}," evlog",[641,1081,659],{"class":651},[641,1083,662],{"class":647},[641,1085,665],{"class":651},[641,1087,1088],{"class":668},"evlog\u002Fhono",[641,1090,672],{"class":651},[641,1092,1093,1095,1097,1099,1101,1103,1105,1107],{"class":643,"line":718},[641,1094,648],{"class":647},[641,1096,652],{"class":651},[641,1098,656],{"class":655},[641,1100,659],{"class":651},[641,1102,662],{"class":647},[641,1104,665],{"class":651},[641,1106,669],{"class":668},[641,1108,672],{"class":651},[641,1110,1111],{"class":643,"line":745},[641,1112,975],{"emptyLinePlaceholder":974},[641,1114,1115,1118,1121,1123,1126,1128],{"class":643,"line":754},[641,1116,1117],{"class":721},"const",[641,1119,1120],{"class":655}," app ",[641,1122,856],{"class":651},[641,1124,1125],{"class":651}," new",[641,1127,1059],{"class":699},[641,1129,1130],{"class":655},"()\n",[641,1132,1133,1136,1138,1141,1143,1146,1148,1151,1154,1157,1159,1162,1164],{"class":643,"line":763},[641,1134,1135],{"class":655},"app",[641,1137,1012],{"class":651},[641,1139,1140],{"class":699},"use",[641,1142,989],{"class":655},[641,1144,1145],{"class":699},"evlog",[641,1147,989],{"class":655},[641,1149,1150],{"class":651},"{",[641,1152,1153],{"class":1023}," drain",[641,1155,1156],{"class":651},":",[641,1158,656],{"class":699},[641,1160,1161],{"class":655},"() ",[641,1163,1043],{"class":651},[641,1165,1166],{"class":655},"))\n",[631,1168,1170],{"className":633,"code":1169,"filename":260,"language":636,"meta":637,"style":637},"import express from 'express'\nimport { evlog } from 'evlog\u002Fexpress'\nimport { createClickHouseDrain } from 'evlog\u002Fclickhouse'\n\nconst app = express()\napp.use(evlog({ drain: createClickHouseDrain() }))\n",[557,1171,1172,1189,1208,1226,1230,1243],{"__ignoreMap":637},[641,1173,1174,1176,1179,1182,1184,1187],{"class":643,"line":644},[641,1175,648],{"class":647},[641,1177,1178],{"class":655}," express ",[641,1180,1181],{"class":647},"from",[641,1183,665],{"class":651},[641,1185,1186],{"class":668},"express",[641,1188,672],{"class":651},[641,1190,1191,1193,1195,1197,1199,1201,1203,1206],{"class":643,"line":712},[641,1192,648],{"class":647},[641,1194,652],{"class":651},[641,1196,1079],{"class":655},[641,1198,659],{"class":651},[641,1200,662],{"class":647},[641,1202,665],{"class":651},[641,1204,1205],{"class":668},"evlog\u002Fexpress",[641,1207,672],{"class":651},[641,1209,1210,1212,1214,1216,1218,1220,1222,1224],{"class":643,"line":718},[641,1211,648],{"class":647},[641,1213,652],{"class":651},[641,1215,656],{"class":655},[641,1217,659],{"class":651},[641,1219,662],{"class":647},[641,1221,665],{"class":651},[641,1223,669],{"class":668},[641,1225,672],{"class":651},[641,1227,1228],{"class":643,"line":745},[641,1229,975],{"emptyLinePlaceholder":974},[641,1231,1232,1234,1236,1238,1241],{"class":643,"line":754},[641,1233,1117],{"class":721},[641,1235,1120],{"class":655},[641,1237,856],{"class":651},[641,1239,1240],{"class":699}," express",[641,1242,1130],{"class":655},[641,1244,1245,1247,1249,1251,1253,1255,1257,1259,1261,1263,1265,1267,1269],{"class":643,"line":763},[641,1246,1135],{"class":655},[641,1248,1012],{"class":651},[641,1250,1140],{"class":699},[641,1252,989],{"class":655},[641,1254,1145],{"class":699},[641,1256,989],{"class":655},[641,1258,1150],{"class":651},[641,1260,1153],{"class":1023},[641,1262,1156],{"class":651},[641,1264,656],{"class":699},[641,1266,1161],{"class":655},[641,1268,1043],{"class":651},[641,1270,1166],{"class":655},[631,1272,1274],{"className":633,"code":1273,"filename":270,"language":636,"meta":637,"style":637},"import Fastify from 'fastify'\nimport { evlog } from 'evlog\u002Ffastify'\nimport { createClickHouseDrain } from 'evlog\u002Fclickhouse'\n\nconst app = Fastify()\nawait app.register(evlog, { drain: createClickHouseDrain() })\n",[557,1275,1276,1292,1311,1329,1333,1346],{"__ignoreMap":637},[641,1277,1278,1280,1283,1285,1287,1290],{"class":643,"line":644},[641,1279,648],{"class":647},[641,1281,1282],{"class":655}," Fastify ",[641,1284,1181],{"class":647},[641,1286,665],{"class":651},[641,1288,1289],{"class":668},"fastify",[641,1291,672],{"class":651},[641,1293,1294,1296,1298,1300,1302,1304,1306,1309],{"class":643,"line":712},[641,1295,648],{"class":647},[641,1297,652],{"class":651},[641,1299,1079],{"class":655},[641,1301,659],{"class":651},[641,1303,662],{"class":647},[641,1305,665],{"class":651},[641,1307,1308],{"class":668},"evlog\u002Ffastify",[641,1310,672],{"class":651},[641,1312,1313,1315,1317,1319,1321,1323,1325,1327],{"class":643,"line":718},[641,1314,648],{"class":647},[641,1316,652],{"class":651},[641,1318,656],{"class":655},[641,1320,659],{"class":651},[641,1322,662],{"class":647},[641,1324,665],{"class":651},[641,1326,669],{"class":668},[641,1328,672],{"class":651},[641,1330,1331],{"class":643,"line":745},[641,1332,975],{"emptyLinePlaceholder":974},[641,1334,1335,1337,1339,1341,1344],{"class":643,"line":754},[641,1336,1117],{"class":721},[641,1338,1120],{"class":655},[641,1340,856],{"class":651},[641,1342,1343],{"class":699}," Fastify",[641,1345,1130],{"class":655},[641,1347,1348,1351,1354,1356,1359,1362,1364,1366,1368,1370,1372,1374,1376],{"class":643,"line":763},[641,1349,1350],{"class":647},"await",[641,1352,1353],{"class":655}," app",[641,1355,1012],{"class":651},[641,1357,1358],{"class":699},"register",[641,1360,1361],{"class":655},"(evlog",[641,1363,1033],{"class":651},[641,1365,652],{"class":651},[641,1367,1153],{"class":1023},[641,1369,1156],{"class":651},[641,1371,656],{"class":699},[641,1373,1161],{"class":655},[641,1375,1043],{"class":651},[641,1377,847],{"class":655},[631,1379,1381],{"className":633,"code":1380,"filename":275,"language":636,"meta":637,"style":637},"import { Elysia } from 'elysia'\nimport { evlog } from 'evlog\u002Felysia'\nimport { createClickHouseDrain } from 'evlog\u002Fclickhouse'\n\nconst app = new Elysia().use(evlog({ drain: createClickHouseDrain() }))\n",[557,1382,1383,1403,1422,1440,1444],{"__ignoreMap":637},[641,1384,1385,1387,1389,1392,1394,1396,1398,1401],{"class":643,"line":644},[641,1386,648],{"class":647},[641,1388,652],{"class":651},[641,1390,1391],{"class":655}," Elysia",[641,1393,659],{"class":651},[641,1395,662],{"class":647},[641,1397,665],{"class":651},[641,1399,1400],{"class":668},"elysia",[641,1402,672],{"class":651},[641,1404,1405,1407,1409,1411,1413,1415,1417,1420],{"class":643,"line":712},[641,1406,648],{"class":647},[641,1408,652],{"class":651},[641,1410,1079],{"class":655},[641,1412,659],{"class":651},[641,1414,662],{"class":647},[641,1416,665],{"class":651},[641,1418,1419],{"class":668},"evlog\u002Felysia",[641,1421,672],{"class":651},[641,1423,1424,1426,1428,1430,1432,1434,1436,1438],{"class":643,"line":718},[641,1425,648],{"class":647},[641,1427,652],{"class":651},[641,1429,656],{"class":655},[641,1431,659],{"class":651},[641,1433,662],{"class":647},[641,1435,665],{"class":651},[641,1437,669],{"class":668},[641,1439,672],{"class":651},[641,1441,1442],{"class":643,"line":745},[641,1443,975],{"emptyLinePlaceholder":974},[641,1445,1446,1448,1450,1452,1454,1456,1459,1461,1463,1465,1467,1469,1471,1473,1475,1477,1479,1481],{"class":643,"line":754},[641,1447,1117],{"class":721},[641,1449,1120],{"class":655},[641,1451,856],{"class":651},[641,1453,1125],{"class":651},[641,1455,1391],{"class":699},[641,1457,1458],{"class":655},"()",[641,1460,1012],{"class":651},[641,1462,1140],{"class":699},[641,1464,989],{"class":655},[641,1466,1145],{"class":699},[641,1468,989],{"class":655},[641,1470,1150],{"class":651},[641,1472,1153],{"class":1023},[641,1474,1156],{"class":651},[641,1476,656],{"class":699},[641,1478,1161],{"class":655},[641,1480,1043],{"class":651},[641,1482,1166],{"class":655},[631,1484,1486],{"className":633,"code":1485,"filename":255,"language":636,"meta":637,"style":637},"import { Module } from '@nestjs\u002Fcommon'\nimport { EvlogModule } from 'evlog\u002Fnestjs'\nimport { createClickHouseDrain } from 'evlog\u002Fclickhouse'\n\n@Module({\n  imports: [EvlogModule.forRoot({ drain: createClickHouseDrain() })],\n})\nexport class AppModule {}\n",[557,1487,1488,1508,1528,1546,1550,1563,1598,1604],{"__ignoreMap":637},[641,1489,1490,1492,1494,1497,1499,1501,1503,1506],{"class":643,"line":644},[641,1491,648],{"class":647},[641,1493,652],{"class":651},[641,1495,1496],{"class":655}," Module",[641,1498,659],{"class":651},[641,1500,662],{"class":647},[641,1502,665],{"class":651},[641,1504,1505],{"class":668},"@nestjs\u002Fcommon",[641,1507,672],{"class":651},[641,1509,1510,1512,1514,1517,1519,1521,1523,1526],{"class":643,"line":712},[641,1511,648],{"class":647},[641,1513,652],{"class":651},[641,1515,1516],{"class":655}," EvlogModule",[641,1518,659],{"class":651},[641,1520,662],{"class":647},[641,1522,665],{"class":651},[641,1524,1525],{"class":668},"evlog\u002Fnestjs",[641,1527,672],{"class":651},[641,1529,1530,1532,1534,1536,1538,1540,1542,1544],{"class":643,"line":718},[641,1531,648],{"class":647},[641,1533,652],{"class":651},[641,1535,656],{"class":655},[641,1537,659],{"class":651},[641,1539,662],{"class":647},[641,1541,665],{"class":651},[641,1543,669],{"class":668},[641,1545,672],{"class":651},[641,1547,1548],{"class":643,"line":745},[641,1549,975],{"emptyLinePlaceholder":974},[641,1551,1552,1555,1558,1560],{"class":643,"line":754},[641,1553,1554],{"class":651},"@",[641,1556,1557],{"class":699},"Module",[641,1559,989],{"class":655},[641,1561,1562],{"class":651},"{\n",[641,1564,1565,1568,1570,1573,1575,1578,1580,1582,1584,1586,1588,1590,1592,1595],{"class":643,"line":763},[641,1566,1567],{"class":1023},"  imports",[641,1569,1156],{"class":651},[641,1571,1572],{"class":655}," [EvlogModule",[641,1574,1012],{"class":651},[641,1576,1577],{"class":699},"forRoot",[641,1579,989],{"class":655},[641,1581,1150],{"class":651},[641,1583,1153],{"class":1023},[641,1585,1156],{"class":651},[641,1587,656],{"class":699},[641,1589,1161],{"class":655},[641,1591,1043],{"class":651},[641,1593,1594],{"class":655},")]",[641,1596,1597],{"class":651},",\n",[641,1599,1600,1602],{"class":643,"line":769},[641,1601,1043],{"class":651},[641,1603,847],{"class":655},[641,1605,1606,1608,1611,1615],{"class":643,"line":775},[641,1607,980],{"class":647},[641,1609,1610],{"class":721}," class",[641,1612,1614],{"class":1613},"sBMFI"," AppModule",[641,1616,1617],{"class":651}," {}\n",[631,1619,1621],{"className":633,"code":1620,"filename":290,"language":636,"meta":637,"style":637},"import { initLogger } from 'evlog'\nimport { createClickHouseDrain } from 'evlog\u002Fclickhouse'\n\ninitLogger({\n  env: { service: 'my-app' },\n  drain: createClickHouseDrain(),\n})\n",[557,1622,1623,1642,1660,1664,1673,1697,1710],{"__ignoreMap":637},[641,1624,1625,1627,1629,1632,1634,1636,1638,1640],{"class":643,"line":644},[641,1626,648],{"class":647},[641,1628,652],{"class":651},[641,1630,1631],{"class":655}," initLogger",[641,1633,659],{"class":651},[641,1635,662],{"class":647},[641,1637,665],{"class":651},[641,1639,1145],{"class":668},[641,1641,672],{"class":651},[641,1643,1644,1646,1648,1650,1652,1654,1656,1658],{"class":643,"line":712},[641,1645,648],{"class":647},[641,1647,652],{"class":651},[641,1649,656],{"class":655},[641,1651,659],{"class":651},[641,1653,662],{"class":647},[641,1655,665],{"class":651},[641,1657,669],{"class":668},[641,1659,672],{"class":651},[641,1661,1662],{"class":643,"line":718},[641,1663,975],{"emptyLinePlaceholder":974},[641,1665,1666,1669,1671],{"class":643,"line":745},[641,1667,1668],{"class":699},"initLogger",[641,1670,989],{"class":655},[641,1672,1562],{"class":651},[641,1674,1675,1678,1680,1682,1685,1687,1689,1692,1694],{"class":643,"line":754},[641,1676,1677],{"class":1023},"  env",[641,1679,1156],{"class":651},[641,1681,652],{"class":651},[641,1683,1684],{"class":1023}," service",[641,1686,1156],{"class":651},[641,1688,665],{"class":651},[641,1690,1691],{"class":668},"my-app",[641,1693,734],{"class":651},[641,1695,1696],{"class":651}," },\n",[641,1698,1699,1702,1704,1706,1708],{"class":643,"line":763},[641,1700,1701],{"class":1023},"  drain",[641,1703,1156],{"class":651},[641,1705,656],{"class":699},[641,1707,1458],{"class":655},[641,1709,1597],{"class":651},[641,1711,1712,1714],{"class":643,"line":769},[641,1713,1043],{"class":651},[641,1715,847],{"class":655},[624,1717,508],{"id":1718},"configuration",[1720,1721,1723],"h3",{"id":1722},"environment-variables","Environment variables",[1725,1726,1727,1743],"table",{},[1728,1729,1730],"thead",{},[1731,1732,1733,1737,1740],"tr",{},[1734,1735,1736],"th",{},"Variable",[1734,1738,1739],{},"Required",[1734,1741,1742],{},"Description",[1744,1745,1746,1764,1780,1792,1806],"tbody",{},[1731,1747,1748,1754,1757],{},[1749,1750,1751],"td",{},[557,1752,1753],{},"CLICKHOUSE_ENDPOINT",[1749,1755,1756],{},"Yes",[1749,1758,1759,1760,1763],{},"HTTP interface URL (",[557,1761,1762],{},"CLICKHOUSE_URL"," also accepted)",[1731,1765,1766,1771,1774],{},[1749,1767,1768],{},[557,1769,1770],{},"CLICKHOUSE_USER",[1749,1772,1773],{},"No",[1749,1775,1776,1777],{},"Username. Default ",[557,1778,1779],{},"default",[1731,1781,1782,1787,1789],{},[1749,1783,1784],{},[557,1785,1786],{},"CLICKHOUSE_PASSWORD",[1749,1788,1773],{},[1749,1790,1791],{},"Password. Omit for an unauthenticated local instance",[1731,1793,1794,1799,1801],{},[1749,1795,1796],{},[557,1797,1798],{},"CLICKHOUSE_DATABASE",[1749,1800,1773],{},[1749,1802,1803,1804],{},"Database. Default ",[557,1805,1779],{},[1731,1807,1808,1813,1815],{},[1749,1809,1810],{},[557,1811,1812],{},"CLICKHOUSE_TABLE",[1749,1814,1773],{},[1749,1816,1817,1818],{},"Table. Default ",[557,1819,1820],{},"evlog_events",[1720,1822,336],{"id":1823},"options",[1725,1825,1826,1841],{},[1728,1827,1828],{},[1731,1829,1830,1833,1836,1839],{},[1734,1831,1832],{},"Option",[1734,1834,1835],{},"Type",[1734,1837,1838],{},"Default",[1734,1840,1742],{},[1744,1842,1843,1861,1879,1896,1914,1930,1950,1969,1989,2009],{},[1731,1844,1845,1850,1855,1858],{},[1749,1846,1847],{},[557,1848,1849],{},"endpoint",[1749,1851,1852],{},[557,1853,1854],{},"string",[1749,1856,1857],{},"—",[1749,1859,1860],{},"HTTP interface URL",[1731,1862,1863,1868,1872,1876],{},[1749,1864,1865],{},[557,1866,1867],{},"database",[1749,1869,1870],{},[557,1871,1854],{},[1749,1873,1874],{},[557,1875,1779],{},[1749,1877,1878],{},"Target database",[1731,1880,1881,1885,1889,1893],{},[1749,1882,1883],{},[557,1884,1725],{},[1749,1886,1887],{},[557,1888,1854],{},[1749,1890,1891],{},[557,1892,1820],{},[1749,1894,1895],{},"Target table",[1731,1897,1898,1903,1907,1911],{},[1749,1899,1900],{},[557,1901,1902],{},"username",[1749,1904,1905],{},[557,1906,1854],{},[1749,1908,1909],{},[557,1910,1779],{},[1749,1912,1913],{},"Username",[1731,1915,1916,1921,1925,1927],{},[1749,1917,1918],{},[557,1919,1920],{},"password",[1749,1922,1923],{},[557,1924,1854],{},[1749,1926,1857],{},[1749,1928,1929],{},"Password",[1731,1931,1932,1937,1942,1947],{},[1749,1933,1934],{},[557,1935,1936],{},"asyncInsert",[1749,1938,1939],{},[557,1940,1941],{},"boolean",[1749,1943,1944],{},[557,1945,1946],{},"true",[1749,1948,1949],{},"Batch inserts server-side",[1731,1951,1952,1957,1961,1966],{},[1749,1953,1954],{},[557,1955,1956],{},"waitForAsyncInsert",[1749,1958,1959],{},[557,1960,1941],{},[1749,1962,1963],{},[557,1964,1965],{},"false",[1749,1967,1968],{},"Wait for the flush before responding",[1731,1970,1971,1976,1981,1986],{},[1749,1972,1973],{},[557,1974,1975],{},"transform",[1749,1977,1978],{},[557,1979,1980],{},"(event) => Record\u003Cstring, unknown>",[1749,1982,1983],{},[557,1984,1985],{},"toClickHouseRow",[1749,1987,1988],{},"Map an event to a row",[1731,1990,1991,1996,2001,2006],{},[1749,1992,1993],{},[557,1994,1995],{},"timeout",[1749,1997,1998],{},[557,1999,2000],{},"number",[1749,2002,2003],{},[557,2004,2005],{},"5000",[1749,2007,2008],{},"Request timeout in ms",[1731,2010,2011,2016,2020,2025],{},[1749,2012,2013],{},[557,2014,2015],{},"retries",[1749,2017,2018],{},[557,2019,2000],{},[1749,2021,2022],{},[557,2023,2024],{},"2",[1749,2026,2027],{},"Retry attempts",[624,2029,2031],{"id":2030},"deployment","Deployment",[545,2033,2034],{},"The adapter is identical either way. Only the endpoint and credentials change.",[1720,2036,2038],{"id":2037},"self-hosted","Self-hosted",[545,2040,2041],{},"A local or self-managed instance, with or without auth:",[631,2043,2046],{"className":633,"code":2044,"filename":2045,"language":636,"meta":637,"style":637},"createClickHouseDrain({ endpoint: 'http:\u002F\u002Flocalhost:8123' })\n","server\u002Fplugins\u002Fevlog.ts",[557,2047,2048],{"__ignoreMap":637},[641,2049,2050,2053,2055,2057,2060,2062,2064,2066,2068,2070],{"class":643,"line":644},[641,2051,2052],{"class":699},"createClickHouseDrain",[641,2054,989],{"class":655},[641,2056,1150],{"class":651},[641,2058,2059],{"class":1023}," endpoint",[641,2061,1156],{"class":651},[641,2063,665],{"class":651},[641,2065,605],{"class":668},[641,2067,734],{"class":651},[641,2069,659],{"class":651},[641,2071,847],{"class":655},[631,2073,2078],{"className":2074,"code":2075,"filename":2076,"language":2077,"meta":637,"style":637},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","CLICKHOUSE_ENDPOINT=http:\u002F\u002Flocalhost:8123\n# Only if your instance requires auth:\nCLICKHOUSE_USER=evlog\nCLICKHOUSE_PASSWORD=your-password\n",".env","bash",[557,2079,2080,2089,2094,2103],{"__ignoreMap":637},[641,2081,2082,2084,2086],{"class":643,"line":644},[641,2083,1753],{"class":655},[641,2085,856],{"class":651},[641,2087,2088],{"class":668},"http:\u002F\u002Flocalhost:8123\n",[641,2090,2091],{"class":643,"line":712},[641,2092,2093],{"class":950},"# Only if your instance requires auth:\n",[641,2095,2096,2098,2100],{"class":643,"line":718},[641,2097,1770],{"class":655},[641,2099,856],{"class":651},[641,2101,2102],{"class":668},"evlog\n",[641,2104,2105,2107,2109],{"class":643,"line":745},[641,2106,1786],{"class":655},[641,2108,856],{"class":651},[641,2110,2111],{"class":668},"your-password\n",[545,2113,2114,2115,2117,2118,2120,2121,2123,2124,2126],{},"A fresh container runs as ",[557,2116,1779],{}," with no password, which is why ",[557,2119,1902],{},"\ndefaults to ",[557,2122,1779],{}," and ",[557,2125,1920],{}," is optional.",[1720,2128,2130],{"id":2129},"clickhouse-cloud","ClickHouse Cloud",[545,2132,2133],{},"Cloud services always require credentials and speak HTTPS on port 8443:",[631,2135,2137],{"className":633,"code":2136,"filename":2045,"language":636,"meta":637,"style":637},"createClickHouseDrain({\n  endpoint: 'https:\u002F\u002Fabc123.eu-west-1.aws.clickhouse.cloud:8443',\n  password: process.env.CLICKHOUSE_PASSWORD,\n  database: 'logs',\n})\n",[557,2138,2139,2147,2163,2184,2200],{"__ignoreMap":637},[641,2140,2141,2143,2145],{"class":643,"line":644},[641,2142,2052],{"class":699},[641,2144,989],{"class":655},[641,2146,1562],{"class":651},[641,2148,2149,2152,2154,2156,2159,2161],{"class":643,"line":712},[641,2150,2151],{"class":1023},"  endpoint",[641,2153,1156],{"class":651},[641,2155,665],{"class":651},[641,2157,2158],{"class":668},"https:\u002F\u002Fabc123.eu-west-1.aws.clickhouse.cloud:8443",[641,2160,734],{"class":651},[641,2162,1597],{"class":651},[641,2164,2165,2168,2170,2173,2175,2178,2180,2182],{"class":643,"line":718},[641,2166,2167],{"class":1023},"  password",[641,2169,1156],{"class":651},[641,2171,2172],{"class":655}," process",[641,2174,1012],{"class":651},[641,2176,2177],{"class":655},"env",[641,2179,1012],{"class":651},[641,2181,1786],{"class":655},[641,2183,1597],{"class":651},[641,2185,2186,2189,2191,2193,2196,2198],{"class":643,"line":745},[641,2187,2188],{"class":1023},"  database",[641,2190,1156],{"class":651},[641,2192,665],{"class":651},[641,2194,2195],{"class":668},"logs",[641,2197,734],{"class":651},[641,2199,1597],{"class":651},[641,2201,2202,2204],{"class":643,"line":754},[641,2203,1043],{"class":651},[641,2205,847],{"class":655},[631,2207,2209],{"className":2074,"code":2208,"filename":2076,"language":2077,"meta":637,"style":637},"CLICKHOUSE_ENDPOINT=https:\u002F\u002Fabc123.eu-west-1.aws.clickhouse.cloud:8443\nCLICKHOUSE_PASSWORD=your-service-password\nCLICKHOUSE_DATABASE=logs\n",[557,2210,2211,2220,2229],{"__ignoreMap":637},[641,2212,2213,2215,2217],{"class":643,"line":644},[641,2214,1753],{"class":655},[641,2216,856],{"class":651},[641,2218,2219],{"class":668},"https:\u002F\u002Fabc123.eu-west-1.aws.clickhouse.cloud:8443\n",[641,2221,2222,2224,2226],{"class":643,"line":712},[641,2223,1786],{"class":655},[641,2225,856],{"class":651},[641,2227,2228],{"class":668},"your-service-password\n",[641,2230,2231,2233,2235],{"class":643,"line":718},[641,2232,1798],{"class":655},[641,2234,856],{"class":651},[641,2236,2237],{"class":668},"logs\n",[923,2239,2240,2241,2245,2246,2249,2250,2252],{"color":925,"icon":13},"Copy the endpoint from ",[2242,2243,2244],"em",{},"Connect → HTTPS"," in the ClickHouse Cloud console,\nincluding the ",[557,2247,2248],{},":8443"," port. Cloud services idle-suspend, so the first insert\nafter a pause can take a few seconds; raise ",[557,2251,1995],{}," if you see aborts.",[923,2254,2256,2257,2260,2261,2264,2265,2268,2269,2272],{"color":2255,"icon":379},"success","Credentials are sent as ",[557,2258,2259],{},"X-ClickHouse-User"," \u002F ",[557,2262,2263],{},"X-ClickHouse-Key"," ",[565,2266,2267],{},"headers",",\nnever as query parameters, so they never reach ",[557,2270,2271],{},"system.query_log"," or an\nintermediate proxy's access log.",[624,2274,2276],{"id":2275},"verify-it-locally","Verify it locally",[545,2278,2279],{},"Spin up ClickHouse in Docker, create the table and push a real event:",[631,2281,2284],{"className":2074,"code":2282,"filename":2283,"language":2077,"meta":637,"style":637},"docker compose -f packages\u002Fevlog\u002Ftest\u002Fe2e\u002Fdocker-compose.yml up -d\nCLICKHOUSE_ENDPOINT=http:\u002F\u002Flocalhost:8123 pnpm run test:e2e\ndocker compose -f packages\u002Fevlog\u002Ftest\u002Fe2e\u002Fdocker-compose.yml down -v\n","Terminal",[557,2285,2286,2306,2323],{"__ignoreMap":637},[641,2287,2288,2291,2294,2297,2300,2303],{"class":643,"line":644},[641,2289,2290],{"class":1613},"docker",[641,2292,2293],{"class":668}," compose",[641,2295,2296],{"class":668}," -f",[641,2298,2299],{"class":668}," packages\u002Fevlog\u002Ftest\u002Fe2e\u002Fdocker-compose.yml",[641,2301,2302],{"class":668}," up",[641,2304,2305],{"class":668}," -d\n",[641,2307,2308,2310,2312,2314,2317,2320],{"class":643,"line":712},[641,2309,1753],{"class":655},[641,2311,856],{"class":651},[641,2313,605],{"class":668},[641,2315,2316],{"class":1613}," pnpm",[641,2318,2319],{"class":668}," run",[641,2321,2322],{"class":668}," test:e2e\n",[641,2324,2325,2327,2329,2331,2333,2336],{"class":643,"line":718},[641,2326,2290],{"class":1613},[641,2328,2293],{"class":668},[641,2330,2296],{"class":668},[641,2332,2299],{"class":668},[641,2334,2335],{"class":668}," down",[641,2337,2338],{"class":668}," -v\n",[545,2340,2341,2342,2345,2346,2349,2350,2352,2353,2355,2356,2358],{},"The suite is a ",[565,2343,2344],{},"round-trip",": it inserts events, reads them back with\n",[557,2347,2348],{},"SELECT",", and asserts the typed columns and the ",[557,2351,571],{}," JSON survived. The\ncompose file creates ",[557,2354,1820],{}," from the schema above on first boot.\nWithout ",[557,2357,1753],{}," it skips itself with a visible label.",[545,2360,2361,2362,2365],{},"To ",[2242,2363,2364],{},"see"," the events rather than assert on them, seed the sandbox and open the\nprovisioned dashboard. The stack ships a Grafana with the ClickHouse\ndatasource already wired up:",[631,2367,2369],{"className":2074,"code":2368,"filename":2283,"language":2077,"meta":637,"style":637},"pnpm run sandbox:up\npnpm run sandbox:seed\n# → http:\u002F\u002Flocalhost:3001\u002Fd\u002Fevlog-wide-events\n",[557,2370,2371,2381,2390],{"__ignoreMap":637},[641,2372,2373,2376,2378],{"class":643,"line":644},[641,2374,2375],{"class":1613},"pnpm",[641,2377,2319],{"class":668},[641,2379,2380],{"class":668}," sandbox:up\n",[641,2382,2383,2385,2387],{"class":643,"line":712},[641,2384,2375],{"class":1613},[641,2386,2319],{"class":668},[641,2388,2389],{"class":668}," sandbox:seed\n",[641,2391,2392],{"class":643,"line":718},[641,2393,2394],{"class":950},"# → http:\u002F\u002Flocalhost:3001\u002Fd\u002Fevlog-wide-events\n",[545,2396,2397,2398,2401,2402,2405],{},"ClickHouse's built-in ",[557,2399,2400],{},"\u002Fplay"," page at ",[557,2403,2404],{},"http:\u002F\u002Flocalhost:8123\u002Fplay"," also works\nfor raw SQL, but it is deliberately minimal, and the dashboard is the better\nstarting point.",[624,2407,2409],{"id":2408},"async-inserts","Async inserts",[545,2411,2412,2413,2418,2419,2422],{},"Log ingestion means many small inserts, and one MergeTree part per request would quickly degrade a table. The adapter therefore enables ",[549,2414,2417],{"href":2415,"rel":2416},"https:\u002F\u002Fclickhouse.com\u002Fdocs\u002Fen\u002Foptimize\u002Fasynchronous-inserts",[553],"asynchronous inserts"," by default, and does ",[565,2420,2421],{},"not"," wait for the flush:",[631,2424,2429],{"className":2425,"code":2427,"language":2428},[2426],"language-text","async_insert=1&wait_for_async_insert=0\n","text",[557,2430,2427],{"__ignoreMap":637},[545,2432,2433],{},"ClickHouse buffers rows server-side and writes them in batches. Draining never blocks a request on disk writes.",[545,2435,2436,2437,2440,2441,2444,2445,1012],{},"Set ",[557,2438,2439],{},"waitForAsyncInsert: true"," if you need the insert acknowledged as durable before the drain resolves, at the cost of latency. Set ",[557,2442,2443],{},"asyncInsert: false"," to insert synchronously, which only makes sense when you already batch client-side with ",[557,2446,2447],{},"evlog\u002Fpipeline",[624,2449,2451],{"id":2450},"querying","Querying",[545,2453,2454,2455,2457],{},"Typed columns are indexed by the sort key; everything else lives in ",[557,2456,571],{}," and is reachable with ClickHouse's JSON functions:",[631,2459,2461],{"className":682,"code":2460,"language":685,"meta":637,"style":637},"-- Error rate per service over the last hour\nSELECT service, countIf(level = 'error') \u002F count() AS error_rate\nFROM evlog_events\nWHERE timestamp > now() - INTERVAL 1 HOUR\nGROUP BY service;\n",[557,2462,2463,2468,2506,2513,2540],{"__ignoreMap":637},[641,2464,2465],{"class":643,"line":644},[641,2466,2467],{"class":950},"-- Error rate per service over the last hour\n",[641,2469,2470,2472,2474,2477,2480,2483,2485,2488,2490,2492,2495,2498,2500,2503],{"class":643,"line":712},[641,2471,2348],{"class":692},[641,2473,1684],{"class":692},[641,2475,2476],{"class":655},", countIf(",[641,2478,2479],{"class":692},"level",[641,2481,2482],{"class":651}," =",[641,2484,665],{"class":651},[641,2486,2487],{"class":668},"error",[641,2489,734],{"class":651},[641,2491,906],{"class":655},[641,2493,2494],{"class":651},"\u002F",[641,2496,2497],{"class":699}," count",[641,2499,1161],{"class":655},[641,2501,2502],{"class":692},"AS",[641,2504,2505],{"class":655}," error_rate\n",[641,2507,2508,2511],{"class":643,"line":718},[641,2509,2510],{"class":692},"FROM",[641,2512,709],{"class":655},[641,2514,2515,2518,2521,2524,2527,2529,2532,2534,2537],{"class":643,"line":745},[641,2516,2517],{"class":692},"WHERE",[641,2519,2520],{"class":721}," timestamp",[641,2522,2523],{"class":651}," >",[641,2525,2526],{"class":692}," now",[641,2528,1458],{"class":651},[641,2530,2531],{"class":651}," -",[641,2533,912],{"class":655},[641,2535,2536],{"class":692},"1",[641,2538,2539],{"class":692}," HOUR\n",[641,2541,2542,2545,2547],{"class":643,"line":754},[641,2543,2544],{"class":692},"GROUP BY",[641,2546,1684],{"class":692},[641,2548,921],{"class":655},[631,2550,2552],{"className":682,"code":2551,"language":685,"meta":637,"style":637},"-- Slowest routes\nSELECT path, count() AS hits, avg(duration_ms) AS avg_ms, quantile(0.95)(duration_ms) AS p95_ms\nFROM evlog_events\nWHERE timestamp > now() - INTERVAL 1 DAY AND method = 'GET' AND duration_ms IS NOT NULL\nGROUP BY path\nORDER BY avg_ms DESC\nLIMIT 20;\n",[557,2553,2554,2559,2605,2611,2654,2661,2671],{"__ignoreMap":637},[641,2555,2556],{"class":643,"line":644},[641,2557,2558],{"class":950},"-- Slowest routes\n",[641,2560,2561,2563,2566,2568,2571,2573,2575,2578,2581,2584,2586,2589,2592,2594,2597,2600,2602],{"class":643,"line":712},[641,2562,2348],{"class":692},[641,2564,2565],{"class":721}," path",[641,2567,731],{"class":655},[641,2569,2570],{"class":699},"count",[641,2572,1161],{"class":655},[641,2574,2502],{"class":692},[641,2576,2577],{"class":655}," hits, ",[641,2579,2580],{"class":699},"avg",[641,2582,2583],{"class":655},"(duration_ms) ",[641,2585,2502],{"class":692},[641,2587,2588],{"class":655}," avg_ms, quantile(",[641,2590,2591],{"class":692},"0",[641,2593,1012],{"class":655},[641,2595,2596],{"class":692},"95",[641,2598,2599],{"class":655},")(duration_ms) ",[641,2601,2502],{"class":692},[641,2603,2604],{"class":655}," p95_ms\n",[641,2606,2607,2609],{"class":643,"line":718},[641,2608,2510],{"class":692},[641,2610,709],{"class":655},[641,2612,2613,2615,2617,2619,2621,2623,2625,2627,2629,2631,2634,2637,2639,2641,2644,2646,2648,2651],{"class":643,"line":745},[641,2614,2517],{"class":692},[641,2616,2520],{"class":721},[641,2618,2523],{"class":651},[641,2620,2526],{"class":692},[641,2622,1458],{"class":651},[641,2624,2531],{"class":651},[641,2626,912],{"class":655},[641,2628,2536],{"class":692},[641,2630,918],{"class":692},[641,2632,2633],{"class":692}," AND",[641,2635,2636],{"class":655}," method ",[641,2638,856],{"class":651},[641,2640,665],{"class":651},[641,2642,2643],{"class":668},"GET",[641,2645,734],{"class":651},[641,2647,2633],{"class":692},[641,2649,2650],{"class":655}," duration_ms ",[641,2652,2653],{"class":692},"IS NOT NULL\n",[641,2655,2656,2658],{"class":643,"line":754},[641,2657,2544],{"class":692},[641,2659,2660],{"class":721}," path\n",[641,2662,2663,2665,2668],{"class":643,"line":763},[641,2664,882],{"class":692},[641,2666,2667],{"class":655}," avg_ms ",[641,2669,2670],{"class":692},"DESC\n",[641,2672,2673,2676,2679],{"class":643,"line":769},[641,2674,2675],{"class":692},"LIMIT",[641,2677,2678],{"class":692}," 20",[641,2680,921],{"class":655},[631,2682,2684],{"className":682,"code":2683,"language":685,"meta":637,"style":637},"-- One request end to end\nSELECT timestamp, level, path, status, data\nFROM evlog_events\nWHERE request_id = '4a8ff3a8-...'\nORDER BY timestamp;\n",[557,2685,2686,2691,2716,2722,2738],{"__ignoreMap":637},[641,2687,2688],{"class":643,"line":644},[641,2689,2690],{"class":950},"-- One request end to end\n",[641,2692,2693,2695,2697,2699,2701,2703,2706,2708,2711,2713],{"class":643,"line":712},[641,2694,2348],{"class":692},[641,2696,2520],{"class":721},[641,2698,731],{"class":655},[641,2700,2479],{"class":692},[641,2702,731],{"class":655},[641,2704,2705],{"class":721},"path",[641,2707,731],{"class":655},[641,2709,2710],{"class":692},"status",[641,2712,731],{"class":655},[641,2714,2715],{"class":692},"data\n",[641,2717,2718,2720],{"class":643,"line":718},[641,2719,2510],{"class":692},[641,2721,709],{"class":655},[641,2723,2724,2726,2729,2731,2733,2736],{"class":643,"line":745},[641,2725,2517],{"class":692},[641,2727,2728],{"class":655}," request_id ",[641,2730,856],{"class":651},[641,2732,665],{"class":651},[641,2734,2735],{"class":668},"4a8ff3a8-...",[641,2737,672],{"class":651},[641,2739,2740,2742,2744],{"class":643,"line":754},[641,2741,882],{"class":692},[641,2743,2520],{"class":721},[641,2745,921],{"class":655},[631,2747,2749],{"className":682,"code":2748,"language":685,"meta":637,"style":637},"-- Reach into a custom field kept only in data\nSELECT JSONExtractString(data, 'user', 'plan') AS plan, count()\nFROM evlog_events\nWHERE timestamp > now() - INTERVAL 7 DAY\nGROUP BY plan;\n",[557,2750,2751,2756,2794,2800,2822],{"__ignoreMap":637},[641,2752,2753],{"class":643,"line":644},[641,2754,2755],{"class":950},"-- Reach into a custom field kept only in data\n",[641,2757,2758,2760,2763,2765,2767,2769,2772,2774,2776,2778,2781,2783,2785,2787,2790,2792],{"class":643,"line":712},[641,2759,2348],{"class":692},[641,2761,2762],{"class":655}," JSONExtractString(",[641,2764,571],{"class":692},[641,2766,731],{"class":655},[641,2768,734],{"class":651},[641,2770,2771],{"class":668},"user",[641,2773,734],{"class":651},[641,2775,731],{"class":655},[641,2777,734],{"class":651},[641,2779,2780],{"class":668},"plan",[641,2782,734],{"class":651},[641,2784,906],{"class":655},[641,2786,2502],{"class":692},[641,2788,2789],{"class":655}," plan, ",[641,2791,2570],{"class":699},[641,2793,1130],{"class":655},[641,2795,2796,2798],{"class":643,"line":718},[641,2797,2510],{"class":692},[641,2799,709],{"class":655},[641,2801,2802,2804,2806,2808,2810,2812,2814,2816,2819],{"class":643,"line":745},[641,2803,2517],{"class":692},[641,2805,2520],{"class":721},[641,2807,2523],{"class":651},[641,2809,2526],{"class":692},[641,2811,1458],{"class":651},[641,2813,2531],{"class":651},[641,2815,912],{"class":655},[641,2817,2818],{"class":692},"7",[641,2820,2821],{"class":692}," DAY\n",[641,2823,2824,2826],{"class":643,"line":754},[641,2825,2544],{"class":692},[641,2827,2828],{"class":655}," plan;\n",[624,2830,2832],{"id":2831},"custom-schema","Custom schema",[545,2834,2835,2836,2838],{},"Pass ",[557,2837,1975],{}," to target a table of your own shape:",[631,2840,2842],{"className":633,"code":2841,"filename":2045,"language":636,"meta":637,"style":637},"import { createClickHouseDrain } from 'evlog\u002Fclickhouse'\n\ncreateClickHouseDrain({\n  table: 'app_logs',\n  transform: event => ({\n    ts: event.timestamp,\n    lvl: event.level,\n    svc: event.service,\n    payload: JSON.stringify(event),\n  }),\n})\n",[557,2843,2844,2862,2866,2874,2890,2906,2921,2936,2951,2971,2980],{"__ignoreMap":637},[641,2845,2846,2848,2850,2852,2854,2856,2858,2860],{"class":643,"line":644},[641,2847,648],{"class":647},[641,2849,652],{"class":651},[641,2851,656],{"class":655},[641,2853,659],{"class":651},[641,2855,662],{"class":647},[641,2857,665],{"class":651},[641,2859,669],{"class":668},[641,2861,672],{"class":651},[641,2863,2864],{"class":643,"line":712},[641,2865,975],{"emptyLinePlaceholder":974},[641,2867,2868,2870,2872],{"class":643,"line":718},[641,2869,2052],{"class":699},[641,2871,989],{"class":655},[641,2873,1562],{"class":651},[641,2875,2876,2879,2881,2883,2886,2888],{"class":643,"line":745},[641,2877,2878],{"class":1023},"  table",[641,2880,1156],{"class":651},[641,2882,665],{"class":651},[641,2884,2885],{"class":668},"app_logs",[641,2887,734],{"class":651},[641,2889,1597],{"class":651},[641,2891,2892,2895,2897,2900,2902,2904],{"class":643,"line":754},[641,2893,2894],{"class":699},"  transform",[641,2896,1156],{"class":651},[641,2898,2899],{"class":994}," event",[641,2901,1001],{"class":721},[641,2903,885],{"class":655},[641,2905,1562],{"class":651},[641,2907,2908,2911,2913,2915,2917,2919],{"class":643,"line":763},[641,2909,2910],{"class":1023},"    ts",[641,2912,1156],{"class":651},[641,2914,2899],{"class":655},[641,2916,1012],{"class":651},[641,2918,874],{"class":655},[641,2920,1597],{"class":651},[641,2922,2923,2926,2928,2930,2932,2934],{"class":643,"line":769},[641,2924,2925],{"class":1023},"    lvl",[641,2927,1156],{"class":651},[641,2929,2899],{"class":655},[641,2931,1012],{"class":651},[641,2933,2479],{"class":655},[641,2935,1597],{"class":651},[641,2937,2938,2941,2943,2945,2947,2949],{"class":643,"line":775},[641,2939,2940],{"class":1023},"    svc",[641,2942,1156],{"class":651},[641,2944,2899],{"class":655},[641,2946,1012],{"class":651},[641,2948,888],{"class":655},[641,2950,1597],{"class":651},[641,2952,2953,2956,2958,2961,2963,2966,2969],{"class":643,"line":781},[641,2954,2955],{"class":1023},"    payload",[641,2957,1156],{"class":651},[641,2959,2960],{"class":655}," JSON",[641,2962,1012],{"class":651},[641,2964,2965],{"class":699},"stringify",[641,2967,2968],{"class":655},"(event)",[641,2970,1597],{"class":651},[641,2972,2973,2976,2978],{"class":643,"line":787},[641,2974,2975],{"class":651},"  }",[641,2977,998],{"class":655},[641,2979,1597],{"class":651},[641,2981,2982,2984],{"class":643,"line":793},[641,2983,1043],{"class":651},[641,2985,847],{"class":655},[545,2987,2988,2989,2991],{},"Keys must match your column names, because ClickHouse rejects a ",[557,2990,559],{}," insert containing unknown columns.",[624,2993,2995],{"id":2994},"batching","Batching",[545,2997,2998],{},"Pair with a pipeline to insert in larger batches:",[631,3000,3002],{"className":633,"code":3001,"filename":2045,"language":636,"meta":637,"style":637},"import { createDrainPipeline } from 'evlog\u002Fpipeline'\nimport { createClickHouseDrain } from 'evlog\u002Fclickhouse'\nimport type { DrainContext } from 'evlog'\n\nconst pipeline = createDrainPipeline\u003CDrainContext>({\n  batch: { size: 500, intervalMs: 5000 },\n})\n\nexport default defineNitroPlugin((nitroApp) => {\n  nitroApp.hooks.hook('evlog:drain', pipeline(createClickHouseDrain()))\n})\n",[557,3003,3004,3023,3041,3063,3067,3091,3120,3126,3130,3150,3182],{"__ignoreMap":637},[641,3005,3006,3008,3010,3013,3015,3017,3019,3021],{"class":643,"line":644},[641,3007,648],{"class":647},[641,3009,652],{"class":651},[641,3011,3012],{"class":655}," createDrainPipeline",[641,3014,659],{"class":651},[641,3016,662],{"class":647},[641,3018,665],{"class":651},[641,3020,2447],{"class":668},[641,3022,672],{"class":651},[641,3024,3025,3027,3029,3031,3033,3035,3037,3039],{"class":643,"line":712},[641,3026,648],{"class":647},[641,3028,652],{"class":651},[641,3030,656],{"class":655},[641,3032,659],{"class":651},[641,3034,662],{"class":647},[641,3036,665],{"class":651},[641,3038,669],{"class":668},[641,3040,672],{"class":651},[641,3042,3043,3045,3048,3050,3053,3055,3057,3059,3061],{"class":643,"line":718},[641,3044,648],{"class":647},[641,3046,3047],{"class":647}," type",[641,3049,652],{"class":651},[641,3051,3052],{"class":655}," DrainContext",[641,3054,659],{"class":651},[641,3056,662],{"class":647},[641,3058,665],{"class":651},[641,3060,1145],{"class":668},[641,3062,672],{"class":651},[641,3064,3065],{"class":643,"line":745},[641,3066,975],{"emptyLinePlaceholder":974},[641,3068,3069,3071,3074,3076,3078,3081,3084,3087,3089],{"class":643,"line":754},[641,3070,1117],{"class":721},[641,3072,3073],{"class":655}," pipeline ",[641,3075,856],{"class":651},[641,3077,3012],{"class":699},[641,3079,3080],{"class":651},"\u003C",[641,3082,3083],{"class":1613},"DrainContext",[641,3085,3086],{"class":651},">",[641,3088,989],{"class":655},[641,3090,1562],{"class":651},[641,3092,3093,3096,3098,3100,3103,3105,3108,3110,3113,3115,3118],{"class":643,"line":763},[641,3094,3095],{"class":1023},"  batch",[641,3097,1156],{"class":651},[641,3099,652],{"class":651},[641,3101,3102],{"class":1023}," size",[641,3104,1156],{"class":651},[641,3106,3107],{"class":692}," 500",[641,3109,1033],{"class":651},[641,3111,3112],{"class":1023}," intervalMs",[641,3114,1156],{"class":651},[641,3116,3117],{"class":692}," 5000",[641,3119,1696],{"class":651},[641,3121,3122,3124],{"class":643,"line":769},[641,3123,1043],{"class":651},[641,3125,847],{"class":655},[641,3127,3128],{"class":643,"line":775},[641,3129,975],{"emptyLinePlaceholder":974},[641,3131,3132,3134,3136,3138,3140,3142,3144,3146,3148],{"class":643,"line":781},[641,3133,980],{"class":647},[641,3135,983],{"class":647},[641,3137,986],{"class":699},[641,3139,989],{"class":655},[641,3141,989],{"class":651},[641,3143,995],{"class":994},[641,3145,998],{"class":651},[641,3147,1001],{"class":721},[641,3149,1004],{"class":651},[641,3151,3152,3154,3156,3158,3160,3162,3164,3166,3168,3170,3172,3175,3177,3179],{"class":643,"line":787},[641,3153,1009],{"class":655},[641,3155,1012],{"class":651},[641,3157,1015],{"class":655},[641,3159,1012],{"class":651},[641,3161,1020],{"class":699},[641,3163,989],{"class":1023},[641,3165,734],{"class":651},[641,3167,1028],{"class":668},[641,3169,734],{"class":651},[641,3171,1033],{"class":651},[641,3173,3174],{"class":699}," pipeline",[641,3176,989],{"class":1023},[641,3178,2052],{"class":699},[641,3180,3181],{"class":1023},"()))\n",[641,3183,3184,3186],{"class":643,"line":793},[641,3185,1043],{"class":651},[641,3187,847],{"class":655},[624,3189,3191],{"id":3190},"troubleshooting","Troubleshooting",[545,3193,3194,2264,3199,3201,3202,3204,3205,3208],{},[565,3195,3196,1012],{},[557,3197,3198],{},"Missing endpoint",[557,3200,1753],{}," is unset and no ",[557,3203,1849],{}," was passed. The drain logs ",[557,3206,3207],{},"[evlog\u002Fclickhouse] Missing endpoint"," once and then does nothing, so requests are never blocked or failed.",[545,3210,3211,3216,3217,2260,3219,3221,3222,2260,3224,3226,3227,1012],{},[565,3212,3213,1012],{},[557,3214,3215],{},"ClickHouse API error: 401"," Check ",[557,3218,1770],{},[557,3220,1786],{},". Credentials are sent as ",[557,3223,2259],{},[557,3225,2263],{}," headers, never in the query string, so they never reach ",[557,3228,2271],{},[545,3230,3231,3237,3238,3240],{},[565,3232,3233,3236],{},[557,3234,3235],{},"ClickHouse API error: 400"," mentioning unknown column."," Your table does not match the row shape. Either create the table from the DDL above, or supply a ",[557,3239,1975],{}," matching your columns.",[545,3242,3243,3248,3249,3251,3252,3255],{},[565,3244,3245,1012],{},[557,3246,3247],{},"Cannot parse input"," The table exists but a column type disagrees. ",[557,3250,2710],{}," is ",[557,3253,3254],{},"Nullable(UInt16)"," because it is absent on non-HTTP events.",[624,3257,3259],{"id":3258},"direct-api-usage","Direct API usage",[631,3261,3264],{"className":633,"code":3262,"filename":3263,"language":636,"meta":637,"style":637},"import { sendBatchToClickHouse, sendToClickHouse } from 'evlog\u002Fclickhouse'\n\nawait sendToClickHouse(event, { endpoint: 'http:\u002F\u002Flocalhost:8123' })\nawait sendBatchToClickHouse(events, { endpoint: 'http:\u002F\u002Flocalhost:8123' })\n","scripts\u002Fbackfill.ts",[557,3265,3266,3290,3294,3321],{"__ignoreMap":637},[641,3267,3268,3270,3272,3275,3277,3280,3282,3284,3286,3288],{"class":643,"line":644},[641,3269,648],{"class":647},[641,3271,652],{"class":651},[641,3273,3274],{"class":655}," sendBatchToClickHouse",[641,3276,1033],{"class":651},[641,3278,3279],{"class":655}," sendToClickHouse",[641,3281,659],{"class":651},[641,3283,662],{"class":647},[641,3285,665],{"class":651},[641,3287,669],{"class":668},[641,3289,672],{"class":651},[641,3291,3292],{"class":643,"line":712},[641,3293,975],{"emptyLinePlaceholder":974},[641,3295,3296,3298,3300,3303,3305,3307,3309,3311,3313,3315,3317,3319],{"class":643,"line":718},[641,3297,1350],{"class":647},[641,3299,3279],{"class":699},[641,3301,3302],{"class":655},"(event",[641,3304,1033],{"class":651},[641,3306,652],{"class":651},[641,3308,2059],{"class":1023},[641,3310,1156],{"class":651},[641,3312,665],{"class":651},[641,3314,605],{"class":668},[641,3316,734],{"class":651},[641,3318,659],{"class":651},[641,3320,847],{"class":655},[641,3322,3323,3325,3327,3330,3332,3334,3336,3338,3340,3342,3344,3346],{"class":643,"line":745},[641,3324,1350],{"class":647},[641,3326,3274],{"class":699},[641,3328,3329],{"class":655},"(events",[641,3331,1033],{"class":651},[641,3333,652],{"class":651},[641,3335,2059],{"class":1023},[641,3337,1156],{"class":651},[641,3339,665],{"class":651},[641,3341,605],{"class":668},[641,3343,734],{"class":651},[641,3345,659],{"class":651},[641,3347,847],{"class":655},[545,3349,3350,731,3353,3356,3357,3360],{},[557,3351,3352],{},"toClickHouseRow()",[557,3354,3355],{},"toJSONEachRow()",", and ",[557,3358,3359],{},"resolveClickHouseUrl()"," are also exported.",[624,3362,3364],{"id":3363},"next-steps","Next steps",[3366,3367,3368,3373,3378,3384],"ul",{},[585,3369,3370,3372],{},[549,3371,61],{"href":62},": control volume before it reaches ClickHouse",[585,3374,3375,3377],{},[549,3376,431],{"href":432},": add derived fields to every event",[585,3379,3380,3383],{},[549,3381,3382],{"href":496},"Pipeline",": batching, retries, and fan-out",[585,3385,3386,3389],{},[549,3387,3388],{"href":143},"Adapters Overview",": all available destinations",[3391,3392,3393],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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}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 .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":637,"searchDepth":712,"depth":712,"links":3395},[3396,3397,3398,3399,3403,3407,3408,3409,3410,3411,3412,3413,3414],{"id":626,"depth":712,"text":20},{"id":675,"depth":712,"text":676},{"id":936,"depth":712,"text":25},{"id":1718,"depth":712,"text":508,"children":3400},[3401,3402],{"id":1722,"depth":718,"text":1723},{"id":1823,"depth":718,"text":336},{"id":2030,"depth":712,"text":2031,"children":3404},[3405,3406],{"id":2037,"depth":718,"text":2038},{"id":2129,"depth":718,"text":2130},{"id":2275,"depth":712,"text":2276},{"id":2408,"depth":712,"text":2409},{"id":2450,"depth":712,"text":2451},{"id":2831,"depth":712,"text":2832},{"id":2994,"depth":712,"text":2995},{"id":3190,"depth":712,"text":3191},{"id":3258,"depth":712,"text":3259},{"id":3363,"depth":712,"text":3364},"Insert wide events into ClickHouse over the HTTP interface — typed columns for what you aggregate, full JSON for everything else.","md",[3418,3424],{"label":3419,"icon":3420,"to":551,"target":3421,"color":3422,"variant":3423},"HTTP Interface","i-lucide-external-link","_blank","neutral","subtle",{"label":3425,"icon":3420,"to":2415,"target":3421,"color":3422,"variant":3423},"Async Inserts",{},{"title":186,"icon":189},{"title":540,"description":3415},"2tkkGzm_QM70LI_vpY_UpJWCHtZzf2R9tvxSFL45XwM",[3431,3433],{"title":181,"path":182,"stem":183,"description":3432,"icon":184,"children":-1},"Push wide events to Grafana Loki — self-hosted, multi-tenant, or Grafana Cloud — with low-cardinality labels and full JSON querying.",{"title":191,"path":192,"stem":193,"description":3434,"icon":194,"children":-1},"Send logs via OpenTelemetry Protocol (OTLP) to Grafana, Datadog, Honeycomb, and any compatible backend. Supports gRPC and HTTP transports.",1786817437880]