[{"data":1,"prerenderedAt":3348},["ShallowReactive",2],{"navigation_docs":3,"-docs-capabilities-observability":493,"-docs-capabilities-observability-surround":3343},[4,46,135,218,257,292,355,377,420],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":45},"Getting Started","i-lucide-rocket","\u002Fdocs\u002Fgetting-started","docs\u002F01.getting-started",[10,15,20,25,30,35,40],{"title":11,"path":12,"stem":13,"icon":14},"What is Heximon?","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002F01.getting-started\u002F01.introduction","i-lucide-info",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","docs\u002F01.getting-started\u002F02.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","\u002Fdocs\u002Fgetting-started\u002Fquick-start","docs\u002F01.getting-started\u002F03.quick-start","i-lucide-zap",{"title":26,"path":27,"stem":28,"icon":29},"Core Concepts","\u002Fdocs\u002Fgetting-started\u002Fcore-concepts","docs\u002F01.getting-started\u002F04.core-concepts","i-lucide-shapes",{"title":31,"path":32,"stem":33,"icon":34},"Examples","\u002Fdocs\u002Fgetting-started\u002Fexamples","docs\u002F01.getting-started\u002F05.examples","i-lucide-library",{"title":36,"path":37,"stem":38,"icon":39},"Where Next?","\u002Fdocs\u002Fgetting-started\u002Fwhere-next","docs\u002F01.getting-started\u002F06.where-next","i-lucide-signpost",{"title":41,"path":42,"stem":43,"icon":44},"Troubleshooting","\u002Fdocs\u002Fgetting-started\u002Ftroubleshooting","docs\u002F01.getting-started\u002F07.troubleshooting","i-lucide-life-buoy",false,{"title":47,"icon":48,"path":49,"stem":50,"children":51,"page":45},"Essentials","i-lucide-boxes","\u002Fdocs\u002Fessentials","docs\u002F02.essentials",[52,56,61,66,71,76,81,86,91,96,101,105,110,115,120,125,130],{"title":53,"path":54,"stem":55,"icon":48},"Modules & DI","\u002Fdocs\u002Fessentials\u002Fmodules-and-di","docs\u002F02.essentials\u002F01.modules-and-di",{"title":57,"path":58,"stem":59,"icon":60},"Controllers","\u002Fdocs\u002Fessentials\u002Fcontrollers","docs\u002F02.essentials\u002F02.controllers","i-lucide-route",{"title":62,"path":63,"stem":64,"icon":65},"Validation & DTOs","\u002Fdocs\u002Fessentials\u002Fvalidation","docs\u002F02.essentials\u002F03.validation","i-lucide-shield-check",{"title":67,"path":68,"stem":69,"icon":70},"Contracts","\u002Fdocs\u002Fessentials\u002Fcontracts","docs\u002F02.essentials\u002F04.contracts","i-lucide-file-signature",{"title":72,"path":73,"stem":74,"icon":75},"REST Client","\u002Fdocs\u002Fessentials\u002Fclient","docs\u002F02.essentials\u002F05.client","i-lucide-plug",{"title":77,"path":78,"stem":79,"icon":80},"Database","\u002Fdocs\u002Fessentials\u002Fdatabase","docs\u002F02.essentials\u002F06.database","i-lucide-database",{"title":82,"path":83,"stem":84,"icon":85},"Drizzle ORM","\u002Fdocs\u002Fessentials\u002Fdrizzle","docs\u002F02.essentials\u002F07.drizzle","i-lucide-database-zap",{"title":87,"path":88,"stem":89,"icon":90},"Persistence & Transactions","\u002Fdocs\u002Fessentials\u002Fpersistence","docs\u002F02.essentials\u002F08.persistence","i-lucide-database-backup",{"title":92,"path":93,"stem":94,"icon":95},"Migrations","\u002Fdocs\u002Fessentials\u002Fmigrations","docs\u002F02.essentials\u002F09.migrations","i-lucide-git-branch",{"title":97,"path":98,"stem":99,"icon":100},"Authentication","\u002Fdocs\u002Fessentials\u002Fauthentication","docs\u002F02.essentials\u002F10.authentication","i-lucide-key-round",{"title":102,"path":103,"stem":104,"icon":65},"Permissions & scopes","\u002Fdocs\u002Fessentials\u002Fpermissions","docs\u002F02.essentials\u002F11.permissions",{"title":106,"path":107,"stem":108,"icon":109},"Error Handling","\u002Fdocs\u002Fessentials\u002Ferrors","docs\u002F02.essentials\u002F12.errors","i-lucide-triangle-alert",{"title":111,"path":112,"stem":113,"icon":114},"Testing a Heximon App","\u002Fdocs\u002Fessentials\u002Ftesting","docs\u002F02.essentials\u002F13.testing","i-lucide-flask-conical",{"title":116,"path":117,"stem":118,"icon":119},"Test app harness","\u002Fdocs\u002Fessentials\u002Fcreatetestapp","docs\u002F02.essentials\u002F14.createtestapp","i-lucide-test-tube",{"title":121,"path":122,"stem":123,"icon":124},"Logging & Observability","\u002Fdocs\u002Fessentials\u002Flogging","docs\u002F02.essentials\u002F17.logging","i-lucide-scroll-text",{"title":126,"path":127,"stem":128,"icon":129},"Context & Lifecycle","\u002Fdocs\u002Fessentials\u002Fcontext-and-lifecycle","docs\u002F02.essentials\u002F18.context-and-lifecycle","i-lucide-radio",{"title":131,"path":132,"stem":133,"icon":134},"Project Structure","\u002Fdocs\u002Fessentials\u002Fproject-structure","docs\u002F02.essentials\u002F19.project-structure","i-lucide-folder-tree",{"title":136,"icon":137,"path":138,"stem":139,"children":140,"page":45},"Capabilities","i-lucide-sparkles","\u002Fdocs\u002Fcapabilities","docs\u002F03.capabilities",[141,145,150,155,160,164,169,174,179,184,188,193,198,203,208,213],{"title":142,"path":143,"stem":144,"icon":137},"Overview","\u002Fdocs\u002Fcapabilities\u002Foverview","docs\u002F03.capabilities\u002F01.overview",{"title":146,"path":147,"stem":148,"icon":149},"Events","\u002Fdocs\u002Fcapabilities\u002Fevents","docs\u002F03.capabilities\u002F02.events","i-lucide-radio-tower",{"title":151,"path":152,"stem":153,"icon":154},"Queue","\u002Fdocs\u002Fcapabilities\u002Fbackground-jobs","docs\u002F03.capabilities\u002F03.background-jobs","i-lucide-list-ordered",{"title":156,"path":157,"stem":158,"icon":159},"Scheduled Work","\u002Fdocs\u002Fcapabilities\u002Fscheduled-jobs","docs\u002F03.capabilities\u002F04.scheduled-jobs","i-lucide-clock",{"title":161,"path":162,"stem":163,"icon":85},"Caching","\u002Fdocs\u002Fcapabilities\u002Fcaching","docs\u002F03.capabilities\u002F05.caching",{"title":165,"path":166,"stem":167,"icon":168},"Key\u002FValue Storage","\u002Fdocs\u002Fcapabilities\u002Fkey-value","docs\u002F03.capabilities\u002F06.key-value","i-lucide-hard-drive",{"title":170,"path":171,"stem":172,"icon":173},"Blob Storage","\u002Fdocs\u002Fcapabilities\u002Fblob","docs\u002F03.capabilities\u002F07.blob","i-lucide-folder-open",{"title":175,"path":176,"stem":177,"icon":178},"Health & Readiness","\u002Fdocs\u002Fcapabilities\u002Fhealth","docs\u002F03.capabilities\u002F08.health","i-lucide-heart-pulse",{"title":180,"path":181,"stem":182,"icon":183},"Notifications","\u002Fdocs\u002Fcapabilities\u002Fnotifications","docs\u002F03.capabilities\u002F09.notifications","i-lucide-mail",{"title":185,"path":186,"stem":187,"icon":65},"Idempotency","\u002Fdocs\u002Fcapabilities\u002Fidempotency","docs\u002F03.capabilities\u002F10.idempotency",{"title":189,"path":190,"stem":191,"icon":192},"Security Hardening","\u002Fdocs\u002Fcapabilities\u002Fsecurity","docs\u002F03.capabilities\u002F11.security","i-lucide-shield",{"title":194,"path":195,"stem":196,"icon":197},"Observability & Tracing","\u002Fdocs\u002Fcapabilities\u002Fobservability","docs\u002F03.capabilities\u002F12.observability","i-lucide-activity",{"title":199,"path":200,"stem":201,"icon":202},"OpenAPI","\u002Fdocs\u002Fcapabilities\u002Fopenapi","docs\u002F03.capabilities\u002F13.openapi","i-lucide-book-marked",{"title":204,"path":205,"stem":206,"icon":207},"MCP Server","\u002Fdocs\u002Fcapabilities\u002Fmcp","docs\u002F03.capabilities\u002F14.mcp","i-lucide-bot",{"title":209,"path":210,"stem":211,"icon":212},"Schema DTOs","\u002Fdocs\u002Fcapabilities\u002Fschema","docs\u002F03.capabilities\u002F15.schema","i-lucide-file-json",{"title":214,"path":215,"stem":216,"icon":217},"Branded IDs","\u002Fdocs\u002Fcapabilities\u002Fbranded-ids","docs\u002F03.capabilities\u002F16.branded-ids","i-lucide-tag",{"title":219,"icon":220,"path":221,"stem":222,"children":223,"page":45},"Architecture","i-lucide-building","\u002Fdocs\u002Farchitecture","docs\u002F04.architecture",[224,227,232,237,242,247,252],{"title":142,"path":225,"stem":226,"icon":220},"\u002Fdocs\u002Farchitecture\u002Foverview","docs\u002F04.architecture\u002F01.overview",{"title":228,"path":229,"stem":230,"icon":231},"Domain-Driven Design","\u002Fdocs\u002Farchitecture\u002Fddd","docs\u002F04.architecture\u002F02.ddd","i-lucide-hexagon",{"title":233,"path":234,"stem":235,"icon":236},"CQRS","\u002Fdocs\u002Farchitecture\u002Fcqrs","docs\u002F04.architecture\u002F03.cqrs","i-lucide-split",{"title":238,"path":239,"stem":240,"icon":241},"Repository Pattern","\u002Fdocs\u002Farchitecture\u002Frepository-pattern","docs\u002F04.architecture\u002F04.repository-pattern","i-lucide-archive",{"title":243,"path":244,"stem":245,"icon":246},"Integration Events","\u002Fdocs\u002Farchitecture\u002Fintegration-events","docs\u002F04.architecture\u002F05.integration-events","i-lucide-send-horizontal",{"title":248,"path":249,"stem":250,"icon":251},"Saga Orchestration","\u002Fdocs\u002Farchitecture\u002Fsagas","docs\u002F04.architecture\u002F06.sagas","i-lucide-hourglass",{"title":253,"path":254,"stem":255,"icon":256},"Durable Workflows","\u002Fdocs\u002Farchitecture\u002Fworkflows","docs\u002F04.architecture\u002F07.workflows","i-lucide-workflow",{"title":258,"icon":259,"path":260,"stem":261,"children":262,"page":45},"Realtime","i-lucide-cable","\u002Fdocs\u002Frealtime","docs\u002F05.realtime",[263,266,270,274,279,284,288],{"title":142,"path":264,"stem":265,"icon":259},"\u002Fdocs\u002Frealtime\u002Foverview","docs\u002F05.realtime\u002F01.overview",{"title":267,"path":268,"stem":269,"icon":129},"WebSockets","\u002Fdocs\u002Frealtime\u002Fwebsockets","docs\u002F05.realtime\u002F02.websockets",{"title":271,"path":272,"stem":273,"icon":70},"WebSocket Contracts","\u002Fdocs\u002Frealtime\u002Fwebsocket-contracts","docs\u002F05.realtime\u002F03.websocket-contracts",{"title":275,"path":276,"stem":277,"icon":278},"Server-Sent Events","\u002Fdocs\u002Frealtime\u002Fserver-sent-events","docs\u002F05.realtime\u002F04.server-sent-events","i-lucide-rss",{"title":280,"path":281,"stem":282,"icon":283},"Typed Clients","\u002Fdocs\u002Frealtime\u002Ftyped-clients","docs\u002F05.realtime\u002F05.typed-clients","i-lucide-plug-zap",{"title":285,"path":286,"stem":287,"icon":259},"AsyncAPI","\u002Fdocs\u002Frealtime\u002Fasyncapi","docs\u002F05.realtime\u002F06.asyncapi",{"title":289,"path":290,"stem":291,"icon":80},"Durable Objects","\u002Fdocs\u002Frealtime\u002Fdurable-objects","docs\u002F05.realtime\u002F07.durable-objects",{"title":293,"icon":294,"path":295,"stem":296,"children":297,"page":45},"Deploy","i-lucide-cloud-upload","\u002Fdocs\u002Fdeploy","docs\u002F06.deploy",[298,301,306,311,316,321,326,331,336,341,345,350],{"title":142,"path":299,"stem":300,"icon":6},"\u002Fdocs\u002Fdeploy\u002Foverview","docs\u002F06.deploy\u002F01.overview",{"title":302,"path":303,"stem":304,"icon":305},"Node","\u002Fdocs\u002Fdeploy\u002Fnode","docs\u002F06.deploy\u002F02.node","la:node-js",{"title":307,"path":308,"stem":309,"icon":310},"Cloudflare","\u002Fdocs\u002Fdeploy\u002Fcloudflare","docs\u002F06.deploy\u002F03.cloudflare","simple-icons:cloudflare",{"title":312,"path":313,"stem":314,"icon":315},"Vercel","\u002Fdocs\u002Fdeploy\u002Fvercel","docs\u002F06.deploy\u002F04.vercel","ri:vercel-fill",{"title":317,"path":318,"stem":319,"icon":320},"Netlify","\u002Fdocs\u002Fdeploy\u002Fnetlify","docs\u002F06.deploy\u002F05.netlify","i-simple-icons-netlify",{"title":322,"path":323,"stem":324,"icon":325},"AWS Lambda","\u002Fdocs\u002Fdeploy\u002Faws-lambda","docs\u002F06.deploy\u002F06.aws-lambda","hugeicons:aws-lambda",{"title":327,"path":328,"stem":329,"icon":330},"Deno Deploy","\u002Fdocs\u002Fdeploy\u002Fdeno-deploy","docs\u002F06.deploy\u002F07.deno-deploy","simple-icons:denodeploy",{"title":332,"path":333,"stem":334,"icon":335},"Nitro","\u002Fdocs\u002Fdeploy\u002Fnitro","docs\u002F06.deploy\u002F08.nitro","i-unjs-nitro",{"title":337,"path":338,"stem":339,"icon":340},"Nuxt","\u002Fdocs\u002Fdeploy\u002Fnuxt","docs\u002F06.deploy\u002F09.nuxt","i-devicon-nuxt",{"title":342,"path":343,"stem":344,"icon":236},"Mixed-runtime split","\u002Fdocs\u002Fdeploy\u002Fmixed-runtime-split","docs\u002F06.deploy\u002F10.mixed-runtime-split",{"title":346,"path":347,"stem":348,"icon":349},"Hosts","\u002Fdocs\u002Fdeploy\u002Fhosts","docs\u002F06.deploy\u002F11.hosts","i-lucide-map",{"title":351,"path":352,"stem":353,"icon":354},"Cross-service events","\u002Fdocs\u002Fdeploy\u002Fcross-service-events","docs\u002F06.deploy\u002F12.cross-service-events","i-lucide-network",{"title":356,"icon":357,"path":358,"stem":359,"children":360,"page":45},"CLI","i-lucide-terminal","\u002Fdocs\u002Fcli","docs\u002F07.cli",[361,365,369,373],{"title":362,"path":363,"stem":364,"icon":357},"The heximon CLI","\u002Fdocs\u002Fcli\u002Foverview","docs\u002F07.cli\u002F01.overview",{"title":366,"path":367,"stem":368,"icon":137},"Create a New App","\u002Fdocs\u002Fcli\u002Fcreate","docs\u002F07.cli\u002F02.create",{"title":370,"path":371,"stem":372,"icon":95},"Migrations from the CLI","\u002Fdocs\u002Fcli\u002Fmigrations","docs\u002F07.cli\u002F03.migrations",{"title":374,"path":375,"stem":376,"icon":6},"Deploying a Heximon app","\u002Fdocs\u002Fcli\u002Fdeploy","docs\u002F07.cli\u002F04.deploy",{"title":378,"icon":379,"path":380,"stem":381,"children":382,"page":45},"Under the Hood","i-lucide-wrench","\u002Fdocs\u002Funder-the-hood","docs\u002F08.under-the-hood",[383,388,393,397,402,407,411,415],{"title":384,"path":385,"stem":386,"icon":387},"How the Compiler Works","\u002Fdocs\u002Funder-the-hood\u002Fhow-the-compiler-works","docs\u002F08.under-the-hood\u002F01.how-the-compiler-works","i-lucide-cog",{"title":389,"path":390,"stem":391,"icon":392},"Compiler","\u002Fdocs\u002Funder-the-hood\u002Fextending-the-compiler","docs\u002F08.under-the-hood\u002F02.extending-the-compiler","i-lucide-cpu",{"title":394,"path":395,"stem":396,"icon":357},"Compiler Diagnostics","\u002Fdocs\u002Funder-the-hood\u002Fcompiler-diagnostics","docs\u002F08.under-the-hood\u002F03.compiler-diagnostics",{"title":398,"path":399,"stem":400,"icon":401},"Library Mode","\u002Fdocs\u002Funder-the-hood\u002Flibrary-mode","docs\u002F08.under-the-hood\u002F04.library-mode","i-lucide-package",{"title":403,"path":404,"stem":405,"icon":406},"Other bundlers","\u002Fdocs\u002Funder-the-hood\u002Falternate-bundlers","docs\u002F08.under-the-hood\u002F05.alternate-bundlers","i-lucide-blocks",{"title":408,"path":409,"stem":410,"icon":401},"Packages","\u002Fdocs\u002Funder-the-hood\u002Fpackages","docs\u002F08.under-the-hood\u002F06.packages",{"title":412,"path":413,"stem":414,"icon":207},"AI Skills","\u002Fdocs\u002Funder-the-hood\u002Fai-and-agents","docs\u002F08.under-the-hood\u002F07.ai-and-agents",{"title":416,"path":417,"stem":418,"icon":419},"Advanced DI","\u002Fdocs\u002Funder-the-hood\u002Fadvanced-di","docs\u002F08.under-the-hood\u002F08.advanced-di","i-lucide-git-fork",{"title":421,"icon":422,"path":423,"stem":424,"children":425,"page":45},"Recipes","i-lucide-book-open-check","\u002Fdocs\u002Frecipes","docs\u002F09.recipes",[426,431,436,440,444,448,452,456,460,465,469,474,479,484,488],{"title":427,"path":428,"stem":429,"icon":430},"Send an Email","\u002Fdocs\u002Frecipes\u002Fsend-an-email","docs\u002F09.recipes\u002F01.send-an-email","i-lucide-send",{"title":432,"path":433,"stem":434,"icon":435},"Upload a File","\u002Fdocs\u002Frecipes\u002Fupload-a-file","docs\u002F09.recipes\u002F02.upload-a-file","i-lucide-upload",{"title":437,"path":438,"stem":439,"icon":24},"Cache an Expensive Call","\u002Fdocs\u002Frecipes\u002Fcache-an-expensive-call","docs\u002F09.recipes\u002F03.cache-an-expensive-call",{"title":441,"path":442,"stem":443,"icon":154},"Paginate a List","\u002Fdocs\u002Frecipes\u002Fpaginate-a-list","docs\u002F09.recipes\u002F04.paginate-a-list",{"title":445,"path":446,"stem":447,"icon":65},"Protect Admin Routes","\u002Fdocs\u002Frecipes\u002Fprotect-admin-routes","docs\u002F09.recipes\u002F05.protect-admin-routes",{"title":449,"path":450,"stem":451,"icon":178},"Health Probes and a Nightly Job","\u002Fdocs\u002Frecipes\u002Fhealth-probes-and-a-nightly-job","docs\u002F09.recipes\u002F06.health-probes-and-a-nightly-job",{"title":453,"path":454,"stem":455,"icon":80},"Build a CRUD API","\u002Fdocs\u002Frecipes\u002Fcrud-api","docs\u002F09.recipes\u002F07.crud-api",{"title":457,"path":458,"stem":459,"icon":100},"Add Authentication","\u002Fdocs\u002Frecipes\u002Fadd-authentication","docs\u002F09.recipes\u002F08.add-authentication",{"title":461,"path":462,"stem":463,"icon":464},"Background Jobs","\u002Fdocs\u002Frecipes\u002Fbackground-jobs","docs\u002F09.recipes\u002F09.background-jobs","i-lucide-timer",{"title":466,"path":467,"stem":468,"icon":149},"Decouple Features with Events","\u002Fdocs\u002Frecipes\u002Fevent-driven-module","docs\u002F09.recipes\u002F10.event-driven-module",{"title":470,"path":471,"stem":472,"icon":473},"Build a DDD Aggregate","\u002Fdocs\u002Frecipes\u002Fddd-aggregate","docs\u002F09.recipes\u002F11.ddd-aggregate","i-lucide-box",{"title":475,"path":476,"stem":477,"icon":478},"Publish a Feature Package","\u002Fdocs\u002Frecipes\u002Ffeature-package","docs\u002F09.recipes\u002F12.feature-package","i-lucide-package-open",{"title":480,"path":481,"stem":482,"icon":483},"Reliable Integration Events","\u002Fdocs\u002Frecipes\u002Freliable-integration-events","docs\u002F09.recipes\u002F13.reliable-integration-events","i-lucide-inbox",{"title":485,"path":486,"stem":487,"icon":95},"Reactive Choreography","\u002Fdocs\u002Frecipes\u002Freactive-choreography","docs\u002F09.recipes\u002F14.reactive-choreography",{"title":489,"path":490,"stem":491,"icon":492},"Build a Production CRUD API","\u002Fdocs\u002Frecipes\u002Fproduction-crud-api","docs\u002F09.recipes\u002F15.production-crud-api","i-lucide-layers",{"id":494,"title":194,"body":495,"description":3336,"extension":3337,"links":3338,"meta":3339,"navigation":3340,"path":195,"seo":3341,"stem":196,"__hash__":3342},"docs\u002Fdocs\u002F03.capabilities\u002F12.observability.md",{"type":496,"value":497,"toc":3322},"minimark",[498,502,513,516,521,535,777,784,790,798,823,1126,1135,1144,1159,1163,1169,1444,1451,1672,1675,1867,1878,1886,1899,2241,2263,2280,2331,2335,2347,2497,2507,2674,2689,2696,2708,2864,2884,2894,2897,2901,2919,2980,3005,3017,3169,3182,3196,3207,3211,3216,3251,3266,3270,3318],[499,500,501],"p",{},"You want per-module latency and error attribution without threading a tracer through every handler — and you\nwant it good enough to answer \"which module is slow?\" before you decide what to extract into its own service.",[499,503,504,508,509,512],{},[505,506,507],"code",{},"@heximon\u002Fotel"," gives you exactly that with one line of config and zero application code: the compiler already\nresolved the owning module of every controller, command handler, query handler, and event handler at build time,\nso the plugin bakes ",[505,510,511],{},"heximon.module"," onto every span as a string literal.",[499,514,515],{},"There is no runtime class-to-module lookup — and there is no other framework where the trace already knows which\nmodule produced the span, because no runtime-DI container carries that mapping.",[517,518,520],"h2",{"id":519},"the-mental-model-the-module-is-baked-not-looked-up","The mental model: the module is baked, not looked up",[499,522,523,524,526,527,530,531,534],{},"A span needs three things to be useful for attribution: a name, a kind, and the owning module. Heximon's compiler\nresolves the owning module of every dispatched handler while it builds the static DI graph. ",[505,525,507],{}," reads\nthat graph and emits a ",[505,528,529],{},"key → span model"," map into a generated ",[505,532,533],{},"otel.wiring.js"," — the module name is a frozen\nstring literal in the output, established at build time:",[536,537,542],"pre",{"className":538,"code":539,"filename":533,"language":540,"meta":541,"style":541},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Per-dispatch-key span model baked at compile time: span name, kind, and module-attributed\n\u002F\u002F attributes for every command, query, event, and queue handler the dispatch tiers published.\nconst otelSpanModels = {\n  \"CreateOrderCommand#a0892bac\": {\n    \"spanName\": \"CommandBus.dispatch CreateOrderCommand\",\n    \"spanKind\": \"INTERNAL\",\n    \"attributes\": {\n      \"messaging.system\": \"heximon.cqrs\",\n      \"messaging.operation\": \"process\",\n      \"heximon.message.type\": \"CreateOrderCommand\",\n      \"heximon.module\": \"AppModule\",\n      \"heximon.handler\": \"CreateOrderHandler\"\n    }\n  }\n};\n","js","",[505,543,544,553,559,577,595,620,641,655,677,698,719,739,759,765,771],{"__ignoreMap":541},[545,546,549],"span",{"class":547,"line":548},"line",1,[545,550,552],{"class":551},"sHwdD","\u002F\u002F Per-dispatch-key span model baked at compile time: span name, kind, and module-attributed\n",[545,554,556],{"class":547,"line":555},2,[545,557,558],{"class":551},"\u002F\u002F attributes for every command, query, event, and queue handler the dispatch tiers published.\n",[545,560,562,566,570,574],{"class":547,"line":561},3,[545,563,565],{"class":564},"spNyl","const",[545,567,569],{"class":568},"sTEyZ"," otelSpanModels ",[545,571,573],{"class":572},"sMK4o","=",[545,575,576],{"class":572}," {\n",[545,578,580,583,587,590,593],{"class":547,"line":579},4,[545,581,582],{"class":572},"  \"",[545,584,586],{"class":585},"swJcz","CreateOrderCommand#a0892bac",[545,588,589],{"class":572},"\"",[545,591,592],{"class":572},":",[545,594,576],{"class":572},[545,596,598,601,604,606,608,611,615,617],{"class":547,"line":597},5,[545,599,600],{"class":572},"    \"",[545,602,603],{"class":585},"spanName",[545,605,589],{"class":572},[545,607,592],{"class":572},[545,609,610],{"class":572}," \"",[545,612,614],{"class":613},"sfazB","CommandBus.dispatch CreateOrderCommand",[545,616,589],{"class":572},[545,618,619],{"class":572},",\n",[545,621,623,625,628,630,632,634,637,639],{"class":547,"line":622},6,[545,624,600],{"class":572},[545,626,627],{"class":585},"spanKind",[545,629,589],{"class":572},[545,631,592],{"class":572},[545,633,610],{"class":572},[545,635,636],{"class":613},"INTERNAL",[545,638,589],{"class":572},[545,640,619],{"class":572},[545,642,644,646,649,651,653],{"class":547,"line":643},7,[545,645,600],{"class":572},[545,647,648],{"class":585},"attributes",[545,650,589],{"class":572},[545,652,592],{"class":572},[545,654,576],{"class":572},[545,656,658,661,664,666,668,670,673,675],{"class":547,"line":657},8,[545,659,660],{"class":572},"      \"",[545,662,663],{"class":585},"messaging.system",[545,665,589],{"class":572},[545,667,592],{"class":572},[545,669,610],{"class":572},[545,671,672],{"class":613},"heximon.cqrs",[545,674,589],{"class":572},[545,676,619],{"class":572},[545,678,680,682,685,687,689,691,694,696],{"class":547,"line":679},9,[545,681,660],{"class":572},[545,683,684],{"class":585},"messaging.operation",[545,686,589],{"class":572},[545,688,592],{"class":572},[545,690,610],{"class":572},[545,692,693],{"class":613},"process",[545,695,589],{"class":572},[545,697,619],{"class":572},[545,699,701,703,706,708,710,712,715,717],{"class":547,"line":700},10,[545,702,660],{"class":572},[545,704,705],{"class":585},"heximon.message.type",[545,707,589],{"class":572},[545,709,592],{"class":572},[545,711,610],{"class":572},[545,713,714],{"class":613},"CreateOrderCommand",[545,716,589],{"class":572},[545,718,619],{"class":572},[545,720,722,724,726,728,730,732,735,737],{"class":547,"line":721},11,[545,723,660],{"class":572},[545,725,511],{"class":585},[545,727,589],{"class":572},[545,729,592],{"class":572},[545,731,610],{"class":572},[545,733,734],{"class":613},"AppModule",[545,736,589],{"class":572},[545,738,619],{"class":572},[545,740,742,744,747,749,751,753,756],{"class":547,"line":741},12,[545,743,660],{"class":572},[545,745,746],{"class":585},"heximon.handler",[545,748,589],{"class":572},[545,750,592],{"class":572},[545,752,610],{"class":572},[545,754,755],{"class":613},"CreateOrderHandler",[545,757,758],{"class":572},"\"\n",[545,760,762],{"class":547,"line":761},13,[545,763,764],{"class":572},"    }\n",[545,766,768],{"class":547,"line":767},14,[545,769,770],{"class":572},"  }\n",[545,772,774],{"class":547,"line":773},15,[545,775,776],{"class":572},"};\n",[499,778,779,780,783],{},"That's the whole differentiator. Because ",[505,781,782],{},"\"heximon.module\": \"AppModule\""," is a literal in the generated wiring,\nthe runtime span carries it for free — no reflection, no container walk, no decorator.",[499,785,786,787,789],{},"Group your traces by ",[505,788,511],{}," and you get per-module p99 latency and error rates straight from your collector. When one module\nconsistently dominates the latency or owns the errors, that's your microservice-extraction signal — sourced from\nthe trace, not from guesswork.",[517,791,793,794,797],{"id":792},"add-the-plugin-and-set-the-otel-key-the-only-step","Add the plugin and set the ",[505,795,796],{},"otel"," key — the only step",[499,799,800,801,803,804,807,808,811,812,814,815,818,819,822],{},"Tracing is off by default: nothing from ",[505,802,507],{}," is imported unless you register the plugin. Register\n",[505,805,806],{},"new OtelPlugin()"," in the ",[505,809,810],{},"plugins"," array and set the top-level ",[505,813,796],{}," config key — an augmentation\n",[505,816,817],{},"@heximon\u002Fotel\u002Fcompiler"," adds to the ",[505,820,821],{},"heximon.config.ts"," shape, read by the plugin at build time (the plugin\ntakes no constructor argument):",[536,824,828],{"className":825,"code":826,"filename":821,"language":827,"meta":541,"style":541},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { defineHeximonConfig } from \"@heximon\u002Fbuild\";\nimport { CqrsPlugin } from \"@heximon\u002Fcqrs\u002Fcompiler\";\nimport { EventEmitterPlugin } from \"@heximon\u002Fevents\u002Fcompiler\";\nimport { HttpPlugin } from \"@heximon\u002Fhttp\u002Fcompiler\";\nimport { OtelPlugin } from \"@heximon\u002Fotel\u002Fcompiler\";\n\nexport default defineHeximonConfig({\n  plugins: [new HttpPlugin(), new CqrsPlugin(), new EventEmitterPlugin(), new OtelPlugin()],\n  otel: {\n    endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,\n    protocol: \"http\",\n    resourceAttributes: { \"deployment.environment\": \"development\" },\n    batchOptions: { exportTimeoutMillis: 300 },\n  },\n});\n","ts",[505,829,830,858,880,902,924,945,951,968,1015,1024,1047,1063,1091,1111,1116],{"__ignoreMap":541},[545,831,832,836,839,842,845,848,850,853,855],{"class":547,"line":548},[545,833,835],{"class":834},"s7zQu","import",[545,837,838],{"class":572}," {",[545,840,841],{"class":568}," defineHeximonConfig",[545,843,844],{"class":572}," }",[545,846,847],{"class":834}," from",[545,849,610],{"class":572},[545,851,852],{"class":613},"@heximon\u002Fbuild",[545,854,589],{"class":572},[545,856,857],{"class":572},";\n",[545,859,860,862,864,867,869,871,873,876,878],{"class":547,"line":555},[545,861,835],{"class":834},[545,863,838],{"class":572},[545,865,866],{"class":568}," CqrsPlugin",[545,868,844],{"class":572},[545,870,847],{"class":834},[545,872,610],{"class":572},[545,874,875],{"class":613},"@heximon\u002Fcqrs\u002Fcompiler",[545,877,589],{"class":572},[545,879,857],{"class":572},[545,881,882,884,886,889,891,893,895,898,900],{"class":547,"line":561},[545,883,835],{"class":834},[545,885,838],{"class":572},[545,887,888],{"class":568}," EventEmitterPlugin",[545,890,844],{"class":572},[545,892,847],{"class":834},[545,894,610],{"class":572},[545,896,897],{"class":613},"@heximon\u002Fevents\u002Fcompiler",[545,899,589],{"class":572},[545,901,857],{"class":572},[545,903,904,906,908,911,913,915,917,920,922],{"class":547,"line":579},[545,905,835],{"class":834},[545,907,838],{"class":572},[545,909,910],{"class":568}," HttpPlugin",[545,912,844],{"class":572},[545,914,847],{"class":834},[545,916,610],{"class":572},[545,918,919],{"class":613},"@heximon\u002Fhttp\u002Fcompiler",[545,921,589],{"class":572},[545,923,857],{"class":572},[545,925,926,928,930,933,935,937,939,941,943],{"class":547,"line":597},[545,927,835],{"class":834},[545,929,838],{"class":572},[545,931,932],{"class":568}," OtelPlugin",[545,934,844],{"class":572},[545,936,847],{"class":834},[545,938,610],{"class":572},[545,940,817],{"class":613},[545,942,589],{"class":572},[545,944,857],{"class":572},[545,946,947],{"class":547,"line":622},[545,948,950],{"emptyLinePlaceholder":949},true,"\n",[545,952,953,956,959,962,965],{"class":547,"line":643},[545,954,955],{"class":834},"export",[545,957,958],{"class":834}," default",[545,960,841],{"class":961},"s2Zo4",[545,963,964],{"class":568},"(",[545,966,967],{"class":572},"{\n",[545,969,970,973,975,978,981,983,986,989,992,994,996,998,1000,1002,1004,1006,1008,1010,1013],{"class":547,"line":657},[545,971,972],{"class":585},"  plugins",[545,974,592],{"class":572},[545,976,977],{"class":568}," [",[545,979,980],{"class":572},"new",[545,982,910],{"class":961},[545,984,985],{"class":568},"()",[545,987,988],{"class":572},",",[545,990,991],{"class":572}," new",[545,993,866],{"class":961},[545,995,985],{"class":568},[545,997,988],{"class":572},[545,999,991],{"class":572},[545,1001,888],{"class":961},[545,1003,985],{"class":568},[545,1005,988],{"class":572},[545,1007,991],{"class":572},[545,1009,932],{"class":961},[545,1011,1012],{"class":568},"()]",[545,1014,619],{"class":572},[545,1016,1017,1020,1022],{"class":547,"line":679},[545,1018,1019],{"class":585},"  otel",[545,1021,592],{"class":572},[545,1023,576],{"class":572},[545,1025,1026,1029,1031,1034,1037,1040,1042,1045],{"class":547,"line":700},[545,1027,1028],{"class":585},"    endpoint",[545,1030,592],{"class":572},[545,1032,1033],{"class":568}," process",[545,1035,1036],{"class":572},".",[545,1038,1039],{"class":568},"env",[545,1041,1036],{"class":572},[545,1043,1044],{"class":568},"OTEL_EXPORTER_OTLP_ENDPOINT",[545,1046,619],{"class":572},[545,1048,1049,1052,1054,1056,1059,1061],{"class":547,"line":721},[545,1050,1051],{"class":585},"    protocol",[545,1053,592],{"class":572},[545,1055,610],{"class":572},[545,1057,1058],{"class":613},"http",[545,1060,589],{"class":572},[545,1062,619],{"class":572},[545,1064,1065,1068,1070,1072,1074,1077,1079,1081,1083,1086,1088],{"class":547,"line":741},[545,1066,1067],{"class":585},"    resourceAttributes",[545,1069,592],{"class":572},[545,1071,838],{"class":572},[545,1073,610],{"class":572},[545,1075,1076],{"class":585},"deployment.environment",[545,1078,589],{"class":572},[545,1080,592],{"class":572},[545,1082,610],{"class":572},[545,1084,1085],{"class":613},"development",[545,1087,589],{"class":572},[545,1089,1090],{"class":572}," },\n",[545,1092,1093,1096,1098,1100,1103,1105,1109],{"class":547,"line":761},[545,1094,1095],{"class":585},"    batchOptions",[545,1097,592],{"class":572},[545,1099,838],{"class":572},[545,1101,1102],{"class":585}," exportTimeoutMillis",[545,1104,592],{"class":572},[545,1106,1108],{"class":1107},"sbssI"," 300",[545,1110,1090],{"class":572},[545,1112,1113],{"class":547,"line":767},[545,1114,1115],{"class":572},"  },\n",[545,1117,1118,1121,1124],{"class":547,"line":773},[545,1119,1120],{"class":572},"}",[545,1122,1123],{"class":568},")",[545,1125,857],{"class":572},[499,1127,1128,1131,1132,1134],{},[505,1129,1130],{},"OtelPlugin"," owns no module-config namespace key — it discovers nothing from your modules, and it reads its\nconfiguration from the top-level ",[505,1133,796],{}," key rather than a constructor argument.",[499,1136,1137,1138,1140,1141,1143],{},"Instead it reads the HTTP, CQRS, and event dispatch graphs the other plugins publish, and bakes a ",[505,1139,511],{},"-attributed span model into the\ngenerated ",[505,1142,533],{},". The HTTP server span, the command\u002Fquery dispatch spans, and the serial event-handler\nspans are all produced with no further configuration.",[1145,1146,1148,1152,1153,1155,1156,1158],"callout",{"type":1147},"info",[1149,1150,1151],"strong",{},"Decoupled, so an omitted tier emits nothing."," Each dispatch tier publishes its handlers and the OTel plugin\nreads them without a hard plugin dependency. An app that registers ",[505,1154,1130],{}," but omits a tier (say, no CQRS)\nemits no wiring for that tier — its generated output is byte-identical to an app with no ",[505,1157,1130],{},". You only\npay for the tiers you actually run.",[517,1160,1162],{"id":1161},"zero-application-code-at-the-dispatch-seam","Zero application code at the dispatch seam",[499,1164,1165,1166,1168],{},"The spans wrap your handlers without any of them knowing. The controller dispatches CQRS messages, the command\nhandler emits an event — and not one of them imports anything from ",[505,1167,507],{},". This is the controller from\nthe gap's otel-node example:",[536,1170,1173],{"className":825,"code":1171,"filename":1172,"language":827,"meta":541,"style":541},"public async place(action: Post\u003C\"\u002F\", { body: PlaceOrderBody }>): Promise\u003COrder> {\n  const body = await action.request.readValidatedBody();\n  const id = OrderId.generate();\n\n  await this.commandBus.execute(\n    new PlaceOrderCommand(id, body.customerEmail, body.product, body.quantity),\n  );\n\n  const order = await this.queryBus.execute(new GetOrderQuery(id));\n\n  if (!order) {\n    throw new NotFoundError(`Order ${id} not found`);\n  }\n\n  action.response.status = 201;\n\n  return order;\n}\n","src\u002Forders\u002Forders.controller.ts",[505,1174,1175,1228,1254,1271,1275,1280,1312,1317,1321,1351,1355,1373,1407,1411,1415,1427,1432,1438],{"__ignoreMap":541},[545,1176,1177,1180,1183,1186,1189,1191,1194,1196,1198,1200,1203,1205,1208,1211,1214,1218,1220,1223,1226],{"class":547,"line":548},[545,1178,1179],{"class":568},"public async ",[545,1181,1182],{"class":961},"place",[545,1184,1185],{"class":568},"(action: Post",[545,1187,1188],{"class":572},"\u003C",[545,1190,589],{"class":572},[545,1192,1193],{"class":613},"\u002F",[545,1195,589],{"class":572},[545,1197,988],{"class":572},[545,1199,838],{"class":572},[545,1201,1202],{"class":585}," body",[545,1204,592],{"class":572},[545,1206,1207],{"class":568}," PlaceOrderBody ",[545,1209,1210],{"class":572},"}>",[545,1212,1213],{"class":568},"): ",[545,1215,1217],{"class":1216},"sBMFI","Promise",[545,1219,1188],{"class":572},[545,1221,1222],{"class":568},"Order",[545,1224,1225],{"class":572},">",[545,1227,576],{"class":572},[545,1229,1230,1233,1235,1238,1241,1243,1246,1248,1251],{"class":547,"line":555},[545,1231,1232],{"class":568},"  const body ",[545,1234,573],{"class":572},[545,1236,1237],{"class":834}," await",[545,1239,1240],{"class":568}," action",[545,1242,1036],{"class":572},[545,1244,1245],{"class":568},"request",[545,1247,1036],{"class":572},[545,1249,1250],{"class":961},"readValidatedBody",[545,1252,1253],{"class":568},"();\n",[545,1255,1256,1259,1261,1264,1266,1269],{"class":547,"line":561},[545,1257,1258],{"class":568},"  const id ",[545,1260,573],{"class":572},[545,1262,1263],{"class":568}," OrderId",[545,1265,1036],{"class":572},[545,1267,1268],{"class":961},"generate",[545,1270,1253],{"class":568},[545,1272,1273],{"class":547,"line":579},[545,1274,950],{"emptyLinePlaceholder":949},[545,1276,1277],{"class":547,"line":597},[545,1278,1279],{"class":568},"  await this.commandBus.execute(\n",[545,1281,1282,1285,1288,1290,1294,1296,1299,1301,1304,1306,1309],{"class":547,"line":622},[545,1283,1284],{"class":568},"    new ",[545,1286,1287],{"class":585},"PlaceOrderCommand",[545,1289,964],{"class":572},[545,1291,1293],{"class":1292},"sHdIc","id",[545,1295,988],{"class":572},[545,1297,1298],{"class":568}," body.customerEmail",[545,1300,988],{"class":572},[545,1302,1303],{"class":568}," body.product",[545,1305,988],{"class":572},[545,1307,1308],{"class":568}," body.quantity",[545,1310,1311],{"class":572},"),\n",[545,1313,1314],{"class":547,"line":643},[545,1315,1316],{"class":568},"  );\n",[545,1318,1319],{"class":547,"line":657},[545,1320,950],{"emptyLinePlaceholder":949},[545,1322,1323,1326,1328,1330,1333,1336,1338,1341,1343,1345,1348],{"class":547,"line":679},[545,1324,1325],{"class":568},"  const order ",[545,1327,573],{"class":572},[545,1329,1237],{"class":834},[545,1331,1332],{"class":572}," this.",[545,1334,1335],{"class":568},"queryBus",[545,1337,1036],{"class":572},[545,1339,1340],{"class":961},"execute",[545,1342,964],{"class":568},[545,1344,980],{"class":572},[545,1346,1347],{"class":961}," GetOrderQuery",[545,1349,1350],{"class":568},"(id));\n",[545,1352,1353],{"class":547,"line":700},[545,1354,950],{"emptyLinePlaceholder":949},[545,1356,1357,1360,1363,1366,1369,1371],{"class":547,"line":721},[545,1358,1359],{"class":585},"  if",[545,1361,1362],{"class":572}," (",[545,1364,1365],{"class":568},"!",[545,1367,1368],{"class":1292},"order",[545,1370,1123],{"class":572},[545,1372,576],{"class":572},[545,1374,1375,1378,1380,1383,1385,1388,1391,1394,1396,1398,1401,1403,1405],{"class":547,"line":741},[545,1376,1377],{"class":834},"    throw",[545,1379,991],{"class":572},[545,1381,1382],{"class":961}," NotFoundError",[545,1384,964],{"class":585},[545,1386,1387],{"class":572},"`",[545,1389,1390],{"class":613},"Order ",[545,1392,1393],{"class":572},"${",[545,1395,1293],{"class":568},[545,1397,1120],{"class":572},[545,1399,1400],{"class":613}," not found",[545,1402,1387],{"class":572},[545,1404,1123],{"class":585},[545,1406,857],{"class":572},[545,1408,1409],{"class":547,"line":761},[545,1410,770],{"class":572},[545,1412,1413],{"class":547,"line":767},[545,1414,950],{"emptyLinePlaceholder":949},[545,1416,1417,1420,1422,1425],{"class":547,"line":773},[545,1418,1419],{"class":568},"  action.response.status ",[545,1421,573],{"class":572},[545,1423,1424],{"class":1107}," 201",[545,1426,857],{"class":568},[545,1428,1430],{"class":547,"line":1429},16,[545,1431,950],{"emptyLinePlaceholder":949},[545,1433,1435],{"class":547,"line":1434},17,[545,1436,1437],{"class":568},"  return order;\n",[545,1439,1441],{"class":547,"line":1440},18,[545,1442,1443],{"class":572},"}\n",[499,1445,1446,1447,1450],{},"The command handler persists the order and emits a class-tier event on the injected ",[505,1448,1449],{},"EventBus"," — the third tier\non the same trace:",[536,1452,1455],{"className":825,"code":1453,"filename":1454,"language":827,"meta":541,"style":541},"public override async handle(command: PlaceOrderCommand): Promise\u003Cvoid> {\n  const order: Order = {\n    id: command.id,\n    customerEmail: command.customerEmail,\n    product: command.product,\n    quantity: command.quantity,\n    confirmed: false,\n  };\n\n  this.orderStore.save(order);\n\n  \u002F\u002F OrderPlacedEvent extends BaseEvent, so the live instance is emittable with no cast.\n  await this.eventBus.emitAsync(\n    new OrderPlacedEvent(command.id, command.customerEmail, command.product, command.quantity),\n  );\n}\n","src\u002Forders\u002Fcommands\u002Fplace-order.handler.ts",[505,1456,1457,1475,1491,1507,1523,1539,1555,1568,1575,1579,1595,1599,1604,1622,1664,1668],{"__ignoreMap":541},[545,1458,1459,1462,1465,1468,1470,1473],{"class":547,"line":548},[545,1460,1461],{"class":568},"public override async ",[545,1463,1464],{"class":961},"handle",[545,1466,1467],{"class":568},"(command: PlaceOrderCommand): ",[545,1469,1217],{"class":1216},[545,1471,1472],{"class":572},"\u003Cvoid>",[545,1474,576],{"class":572},[545,1476,1477,1480,1482,1484,1487,1489],{"class":547,"line":555},[545,1478,1479],{"class":568},"  const ",[545,1481,1368],{"class":585},[545,1483,592],{"class":572},[545,1485,1486],{"class":568}," Order ",[545,1488,573],{"class":572},[545,1490,576],{"class":572},[545,1492,1493,1496,1498,1501,1503,1505],{"class":547,"line":561},[545,1494,1495],{"class":585},"    id",[545,1497,592],{"class":572},[545,1499,1500],{"class":568}," command",[545,1502,1036],{"class":572},[545,1504,1293],{"class":568},[545,1506,619],{"class":572},[545,1508,1509,1512,1514,1516,1518,1521],{"class":547,"line":579},[545,1510,1511],{"class":585},"    customerEmail",[545,1513,592],{"class":572},[545,1515,1500],{"class":568},[545,1517,1036],{"class":572},[545,1519,1520],{"class":568},"customerEmail",[545,1522,619],{"class":572},[545,1524,1525,1528,1530,1532,1534,1537],{"class":547,"line":597},[545,1526,1527],{"class":585},"    product",[545,1529,592],{"class":572},[545,1531,1500],{"class":568},[545,1533,1036],{"class":572},[545,1535,1536],{"class":568},"product",[545,1538,619],{"class":572},[545,1540,1541,1544,1546,1548,1550,1553],{"class":547,"line":622},[545,1542,1543],{"class":585},"    quantity",[545,1545,592],{"class":572},[545,1547,1500],{"class":568},[545,1549,1036],{"class":572},[545,1551,1552],{"class":568},"quantity",[545,1554,619],{"class":572},[545,1556,1557,1560,1562,1566],{"class":547,"line":643},[545,1558,1559],{"class":585},"    confirmed",[545,1561,592],{"class":572},[545,1563,1565],{"class":1564},"sfNiH"," false",[545,1567,619],{"class":572},[545,1569,1570,1573],{"class":547,"line":657},[545,1571,1572],{"class":572},"  }",[545,1574,857],{"class":568},[545,1576,1577],{"class":547,"line":679},[545,1578,950],{"emptyLinePlaceholder":949},[545,1580,1581,1584,1587,1589,1592],{"class":547,"line":700},[545,1582,1583],{"class":572},"  this.",[545,1585,1586],{"class":568},"orderStore",[545,1588,1036],{"class":572},[545,1590,1591],{"class":961},"save",[545,1593,1594],{"class":568},"(order);\n",[545,1596,1597],{"class":547,"line":721},[545,1598,950],{"emptyLinePlaceholder":949},[545,1600,1601],{"class":547,"line":741},[545,1602,1603],{"class":551},"  \u002F\u002F OrderPlacedEvent extends BaseEvent, so the live instance is emittable with no cast.\n",[545,1605,1606,1609,1611,1614,1616,1619],{"class":547,"line":761},[545,1607,1608],{"class":834},"  await",[545,1610,1332],{"class":572},[545,1612,1613],{"class":568},"eventBus",[545,1615,1036],{"class":572},[545,1617,1618],{"class":961},"emitAsync",[545,1620,1621],{"class":568},"(\n",[545,1623,1624,1627,1630,1633,1635,1637,1639,1641,1643,1645,1647,1649,1651,1653,1655,1657,1659,1662],{"class":547,"line":767},[545,1625,1626],{"class":572},"    new",[545,1628,1629],{"class":961}," OrderPlacedEvent",[545,1631,1632],{"class":568},"(command",[545,1634,1036],{"class":572},[545,1636,1293],{"class":568},[545,1638,988],{"class":572},[545,1640,1500],{"class":568},[545,1642,1036],{"class":572},[545,1644,1520],{"class":568},[545,1646,988],{"class":572},[545,1648,1500],{"class":568},[545,1650,1036],{"class":572},[545,1652,1536],{"class":568},[545,1654,988],{"class":572},[545,1656,1500],{"class":568},[545,1658,1036],{"class":572},[545,1660,1661],{"class":568},"quantity)",[545,1663,619],{"class":572},[545,1665,1666],{"class":547,"line":773},[545,1667,1316],{"class":568},[545,1669,1670],{"class":547,"line":1429},[545,1671,1443],{"class":572},[499,1673,1674],{},"And the serial event handler reacts — also untouched by tracing:",[536,1676,1679],{"className":825,"code":1677,"filename":1678,"language":827,"meta":541,"style":541},"export class ConfirmOrderHandler implements EventHandler\u003COrderPlacedEvent> {\n  constructor(private readonly orderStore: OrderStore) {}\n\n  public handle(event: OrderPlacedEvent): void {\n    const order = this.orderStore.findById(event.orderId);\n\n    if (order !== undefined) {\n      this.orderStore.save({ ...order, confirmed: true });\n    }\n  }\n}\n","src\u002Forders\u002Fevents\u002Fconfirm-order.handler.ts",[505,1680,1681,1706,1732,1736,1761,1794,1798,1818,1855,1859,1863],{"__ignoreMap":541},[545,1682,1683,1685,1688,1691,1694,1697,1699,1702,1704],{"class":547,"line":548},[545,1684,955],{"class":834},[545,1686,1687],{"class":564}," class",[545,1689,1690],{"class":1216}," ConfirmOrderHandler",[545,1692,1693],{"class":564}," implements",[545,1695,1696],{"class":1216}," EventHandler",[545,1698,1188],{"class":572},[545,1700,1701],{"class":1216},"OrderPlacedEvent",[545,1703,1225],{"class":572},[545,1705,576],{"class":572},[545,1707,1708,1711,1713,1716,1719,1722,1724,1727,1729],{"class":547,"line":555},[545,1709,1710],{"class":564},"  constructor",[545,1712,964],{"class":572},[545,1714,1715],{"class":564},"private",[545,1717,1718],{"class":564}," readonly",[545,1720,1721],{"class":1292}," orderStore",[545,1723,592],{"class":572},[545,1725,1726],{"class":1216}," OrderStore",[545,1728,1123],{"class":572},[545,1730,1731],{"class":572}," {}\n",[545,1733,1734],{"class":547,"line":561},[545,1735,950],{"emptyLinePlaceholder":949},[545,1737,1738,1741,1744,1746,1749,1751,1753,1756,1759],{"class":547,"line":579},[545,1739,1740],{"class":564},"  public",[545,1742,1743],{"class":585}," handle",[545,1745,964],{"class":572},[545,1747,1748],{"class":1292},"event",[545,1750,592],{"class":572},[545,1752,1629],{"class":1216},[545,1754,1755],{"class":572},"):",[545,1757,1758],{"class":1216}," void",[545,1760,576],{"class":572},[545,1762,1763,1766,1769,1772,1774,1776,1778,1781,1783,1785,1787,1790,1792],{"class":547,"line":597},[545,1764,1765],{"class":564},"    const",[545,1767,1768],{"class":568}," order",[545,1770,1771],{"class":572}," =",[545,1773,1332],{"class":572},[545,1775,1586],{"class":568},[545,1777,1036],{"class":572},[545,1779,1780],{"class":961},"findById",[545,1782,964],{"class":585},[545,1784,1748],{"class":568},[545,1786,1036],{"class":572},[545,1788,1789],{"class":568},"orderId",[545,1791,1123],{"class":585},[545,1793,857],{"class":572},[545,1795,1796],{"class":547,"line":622},[545,1797,950],{"emptyLinePlaceholder":949},[545,1799,1800,1803,1805,1807,1810,1813,1816],{"class":547,"line":643},[545,1801,1802],{"class":834},"    if",[545,1804,1362],{"class":585},[545,1806,1368],{"class":568},[545,1808,1809],{"class":572}," !==",[545,1811,1812],{"class":572}," undefined",[545,1814,1815],{"class":585},") ",[545,1817,967],{"class":572},[545,1819,1820,1823,1825,1827,1829,1831,1834,1837,1839,1841,1844,1846,1849,1851,1853],{"class":547,"line":657},[545,1821,1822],{"class":572},"      this.",[545,1824,1586],{"class":568},[545,1826,1036],{"class":572},[545,1828,1591],{"class":961},[545,1830,964],{"class":585},[545,1832,1833],{"class":572},"{",[545,1835,1836],{"class":572}," ...",[545,1838,1368],{"class":568},[545,1840,988],{"class":572},[545,1842,1843],{"class":585}," confirmed",[545,1845,592],{"class":572},[545,1847,1848],{"class":1564}," true",[545,1850,844],{"class":572},[545,1852,1123],{"class":585},[545,1854,857],{"class":572},[545,1856,1857],{"class":547,"line":679},[545,1858,764],{"class":572},[545,1860,1861],{"class":547,"line":700},[545,1862,770],{"class":572},[545,1864,1865],{"class":547,"line":721},[545,1866,1443],{"class":572},[499,1868,1869,1870,1873,1874,1877],{},"One ",[505,1871,1872],{},"POST \u002Forders"," crosses all three instrumented tiers: the HTTP server span wraps the command-dispatch span,\nwhich wraps the event-emit span — each attributed to ",[505,1875,1876],{},"OrdersModule",", all produced from the generated wiring.",[517,1879,1881,1882,1885],{"id":1880},"adding-your-own-spans-inject-tracer-dont-import-the-sdk","Adding your own spans — inject ",[505,1883,1884],{},"Tracer",", don't import the SDK",[499,1887,1888,1889,1891,1892,1894,1895,1898],{},"Auto-instrumentation covers the dispatch seam; for a custom span around your own unit of work, inject the\n",[505,1890,1884],{}," facade ",[505,1893,507],{}," provides. It's a normal DI token — constructor-injected like any dependency, so\nyou never reach into ",[505,1896,1897],{},"@opentelemetry\u002Fapi",". This is the query handler from the gap's otel-node example:",[536,1900,1903],{"className":825,"code":1901,"filename":1902,"language":827,"meta":541,"style":541},"import type { QueryHandler } from \"@heximon\u002Fcqrs\";\nimport { Tracer } from \"@heximon\u002Fotel\";\nimport type { Order } from \"..\u002Forder\";\nimport { OrderStore } from \"..\u002Forder.store\";\nimport type { GetOrderQuery } from \".\u002Fget-order.query\";\n\nexport class GetOrderQueryHandler implements QueryHandler\u003CGetOrderQuery> {\n  constructor(\n    private readonly orderStore: OrderStore,\n    private readonly tracer: Tracer,\n  ) {}\n\n  public async handle(query: GetOrderQuery): Promise\u003COrder | undefined> {\n    return this.tracer.span(\"orders.lookup\", async (span) => {\n      span.setAttribute(\"order.id\", query.id);\n      return this.orderStore.findById(query.id);\n    });\n  }\n}\n","src\u002Forders\u002Fqueries\u002Fget-order.handler.ts",[505,1904,1905,1930,1951,1975,1996,2019,2023,2045,2051,2066,2081,2088,2092,2128,2166,2198,2223,2232,2236],{"__ignoreMap":541},[545,1906,1907,1909,1912,1914,1917,1919,1921,1923,1926,1928],{"class":547,"line":548},[545,1908,835],{"class":834},[545,1910,1911],{"class":834}," type",[545,1913,838],{"class":572},[545,1915,1916],{"class":568}," QueryHandler",[545,1918,844],{"class":572},[545,1920,847],{"class":834},[545,1922,610],{"class":572},[545,1924,1925],{"class":613},"@heximon\u002Fcqrs",[545,1927,589],{"class":572},[545,1929,857],{"class":572},[545,1931,1932,1934,1936,1939,1941,1943,1945,1947,1949],{"class":547,"line":555},[545,1933,835],{"class":834},[545,1935,838],{"class":572},[545,1937,1938],{"class":568}," Tracer",[545,1940,844],{"class":572},[545,1942,847],{"class":834},[545,1944,610],{"class":572},[545,1946,507],{"class":613},[545,1948,589],{"class":572},[545,1950,857],{"class":572},[545,1952,1953,1955,1957,1959,1962,1964,1966,1968,1971,1973],{"class":547,"line":561},[545,1954,835],{"class":834},[545,1956,1911],{"class":834},[545,1958,838],{"class":572},[545,1960,1961],{"class":568}," Order",[545,1963,844],{"class":572},[545,1965,847],{"class":834},[545,1967,610],{"class":572},[545,1969,1970],{"class":613},"..\u002Forder",[545,1972,589],{"class":572},[545,1974,857],{"class":572},[545,1976,1977,1979,1981,1983,1985,1987,1989,1992,1994],{"class":547,"line":579},[545,1978,835],{"class":834},[545,1980,838],{"class":572},[545,1982,1726],{"class":568},[545,1984,844],{"class":572},[545,1986,847],{"class":834},[545,1988,610],{"class":572},[545,1990,1991],{"class":613},"..\u002Forder.store",[545,1993,589],{"class":572},[545,1995,857],{"class":572},[545,1997,1998,2000,2002,2004,2006,2008,2010,2012,2015,2017],{"class":547,"line":597},[545,1999,835],{"class":834},[545,2001,1911],{"class":834},[545,2003,838],{"class":572},[545,2005,1347],{"class":568},[545,2007,844],{"class":572},[545,2009,847],{"class":834},[545,2011,610],{"class":572},[545,2013,2014],{"class":613},".\u002Fget-order.query",[545,2016,589],{"class":572},[545,2018,857],{"class":572},[545,2020,2021],{"class":547,"line":622},[545,2022,950],{"emptyLinePlaceholder":949},[545,2024,2025,2027,2029,2032,2034,2036,2038,2041,2043],{"class":547,"line":643},[545,2026,955],{"class":834},[545,2028,1687],{"class":564},[545,2030,2031],{"class":1216}," GetOrderQueryHandler",[545,2033,1693],{"class":564},[545,2035,1916],{"class":1216},[545,2037,1188],{"class":572},[545,2039,2040],{"class":1216},"GetOrderQuery",[545,2042,1225],{"class":572},[545,2044,576],{"class":572},[545,2046,2047,2049],{"class":547,"line":657},[545,2048,1710],{"class":564},[545,2050,1621],{"class":572},[545,2052,2053,2056,2058,2060,2062,2064],{"class":547,"line":679},[545,2054,2055],{"class":564},"    private",[545,2057,1718],{"class":564},[545,2059,1721],{"class":1292},[545,2061,592],{"class":572},[545,2063,1726],{"class":1216},[545,2065,619],{"class":572},[545,2067,2068,2070,2072,2075,2077,2079],{"class":547,"line":700},[545,2069,2055],{"class":564},[545,2071,1718],{"class":564},[545,2073,2074],{"class":1292}," tracer",[545,2076,592],{"class":572},[545,2078,1938],{"class":1216},[545,2080,619],{"class":572},[545,2082,2083,2086],{"class":547,"line":721},[545,2084,2085],{"class":572},"  )",[545,2087,1731],{"class":572},[545,2089,2090],{"class":547,"line":741},[545,2091,950],{"emptyLinePlaceholder":949},[545,2093,2094,2096,2099,2101,2103,2106,2108,2110,2112,2115,2117,2119,2122,2124,2126],{"class":547,"line":761},[545,2095,1740],{"class":564},[545,2097,2098],{"class":564}," async",[545,2100,1743],{"class":585},[545,2102,964],{"class":572},[545,2104,2105],{"class":1292},"query",[545,2107,592],{"class":572},[545,2109,1347],{"class":1216},[545,2111,1755],{"class":572},[545,2113,2114],{"class":1216}," Promise",[545,2116,1188],{"class":572},[545,2118,1222],{"class":1216},[545,2120,2121],{"class":572}," |",[545,2123,1812],{"class":1216},[545,2125,1225],{"class":572},[545,2127,576],{"class":572},[545,2129,2130,2133,2135,2138,2140,2142,2144,2146,2149,2151,2153,2155,2157,2159,2161,2164],{"class":547,"line":767},[545,2131,2132],{"class":834},"    return",[545,2134,1332],{"class":572},[545,2136,2137],{"class":568},"tracer",[545,2139,1036],{"class":572},[545,2141,545],{"class":961},[545,2143,964],{"class":585},[545,2145,589],{"class":572},[545,2147,2148],{"class":613},"orders.lookup",[545,2150,589],{"class":572},[545,2152,988],{"class":572},[545,2154,2098],{"class":564},[545,2156,1362],{"class":572},[545,2158,545],{"class":1292},[545,2160,1123],{"class":572},[545,2162,2163],{"class":564}," =>",[545,2165,576],{"class":572},[545,2167,2168,2171,2173,2176,2178,2180,2183,2185,2187,2190,2192,2194,2196],{"class":547,"line":773},[545,2169,2170],{"class":568},"      span",[545,2172,1036],{"class":572},[545,2174,2175],{"class":961},"setAttribute",[545,2177,964],{"class":585},[545,2179,589],{"class":572},[545,2181,2182],{"class":613},"order.id",[545,2184,589],{"class":572},[545,2186,988],{"class":572},[545,2188,2189],{"class":568}," query",[545,2191,1036],{"class":572},[545,2193,1293],{"class":568},[545,2195,1123],{"class":585},[545,2197,857],{"class":572},[545,2199,2200,2203,2205,2207,2209,2211,2213,2215,2217,2219,2221],{"class":547,"line":1429},[545,2201,2202],{"class":834},"      return",[545,2204,1332],{"class":572},[545,2206,1586],{"class":568},[545,2208,1036],{"class":572},[545,2210,1780],{"class":961},[545,2212,964],{"class":585},[545,2214,2105],{"class":568},[545,2216,1036],{"class":572},[545,2218,1293],{"class":568},[545,2220,1123],{"class":585},[545,2222,857],{"class":572},[545,2224,2225,2228,2230],{"class":547,"line":1434},[545,2226,2227],{"class":572},"    }",[545,2229,1123],{"class":585},[545,2231,857],{"class":572},[545,2233,2234],{"class":547,"line":1440},[545,2235,770],{"class":572},[545,2237,2239],{"class":547,"line":2238},19,[545,2240,1443],{"class":572},[499,2242,2243,2246,2247,2250,2251,2254,2255,2258,2259,2262],{},[505,2244,2245],{},"tracer.span(name, fn, options?)"," runs ",[505,2248,2249],{},"fn"," inside an active span and applies the same discipline the\nauto-instrumentation uses: the span status is set to ",[505,2252,2253],{},"OK"," on success, the exception is recorded with status\n",[505,2256,2257],{},"ERROR"," on a throw (then re-thrown), and the span is ended in a ",[505,2260,2261],{},"finally"," either way.",[499,2264,2265,2266,2269,2270,2272,2273,2276,2277,2279],{},"Because the CQRS tier already opened the active ",[505,2267,2268],{},"QueryBus.dispatch GetOrderQuery"," span, the ",[505,2271,2148],{}," span ",[1149,2274,2275],{},"nests under it","\nautomatically — same trace, no parent passed by hand. The span's ",[505,2278,511],{}," comes from its parent; the\nfacade is an ergonomic win, not a second attribution mechanism.",[1145,2281,2283,2308,2321],{"type":2282},"warning",[499,2284,2285,2293,2294,2296,2297,2299,2300,2303,2304,2307],{},[1149,2286,2287,2288,2290,2291,1036],{},"Injecting ",[505,2289,1884],{}," requires ",[505,2292,1130],{}," The token is satisfied only by the provider ",[505,2295,1130],{},"\ncontributes, so a class that injects ",[505,2298,1884],{}," in an app without the plugin fails to compile —\n",[505,2301,2302],{},"no provider for 'Tracer'",", exactly like injecting ",[505,2305,2306],{},"CommandBus"," without the CQRS plugin.",[499,2309,2310,2311,2314,2315,2317,2318,2320],{},"A precompiled ",[1149,2312,2313],{},"library"," that injects ",[505,2316,1884],{}," declares this in its manifest, so importing it into an app that omits\n",[505,2319,1130],{}," is a clear build error — the boundary check reports the missing required plugin by name —\nrather than a confusing downstream failure.",[499,2322,2323,2324,2326,2327,2330],{},"If you need a tracer in code that must not depend on the\nplugin being on — a shared library, or instrumentation you leave in when tracing is compiled out — use the\nglobal ",[505,2325,1897],{}," ",[505,2328,2329],{},"trace.getTracer(...)"," instead: it no-ops safely when no provider is registered.",[517,2332,2334],{"id":2333},"what-you-get-the-spans","What you get — the spans",[499,2336,2337,2338,2340,2341,2344,2345,592],{},"Four dispatch tiers are instrumented, each span carrying ",[505,2339,511],{}," plus a ",[505,2342,2343],{},"messaging.*"," set and the message\ntype. The attribute names below are exactly what the plugin bakes into ",[505,2346,533],{},[2348,2349,2350,2370],"table",{},[2351,2352,2353],"thead",{},[2354,2355,2356,2361,2364,2367],"tr",{},[2357,2358,2360],"th",{"align":2359},"left","Tier",[2357,2362,2363],{"align":2359},"Span name",[2357,2365,2366],{"align":2359},"Span kind",[2357,2368,2369],{"align":2359},"Key attributes",[2371,2372,2373,2400,2425,2449,2472],"tbody",{},[2354,2374,2375,2379,2384,2389],{},[2376,2377,2378],"td",{"align":2359},"HTTP request",[2376,2380,2381],{"align":2359},[505,2382,2383],{},"\u003CMETHOD> \u003Cpath>",[2376,2385,2386],{"align":2359},[505,2387,2388],{},"SERVER",[2376,2390,2391,2394,2395,2394,2397],{"align":2359},[505,2392,2393],{},"http.request.method",", ",[505,2396,511],{},[505,2398,2399],{},"heximon.request.id",[2354,2401,2402,2405,2410,2414],{},[2376,2403,2404],{"align":2359},"CQRS command",[2376,2406,2407],{"align":2359},[505,2408,2409],{},"CommandBus.dispatch \u003CCommand>",[2376,2411,2412],{"align":2359},[505,2413,636],{},[2376,2415,2416,2394,2419,2394,2421,2394,2423],{"align":2359},[505,2417,2418],{},"messaging.system: \"heximon.cqrs\"",[505,2420,705],{},[505,2422,511],{},[505,2424,746],{},[2354,2426,2427,2430,2435,2439],{},[2376,2428,2429],{"align":2359},"CQRS query",[2376,2431,2432],{"align":2359},[505,2433,2434],{},"QueryBus.dispatch \u003CQuery>",[2376,2436,2437],{"align":2359},[505,2438,636],{},[2376,2440,2441,2394,2443,2394,2445,2394,2447],{"align":2359},[505,2442,2418],{},[505,2444,705],{},[505,2446,511],{},[505,2448,746],{},[2354,2450,2451,2454,2459,2463],{},[2376,2452,2453],{"align":2359},"Serial event",[2376,2455,2456],{"align":2359},[505,2457,2458],{},"EventBus.emit \u003CEvent>",[2376,2460,2461],{"align":2359},[505,2462,636],{},[2376,2464,2465,2394,2468,2394,2470],{"align":2359},[505,2466,2467],{},"messaging.system: \"heximon.events\"",[505,2469,705],{},[505,2471,511],{},[2354,2473,2474,2477,2482,2487],{},[2376,2475,2476],{"align":2359},"Queue channel",[2376,2478,2479],{"align":2359},[505,2480,2481],{},"queue.consume \u003Cchannel>",[2376,2483,2484],{"align":2359},[505,2485,2486],{},"CONSUMER",[2376,2488,2489,2394,2492,2394,2495],{"align":2359},[505,2490,2491],{},"messaging.system: \"heximon.queue\"",[505,2493,2494],{},"messaging.destination.name",[505,2496,511],{},[499,2498,2499,2500,2503,2504,2506],{},"The HTTP server span is produced by a ",[505,2501,2502],{},"RouteDispatcher.configure({ onRequestStart, onRequestEnd })"," call in the\ngenerated wiring, reading ",[505,2505,511],{}," from the route descriptor:",[536,2508,2510],{"className":538,"code":2509,"filename":533,"language":540,"meta":541,"style":541},"const span = httpTracer.startSpan(\n  `${request.method} ${descriptor.path ?? \"\"}`,\n  {\n    kind: SpanKind.SERVER,\n    attributes: {\n      \"http.request.method\": request.method,\n      \"heximon.module\": descriptor.moduleName ?? \"\",\n      \"heximon.request.id\": requestId,\n    },\n  },\n  parentContext,\n);\n",[505,2511,2512,2530,2563,2568,2584,2593,2612,2637,2652,2657,2661,2668],{"__ignoreMap":541},[545,2513,2514,2516,2518,2520,2523,2525,2528],{"class":547,"line":548},[545,2515,565],{"class":564},[545,2517,2272],{"class":568},[545,2519,573],{"class":572},[545,2521,2522],{"class":568}," httpTracer",[545,2524,1036],{"class":572},[545,2526,2527],{"class":961},"startSpan",[545,2529,1621],{"class":568},[545,2531,2532,2535,2537,2539,2542,2544,2547,2550,2552,2555,2558,2561],{"class":547,"line":555},[545,2533,2534],{"class":572},"  `${",[545,2536,1245],{"class":568},[545,2538,1036],{"class":572},[545,2540,2541],{"class":568},"method",[545,2543,1120],{"class":572},[545,2545,2546],{"class":572}," ${",[545,2548,2549],{"class":568},"descriptor",[545,2551,1036],{"class":572},[545,2553,2554],{"class":568},"path ",[545,2556,2557],{"class":572},"??",[545,2559,2560],{"class":572}," \"\"}`",[545,2562,619],{"class":572},[545,2564,2565],{"class":547,"line":561},[545,2566,2567],{"class":572},"  {\n",[545,2569,2570,2573,2575,2578,2580,2582],{"class":547,"line":579},[545,2571,2572],{"class":585},"    kind",[545,2574,592],{"class":572},[545,2576,2577],{"class":568}," SpanKind",[545,2579,1036],{"class":572},[545,2581,2388],{"class":568},[545,2583,619],{"class":572},[545,2585,2586,2589,2591],{"class":547,"line":597},[545,2587,2588],{"class":585},"    attributes",[545,2590,592],{"class":572},[545,2592,576],{"class":572},[545,2594,2595,2597,2599,2601,2603,2606,2608,2610],{"class":547,"line":622},[545,2596,660],{"class":572},[545,2598,2393],{"class":585},[545,2600,589],{"class":572},[545,2602,592],{"class":572},[545,2604,2605],{"class":568}," request",[545,2607,1036],{"class":572},[545,2609,2541],{"class":568},[545,2611,619],{"class":572},[545,2613,2614,2616,2618,2620,2622,2625,2627,2630,2632,2635],{"class":547,"line":643},[545,2615,660],{"class":572},[545,2617,511],{"class":585},[545,2619,589],{"class":572},[545,2621,592],{"class":572},[545,2623,2624],{"class":568}," descriptor",[545,2626,1036],{"class":572},[545,2628,2629],{"class":568},"moduleName ",[545,2631,2557],{"class":572},[545,2633,2634],{"class":572}," \"\"",[545,2636,619],{"class":572},[545,2638,2639,2641,2643,2645,2647,2650],{"class":547,"line":657},[545,2640,660],{"class":572},[545,2642,2399],{"class":585},[545,2644,589],{"class":572},[545,2646,592],{"class":572},[545,2648,2649],{"class":568}," requestId",[545,2651,619],{"class":572},[545,2653,2654],{"class":547,"line":679},[545,2655,2656],{"class":572},"    },\n",[545,2658,2659],{"class":547,"line":700},[545,2660,1115],{"class":572},[545,2662,2663,2666],{"class":547,"line":721},[545,2664,2665],{"class":568},"  parentContext",[545,2667,619],{"class":572},[545,2669,2670,2672],{"class":547,"line":741},[545,2671,1123],{"class":568},[545,2673,857],{"class":572},[499,2675,2676,2677,2680,2681,2684,2685,2688],{},"Each command\u002Fquery\u002Fevent\u002Fqueue span is started by a per-key ",[505,2678,2679],{},"OtelInterceptor"," the plugin splices into that tier's\ndispatch bus steps. The interceptor extracts any incoming W3C ",[505,2682,2683],{},"traceparent"," \u002F ",[505,2686,2687],{},"tracestate"," from the message before\nstarting its child span, so cross-process and cross-tier traces stay connected on one trace id.",[517,2690,2692,2693],{"id":2691},"configuration-otelconfig","Configuration — ",[505,2694,2695],{},"OtelConfig",[499,2697,2698,2699,2701,2702,2704,2705,2707],{},"Tracing is configured by the top-level ",[505,2700,796],{}," key, not a constructor argument; every field is optional, so\n",[505,2703,806],{}," is always valid and an omitted ",[505,2706,796],{}," key bakes the defaults. The same shape applies to both\nthe Node and Workers providers:",[2348,2709,2710,2723],{},[2351,2711,2712],{},[2354,2713,2714,2717,2720],{},[2357,2715,2716],{"align":2359},"Field",[2357,2718,2719],{"align":2359},"Type",[2357,2721,2722],{"align":2359},"Description",[2371,2724,2725,2754,2783,2811,2834],{},[2354,2726,2727,2732,2737],{},[2376,2728,2729],{"align":2359},[505,2730,2731],{},"endpoint",[2376,2733,2734],{"align":2359},[505,2735,2736],{},"string",[2376,2738,2739,2740,2743,2744,2746,2747,2749,2750,2753],{"align":2359},"The OTLP collector endpoint URL. ",[1149,2741,2742],{},"Tracing is opt-in at build time — omit it and the plugin emits LEAN wiring",": no OpenTelemetry SDK is imported or bundled (you declare none of its deps and pay no bundle weight or boot cost) and no auto-spans are baked; the injectable ",[505,2745,1884],{}," stays available as a no-op, so dispatch is byte-identical to a no-",[505,2748,1130],{}," app. Set it — even to the local collector default (",[505,2751,2752],{},"http:\u002F\u002Flocalhost:4318",") — to enable tracing + bake the full provider wiring.",[2354,2755,2756,2761,2766],{},[2376,2757,2758],{"align":2359},[505,2759,2760],{},"protocol",[2376,2762,2763],{"align":2359},[505,2764,2765],{},"\"http\" | \"proto\" | \"grpc\"",[2376,2767,2768,2769,2772,2773,2776,2777,2780,2781,1036],{"align":2359},"OTLP transport: ",[505,2770,2771],{},"\"http\""," (OTLP\u002FHTTP JSON), ",[505,2774,2775],{},"\"proto\""," (OTLP\u002FHTTP Protobuf), ",[505,2778,2779],{},"\"grpc\""," (Node-only native binding). Defaults to ",[505,2782,2771],{},[2354,2784,2785,2790,2795],{},[2376,2786,2787],{"align":2359},[505,2788,2789],{},"resourceAttributes",[2376,2791,2792],{"align":2359},[505,2793,2794],{},"Record\u003Cstring, string>",[2376,2796,2797,2798,2801,2802,2394,2804,2394,2807,2810],{"align":2359},"Static ",[505,2799,2800],{},"Resource"," attributes merged at provider boot — ",[505,2803,1076],{},[505,2805,2806],{},"service.version",[505,2808,2809],{},"cloud.region",". Baked as compile-time literals, so they must be known at build time.",[2354,2812,2813,2818,2823],{},[2376,2814,2815],{"align":2359},[505,2816,2817],{},"samplerRatio",[2376,2819,2820],{"align":2359},[505,2821,2822],{},"number",[2376,2824,2825,2826,2829,2830,2833],{"align":2359},"Head-sampling ratio for root spans, ",[505,2827,2828],{},"0..1",". Applied via ",[505,2831,2832],{},"ParentBasedSampler({ root: TraceIdRatioBasedSampler(ratio) })",": a root span is kept with this probability, a child follows its parent. Omitted ⇒ keep every root span.",[2354,2835,2836,2841,2846],{},[2376,2837,2838],{"align":2359},[505,2839,2840],{},"batchOptions",[2376,2842,2843],{"align":2359},[505,2844,2845],{},"BatchOptions",[2376,2847,2848,2851,2852,2394,2855,2394,2858,2394,2861,1036],{"align":2359},[505,2849,2850],{},"BatchSpanProcessor"," tuning for the Node provider: ",[505,2853,2854],{},"maxQueueSize",[505,2856,2857],{},"maxExportBatchSize",[505,2859,2860],{},"scheduledDelayMillis",[505,2862,2863],{},"exportTimeoutMillis",[499,2865,2866,2869,2870,2873,2874,2876,2877,2879,2880,2883],{},[505,2867,2868],{},"service.name"," is resolved from your ",[505,2871,2872],{},"CoreConfig"," at runtime and does not need to be repeated in\n",[505,2875,2789],{},". ",[505,2878,2817],{}," is a plain numeric knob rather than a ",[505,2881,2882],{},"Sampler"," instance because the value is\nbaked as a compile-time literal into the generated wiring — a function or object sampler cannot be serialized into\nsource, so the provider constructs the sampler from this ratio.",[499,2885,2886,2889,2890,2893],{},[505,2887,2888],{},"batchOptions.exportTimeoutMillis"," is worth setting in development: it bounds how long the shutdown flush waits for\na span export to settle. With no collector reachable, a small value (the example uses ",[505,2891,2892],{},"300",") makes the export fail\nfast rather than stalling on the exporter's default 30 s retry budget, so a graceful restart is not delayed.",[499,2895,2896],{},"The flush failure is caught and logged on shutdown, never surfacing as a crash — the app needs no running collector to\nshut down cleanly.",[517,2898,2900],{"id":2899},"node-vs-edge-the-build-target-picks-the-tracer-leg","Node vs edge — the build target picks the tracer leg",[499,2902,2903,2904,2907,2908,2911,2912,2915,2916],{},"The OTel SDK ships two very different runtimes, and shipping the wrong one to the edge is expensive. Which leg\nthe plugin bakes is decided by the compiler's ",[1149,2905,2906],{},"build target"," — the ",[505,2909,2910],{},"targetClass"," of the deploy strategy on\n",[505,2913,2914],{},"heximon.platform"," — a single axis that captures the one difference codegen cares about: ",[1149,2917,2918],{},"flush at process\nshutdown, or flush per request.",[2348,2920,2921,2939],{},[2351,2922,2923],{},[2354,2924,2925,2930,2933,2936],{},[2357,2926,2927],{"align":2359},[505,2928,2929],{},"target",[2357,2931,2932],{"align":2359},"Tracer leg",[2357,2934,2935],{"align":2359},"Span processor",[2357,2937,2938],{"align":2359},"Flush",[2371,2940,2941,2959],{},[2354,2942,2943,2949,2952,2956],{},[2376,2944,2945,2948],{"align":2359},[505,2946,2947],{},"\"node\""," (default)",[2376,2950,2951],{"align":2359},"the Node SDK",[2376,2953,2954],{"align":2359},[505,2955,2850],{},[2376,2957,2958],{"align":2359},"drained at graceful shutdown",[2354,2960,2961,2966,2969,2974],{},[2376,2962,2963],{"align":2359},[505,2964,2965],{},"\"edge\"",[2376,2967,2968],{"align":2359},"the lean Workers leg",[2376,2970,2971],{"align":2359},[505,2972,2973],{},"SimpleSpanProcessor",[2376,2975,2976,2977],{"align":2359},"drained per request via the platform ",[505,2978,2979],{},"waitUntil",[499,2981,2982,2983,2986,2987,2394,2990,2993,2994,2997,2998,3001,3002,1036],{},"You usually don't pick the leg by hand — it is the runtime-lifetime class of your ",[1149,2984,2985],{},"deploy strategy",", and a\ndeploy host derives that from its preset. The Nitro module maps any ",[505,2988,2989],{},"cloudflare-*",[505,2991,2992],{},"*-edge",", or ",[505,2995,2996],{},"deno-deploy","\npreset to the edge class and every node\u002Fnode-compatible preset to node, for both ",[505,2999,3000],{},"nitro build"," and ",[505,3003,3004],{},"nitro dev",[499,3006,3007,3008,3010,3011,3014,3015,592],{},"On the host-independent ",[505,3009,852],{}," path, an edge-class strategy (e.g. ",[505,3012,3013],{},"CloudflareWorkersStrategy",") selects\nthe Workers leg — set it on ",[505,3016,821],{},[536,3018,3020],{"className":825,"code":3019,"language":827,"meta":541,"style":541},"\u002F\u002F heximon.config.ts\nimport { defineHeximonConfig } from \"@heximon\u002Fbuild\";\nimport { CloudflareWorkersStrategy } from \"@heximon\u002Fcloudflare\";\nimport { OtelPlugin } from \"@heximon\u002Fotel\u002Fcompiler\";\n\nexport default defineHeximonConfig({\n  platform: new CloudflareWorkersStrategy(), \u002F\u002F an edge-class strategy → the Workers tracer leg\n  plugins: [new OtelPlugin()],\n  otel: { endpoint: \"https:\u002F\u002Fotlp.example.com\u002Fv1\u002Ftraces\" },\n});\n",[505,3021,3022,3027,3047,3069,3089,3093,3105,3123,3139,3161],{"__ignoreMap":541},[545,3023,3024],{"class":547,"line":548},[545,3025,3026],{"class":551},"\u002F\u002F heximon.config.ts\n",[545,3028,3029,3031,3033,3035,3037,3039,3041,3043,3045],{"class":547,"line":555},[545,3030,835],{"class":834},[545,3032,838],{"class":572},[545,3034,841],{"class":568},[545,3036,844],{"class":572},[545,3038,847],{"class":834},[545,3040,610],{"class":572},[545,3042,852],{"class":613},[545,3044,589],{"class":572},[545,3046,857],{"class":572},[545,3048,3049,3051,3053,3056,3058,3060,3062,3065,3067],{"class":547,"line":561},[545,3050,835],{"class":834},[545,3052,838],{"class":572},[545,3054,3055],{"class":568}," CloudflareWorkersStrategy",[545,3057,844],{"class":572},[545,3059,847],{"class":834},[545,3061,610],{"class":572},[545,3063,3064],{"class":613},"@heximon\u002Fcloudflare",[545,3066,589],{"class":572},[545,3068,857],{"class":572},[545,3070,3071,3073,3075,3077,3079,3081,3083,3085,3087],{"class":547,"line":579},[545,3072,835],{"class":834},[545,3074,838],{"class":572},[545,3076,932],{"class":568},[545,3078,844],{"class":572},[545,3080,847],{"class":834},[545,3082,610],{"class":572},[545,3084,817],{"class":613},[545,3086,589],{"class":572},[545,3088,857],{"class":572},[545,3090,3091],{"class":547,"line":597},[545,3092,950],{"emptyLinePlaceholder":949},[545,3094,3095,3097,3099,3101,3103],{"class":547,"line":622},[545,3096,955],{"class":834},[545,3098,958],{"class":834},[545,3100,841],{"class":961},[545,3102,964],{"class":568},[545,3104,967],{"class":572},[545,3106,3107,3110,3112,3114,3116,3118,3120],{"class":547,"line":643},[545,3108,3109],{"class":585},"  platform",[545,3111,592],{"class":572},[545,3113,991],{"class":572},[545,3115,3055],{"class":961},[545,3117,985],{"class":568},[545,3119,988],{"class":572},[545,3121,3122],{"class":551}," \u002F\u002F an edge-class strategy → the Workers tracer leg\n",[545,3124,3125,3127,3129,3131,3133,3135,3137],{"class":547,"line":657},[545,3126,972],{"class":585},[545,3128,592],{"class":572},[545,3130,977],{"class":568},[545,3132,980],{"class":572},[545,3134,932],{"class":961},[545,3136,1012],{"class":568},[545,3138,619],{"class":572},[545,3140,3141,3143,3145,3147,3150,3152,3154,3157,3159],{"class":547,"line":679},[545,3142,1019],{"class":585},[545,3144,592],{"class":572},[545,3146,838],{"class":572},[545,3148,3149],{"class":585}," endpoint",[545,3151,592],{"class":572},[545,3153,610],{"class":572},[545,3155,3156],{"class":613},"https:\u002F\u002Fotlp.example.com\u002Fv1\u002Ftraces",[545,3158,589],{"class":572},[545,3160,1090],{"class":572},[545,3162,3163,3165,3167],{"class":547,"line":700},[545,3164,1120],{"class":572},[545,3166,1123],{"class":568},[545,3168,857],{"class":572},[499,3170,3171,3172,3174,3175,3177,3178,3181],{},"On ",[505,3173,2965],{},", the generated wiring builds the span ",[505,3176,2800],{}," in the factory, constructs the per-isolate tracer\nonce at boot, and — inside the same HTTP server-span hook — hands the span flush to the kernel's\n",[505,3179,3180],{},"context.waitUntil"," after the span ends.",[499,3183,3184,3185,3187,3188,3191,3192,3195],{},"The HTTP request frame carries the platform ",[505,3186,2979],{}," sink (the HTTP layer threads it off the runtime's\n",[505,3189,3190],{},"request.waitUntil","), so the flush is forwarded to ",[505,3193,3194],{},"ctx.waitUntil",": exporting never blocks the response and the\nisolate stays alive long enough to drain.",[499,3197,3198,3199,3001,3201,3203,3204,3206],{},"The edge bundle is far leaner: a representative full app's OTLP\u002FHTTP edge bundle is ~77 KB gzip against ~234 KB\ngzip for the Node SDK leg. The ",[505,3200,2817],{},[505,3202,2840],{}," knobs above are Node-leg tuning; the edge leg's\n",[505,3205,2973],{}," ignores them.",[517,3208,3210],{"id":3209},"real-coverage-limits","Real coverage limits",[499,3212,3213,3215],{},[505,3214,511],{}," attribution covers the four tiers above. Three dispatch paths are deliberately out of scope —\nnot from oversight, but because no interceptor seam reaches them, and a wrong attribution would be worse than a\nmissing one:",[3217,3218,3219,3229,3242],"ul",{},[3220,3221,3222,2326,3225,3228],"li",{},[1149,3223,3224],{},"Parallel notification handlers are not traced.",[505,3226,3227],{},"NotificationHandler"," (parallel-absorb) bypasses the\ninterceptor chain entirely, so no span is produced for it.",[3220,3230,3231,2326,3234,3237,3238,3241],{},[1149,3232,3233],{},"String-tier events are not traced.",[505,3235,3236],{},"EventBus.emitStringAsync"," bypasses the shared dispatch substrate the\ninterceptor splices into, so string-keyed events are untraced. Use class-tier events (the ",[505,3239,3240],{},"extends EventHandler\u003CEvent>"," form) for tracing.",[3220,3243,3244,3247,3248,3250],{},[1149,3245,3246],{},"A multi-module event attributes to no single module."," Serial event dispatch is wrapped per handler, not per\nevent: an event fanned out to handlers in several modules produces one span per handler invocation, each\nattributed to its own module. When the owning module is ambiguous, ",[505,3249,511],{}," is omitted rather than set\nto a wrong value — a missing attribute doesn't assert something false; a wrong one corrupts your per-module rollups.",[499,3252,3253,3254,3256,3257,3259,3260,3262,3263,1036],{},"Both legs are production-ready and selected by the build target (above): ",[505,3255,2947],{}," bakes the batch-backed Node\nSDK with a shutdown flush, ",[505,3258,2965],{}," bakes the lean Workers leg with a per-request ",[505,3261,3194],{}," flush. The\nper-request edge flush rides the HTTP request lifecycle; a non-HTTP edge entrypoint (queue\u002Fcron\u002FDurable Object\nRPC) flushes through the host's own ",[505,3264,3265],{},"executionContext.waitUntil",[517,3267,3269],{"id":3268},"see-also","See also",[3217,3271,3272,3290,3300,3309],{},[3220,3273,3274,3283,3284,3286,3287,3289],{},[3275,3276,3280],"a",{"href":3277,"rel":3278},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fgap\u002Fedge-platforms\u002Fotel-node",[3279],"nofollow",[1149,3281,3282],{},"OpenTelemetry Tracing (Node)","\n— a multi-tier orders app where one ",[505,3285,1872],{}," crosses the HTTP, CQRS command, and serial event spans, all\nattributed to ",[505,3288,1876],{},", plus an in-process e2e test that proves the app survives a collector that is\ndown (the flush fails, the lifecycle catches it, dispatch is unchanged).",[3220,3291,3292,2907,3294,2684,3296,3299],{},[3275,3293,233],{"href":234},[505,3295,2306],{},[505,3297,3298],{},"QueryBus"," dispatch the command and query spans wrap.",[3220,3301,3302,3304,3305,3308],{},[3275,3303,146],{"href":147}," — the serial ",[505,3306,3307],{},"EventHandler"," tier the event spans wrap.",[3220,3310,3311,3314,3315,3317],{},[3275,3312,3313],{"href":409},"Packages overview"," — where ",[505,3316,507],{}," sits in the stack.",[3319,3320,3321],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":541,"searchDepth":555,"depth":555,"links":3323},[3324,3325,3327,3328,3330,3331,3333,3334,3335],{"id":519,"depth":555,"text":520},{"id":792,"depth":555,"text":3326},"Add the plugin and set the otel key — the only step",{"id":1161,"depth":555,"text":1162},{"id":1880,"depth":555,"text":3329},"Adding your own spans — inject Tracer, don't import the SDK",{"id":2333,"depth":555,"text":2334},{"id":2691,"depth":555,"text":3332},"Configuration — OtelConfig",{"id":2899,"depth":555,"text":2900},{"id":3209,"depth":555,"text":3210},{"id":3268,"depth":555,"text":3269},"Compile-time, module-attributed OpenTelemetry tracing with OtelPlugin — heximon.module baked onto every HTTP \u002F CommandBus \u002F QueryBus \u002F EventBus span, OTLP export, samplerRatio, batchOptions.","md",null,{},{"icon":197},{"title":194,"description":3336},"vvn4FtlXzUwSvki47K48XiY8rve-Oje1CixLIlxwLJg",[3344,3346],{"title":189,"path":190,"stem":191,"description":3345,"icon":192,"children":-1},"Body-size guard (content-length, 413 RFC-9457), SecurityHeaders (nosniff\u002FDENY\u002Fno-referrer\u002FHSTS), RateLimitStore port, MemoryRateLimitStore, RateLimitMiddleware, @heximon\u002Fhttp\u002Fsecurity, bearer-only CSRF posture.",{"title":199,"path":200,"stem":201,"description":3347,"icon":202,"children":-1},"Generate an OpenAPI 3.1 document from your Contract route tables at runtime with OpenApiGenerator, register security schemes manually with the SecurityScheme factory, and serve Scalar or Swagger UI inline.",1783300761903]