[{"data":1,"prerenderedAt":1265},["ShallowReactive",2],{"navigation_docs_en":3,"-en-observability-sentry":342,"-en-observability-sentry-surround":1260},[4,45,61,96,132,166,196,217,241,265],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Getting Started","i-lucide-rocket","\u002Fen\u002Fgetting-started","en\u002F1.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fgetting-started\u002Fintroduction","en\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Coming from Laravel","\u002Fen\u002Fgetting-started\u002Fcoming-from-laravel","en\u002F1.getting-started\u002F2.coming-from-laravel","i-lucide-arrow-right-left",{"title":21,"path":22,"stem":23,"icon":19},"Coming from Symfony","\u002Fen\u002Fgetting-started\u002Fcoming-from-symfony","en\u002F1.getting-started\u002F3.coming-from-symfony",{"title":25,"path":26,"stem":27,"icon":28},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F1.getting-started\u002F4.installation","i-lucide-download",{"title":30,"path":31,"stem":32,"icon":33},"Your first module","\u002Fen\u002Fgetting-started\u002Ffirst-module","en\u002F1.getting-started\u002F5.first-module","i-lucide-package-plus",{"title":35,"path":36,"stem":37,"icon":38},"Project structure","\u002Fen\u002Fgetting-started\u002Fproject-structure","en\u002F1.getting-started\u002F6.project-structure","i-lucide-folder-tree",{"title":40,"path":41,"stem":42,"icon":43},"The shop sample application","\u002Fen\u002Fgetting-started\u002Fsample-app","en\u002F1.getting-started\u002F7.sample-app","i-lucide-shopping-cart",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F10.reference",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F10.reference\u002F1.configuration","i-lucide-settings",{"title":57,"path":58,"stem":59,"icon":60},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F10.reference\u002F2.dependencies","i-lucide-package",{"title":62,"icon":63,"path":64,"stem":65,"children":66,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F2.concepts",[67,72,77,82,86,91],{"title":68,"path":69,"stem":70,"icon":71},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F2.concepts\u002F1.architecture","i-lucide-layers",{"title":73,"path":74,"stem":75,"icon":76},"Application lifecycle","\u002Fen\u002Fconcepts\u002Fapplication-lifecycle","en\u002F2.concepts\u002F2.application-lifecycle","i-lucide-power",{"title":78,"path":79,"stem":80,"icon":81},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F2.concepts\u002F3.error-model","i-lucide-shield-alert",{"title":52,"path":83,"stem":84,"icon":85},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F2.concepts\u002F4.configuration","i-lucide-settings-2",{"title":87,"path":88,"stem":89,"icon":90},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F2.concepts\u002F5.codegen-pipeline","i-lucide-file-json",{"title":92,"path":93,"stem":94,"icon":95},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F2.concepts\u002F6.design-patterns","i-lucide-puzzle",{"title":97,"icon":98,"path":99,"stem":100,"children":101,"page":44},"HTTP & Routing","i-lucide-globe","\u002Fen\u002Fhttp","en\u002F3.http",[102,107,112,117,122,127],{"title":103,"path":104,"stem":105,"icon":106},"The server core","\u002Fen\u002Fhttp\u002Fserver","en\u002F3.http\u002F1.server","i-lucide-server",{"title":108,"path":109,"stem":110,"icon":111},"The Fiber engine","\u002Fen\u002Fhttp\u002Ffiber","en\u002F3.http\u002F2.fiber","i-lucide-zap",{"title":113,"path":114,"stem":115,"icon":116},"The chi engine","\u002Fen\u002Fhttp\u002Fchi","en\u002F3.http\u002F3.chi","i-lucide-route",{"title":118,"path":119,"stem":120,"icon":121},"Error responses","\u002Fen\u002Fhttp\u002Ferror-responses","en\u002F3.http\u002F4.error-responses","i-lucide-octagon-alert",{"title":123,"path":124,"stem":125,"icon":126},"Validation","\u002Fen\u002Fhttp\u002Fvalidation","en\u002F3.http\u002F5.validation","i-lucide-badge-check",{"title":128,"path":129,"stem":130,"icon":131},"Pagination","\u002Fen\u002Fhttp\u002Fpagination","en\u002F3.http\u002F6.pagination","i-lucide-list-ordered",{"title":133,"icon":134,"path":135,"stem":136,"children":137,"page":44},"Database","i-lucide-database","\u002Fen\u002Fdatabase","en\u002F4.database",[138,142,147,151,156,161],{"title":139,"path":140,"stem":141,"icon":134},"Overview","\u002Fen\u002Fdatabase\u002Foverview","en\u002F4.database\u002F1.overview",{"title":143,"path":144,"stem":145,"icon":146},"pgx","\u002Fen\u002Fdatabase\u002Fpgx","en\u002F4.database\u002F2.pgx","i-lucide-plug",{"title":148,"path":149,"stem":150,"icon":71},"bun","\u002Fen\u002Fdatabase\u002Fbun","en\u002F4.database\u002F3.bun",{"title":152,"path":153,"stem":154,"icon":155},"Transactions","\u002Fen\u002Fdatabase\u002Ftransactions","en\u002F4.database\u002F4.transactions","i-lucide-git-merge",{"title":157,"path":158,"stem":159,"icon":160},"Migrations","\u002Fen\u002Fdatabase\u002Fmigrations","en\u002F4.database\u002F5.migrations","i-lucide-file-stack",{"title":162,"path":163,"stem":164,"icon":165},"Seeders","\u002Fen\u002Fdatabase\u002Fseeding","en\u002F4.database\u002F6.seeding","i-lucide-sprout",{"title":167,"icon":168,"path":169,"stem":170,"children":171,"page":44},"Async & Background","i-lucide-workflow","\u002Fen\u002Fasync","en\u002F5.async",[172,176,181,186,191],{"title":173,"path":174,"stem":175,"icon":131},"Queue","\u002Fen\u002Fasync\u002Fqueue","en\u002F5.async\u002F1.queue",{"title":177,"path":178,"stem":179,"icon":180},"Events","\u002Fen\u002Fasync\u002Fevents","en\u002F5.async\u002F2.events","i-lucide-radio",{"title":182,"path":183,"stem":184,"icon":185},"Outbox","\u002Fen\u002Fasync\u002Foutbox","en\u002F5.async\u002F3.outbox","i-lucide-inbox",{"title":187,"path":188,"stem":189,"icon":190},"Scheduling","\u002Fen\u002Fasync\u002Fscheduler","en\u002F5.async\u002F4.scheduler","i-lucide-calendar-clock",{"title":192,"path":193,"stem":194,"icon":195},"Worker","\u002Fen\u002Fasync\u002Fworker","en\u002F5.async\u002F5.worker","i-lucide-cog",{"title":197,"icon":198,"path":199,"stem":200,"children":201,"page":44},"Security","i-lucide-shield-check","\u002Fen\u002Fsecurity","en\u002F6.security",[202,207,212],{"title":203,"path":204,"stem":205,"icon":206},"Authentication","\u002Fen\u002Fsecurity\u002Fauthentication","en\u002F6.security\u002F1.authentication","i-lucide-key-round",{"title":208,"path":209,"stem":210,"icon":211},"RBAC","\u002Fen\u002Fsecurity\u002Frbac","en\u002F6.security\u002F2.rbac","i-lucide-users",{"title":213,"path":214,"stem":215,"icon":216},"Policies","\u002Fen\u002Fsecurity\u002Fpolicies","en\u002F6.security\u002F3.policies","i-lucide-gavel",{"title":218,"icon":219,"path":220,"stem":221,"children":222,"page":44},"Observability","i-lucide-activity","\u002Fen\u002Fobservability","en\u002F7.observability",[223,226,231,236],{"title":139,"path":224,"stem":225,"icon":219},"\u002Fen\u002Fobservability\u002Foverview","en\u002F7.observability\u002F1.overview",{"title":227,"path":228,"stem":229,"icon":230},"Logging","\u002Fen\u002Fobservability\u002Flogging","en\u002F7.observability\u002F2.logging","i-lucide-scroll-text",{"title":232,"path":233,"stem":234,"icon":235},"OpenTelemetry","\u002Fen\u002Fobservability\u002Fopentelemetry","en\u002F7.observability\u002F3.opentelemetry","i-lucide-radar",{"title":237,"path":238,"stem":239,"icon":240},"Sentry","\u002Fen\u002Fobservability\u002Fsentry","en\u002F7.observability\u002F4.sentry","i-lucide-bug",{"title":242,"icon":243,"path":244,"stem":245,"children":246,"page":44},"Storage & Mail","i-lucide-hard-drive","\u002Fen\u002Fstorage-mail","en\u002F8.storage-mail",[247,251,256,261],{"title":248,"path":249,"stem":250,"icon":243},"Storage","\u002Fen\u002Fstorage-mail\u002Fstorage","en\u002F8.storage-mail\u002F1.storage",{"title":252,"path":253,"stem":254,"icon":255},"Email","\u002Fen\u002Fstorage-mail\u002Fmail","en\u002F8.storage-mail\u002F2.mail","i-lucide-mail",{"title":257,"path":258,"stem":259,"icon":260},"Notifications","\u002Fen\u002Fstorage-mail\u002Fnotifications","en\u002F8.storage-mail\u002F3.notifications","i-lucide-bell",{"title":262,"path":263,"stem":264,"icon":180},"Realtime","\u002Fen\u002Fstorage-mail\u002Frealtime","en\u002F8.storage-mail\u002F4.realtime",{"title":266,"icon":267,"path":268,"stem":269,"children":270,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F9.cli",[271,274,279,284,289,294,299,303,308,313,318,323,328,333,337],{"title":139,"path":272,"stem":273,"icon":267},"\u002Fen\u002Fcli\u002Foverview","en\u002F9.cli\u002F1.overview",{"title":275,"path":276,"stem":277,"icon":278},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F9.cli\u002F10.add-db","i-lucide-database-zap",{"title":280,"path":281,"stem":282,"icon":283},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F9.cli\u002F11.add-compose","i-lucide-container",{"title":285,"path":286,"stem":287,"icon":288},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F9.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":290,"path":291,"stem":292,"icon":293},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F9.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":295,"path":296,"stem":297,"icon":298},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F9.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":300,"path":301,"stem":302,"icon":165},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F9.cli\u002F15.add-seeder",{"title":304,"path":305,"stem":306,"icon":307},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F9.cli\u002F2.new-project","i-lucide-folder-plus",{"title":309,"path":310,"stem":311,"icon":312},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F9.cli\u002F3.new-module","i-lucide-blocks",{"title":314,"path":315,"stem":316,"icon":317},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F9.cli\u002F4.add-surface","i-lucide-layers-2",{"title":319,"path":320,"stem":321,"icon":322},"add core","\u002Fen\u002Fcli\u002Fadd-core","en\u002F9.cli\u002F5.add-core","i-lucide-box",{"title":324,"path":325,"stem":326,"icon":327},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F9.cli\u002F6.add-handler","i-lucide-webhook",{"title":329,"path":330,"stem":331,"icon":332},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F9.cli\u002F7.new-migration","i-lucide-file-plus",{"title":334,"path":335,"stem":336,"icon":195},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F9.cli\u002F8.worker-generators",{"title":338,"path":339,"stem":340,"icon":341},"upgrade templates","\u002Fen\u002Fcli\u002Fupgrade-templates","en\u002F9.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"id":343,"title":237,"body":344,"description":1253,"extension":1254,"links":1255,"meta":1256,"navigation":1257,"path":238,"seo":1258,"stem":239,"__hash__":1259},"docs_en\u002Fen\u002F7.observability\u002F4.sentry.md",{"type":345,"value":346,"toc":1244},"minimark",[347,377,380,436,446,450,538,553,557,572,645,656,660,676,714,721,861,879,888,892,910,914,949,955,1186,1190,1208,1212,1231,1240],[348,349,350,351,355,356,364,365,369,370,373,374,376],"p",{},"Once a DSN is set, ",[352,353,354],"code",{},"sentryx"," turns on Sentry error reporting ",[357,358,359,360,363],"strong",{},"through ",[352,361,362],{},"slog"," and OpenTelemetry",". That is not a technical footnote, it is the point: since the ",[366,367,368],"a",{"href":119},"httperr"," handlers, the Fiber\u002Fchi panic recovery and the ",[366,371,372],{"href":193},"worker"," already log every 5xx and task failure through ",[352,375,362],{}," with a trace-carrying context, wiring in a single slog handler covers every entry point, and there is nothing Sentry-specific in your code.",[348,378,379],{},"Enabling it:",[381,382,387],"pre",{"className":383,"code":384,"language":385,"meta":386,"style":386},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","SENTRY_DSN=https:\u002F\u002F\u003Ckey>@\u003Corg>.ingest.sentry.io\u002F\u003Cproject>\n","sh","",[352,388,389],{"__ignoreMap":386},[390,391,394,398,402,406,409,412,415,418,420,423,425,428,430,433],"span",{"class":392,"line":393},"line",1,[390,395,397],{"class":396},"sTEyZ","SENTRY_DSN",[390,399,401],{"class":400},"sMK4o","=",[390,403,405],{"class":404},"sfazB","https:\u002F\u002F",[390,407,408],{"class":400},"\u003C",[390,410,411],{"class":404},"key",[390,413,414],{"class":400},">",[390,416,417],{"class":404},"@",[390,419,408],{"class":400},[390,421,422],{"class":404},"org",[390,424,414],{"class":400},[390,426,427],{"class":404},".ingest.sentry.io\u002F",[390,429,408],{"class":400},[390,431,432],{"class":404},"project",[390,434,435],{"class":400},">\n",[348,437,438,439,441,442,445],{},"That's it. Without ",[352,440,397],{}," the integration is ",[357,443,444],{},"completely off",": every hook is a no-op, and behavior is identical to a kit without Sentry.",[447,448,52],"h2",{"id":449},"configuration",[451,452,453,469],"table",{},[454,455,456],"thead",{},[457,458,459,463,466],"tr",{},[460,461,462],"th",{},"Variable",[460,464,465],{},"Default",[460,467,468],{},"Meaning",[470,471,472,485,505,524],"tbody",{},[457,473,474,479,482],{},[475,476,477],"td",{},[352,478,397],{},[475,480,481],{},"empty",[475,483,484],{},"project DSN; empty turns the integration fully off",[457,486,487,492,502],{},[475,488,489],{},[352,490,491],{},"SENTRY_ENVIRONMENT",[475,493,494,495,498,499],{},"dev → ",[352,496,497],{},"development",", else ",[352,500,501],{},"production",[475,503,504],{},"environment tag on every event",[457,506,507,512,517],{},[475,508,509],{},[352,510,511],{},"SENTRY_TRACES",[475,513,514],{},[352,515,516],{},"true",[475,518,519,520,523],{},"ship the kit's OTel spans to Sentry; set ",[352,521,522],{},"false"," when your collector forwards them instead",[457,525,526,531,535],{},[475,527,528],{},[352,529,530],{},"SENTRY_DEBUG",[475,532,533],{},[352,534,522],{},[475,536,537],{},"the Sentry SDK's own debug log to stderr",[348,539,540,541,544,545,548,549,552],{},"Every event carries a release of ",[352,542,543],{},"\u003Cservice>@\u003Cversion>"," (from ",[352,546,547],{},"OTEL_SERVICE_NAME"," \u002F ",[352,550,551],{},"OTEL_SERVICE_VERSION","), and Sentry's release tracking works with no extra setup.",[447,554,556],{"id":555},"on-top-of-otel-not-instead-of-it","On top of OTel, not instead of it",[348,558,559,561,562,567,568,571],{},[352,560,354],{}," brings no tracing of its own, no middleware mesh, no measurements: OTel stays the backbone, and Sentry attaches to it at three points. All three are wired by ",[366,563,564],{"href":224},[352,565,566],{},"telemetry.Setup","; you never call ",[352,569,570],{},"sentryx.Setup"," yourself:",[573,574,575,598,639],"ul",{},[576,577,578,581,582,585,586,589,590,593,594,597],"li",{},[357,579,580],{},"Spans → Sentry."," ",[352,583,584],{},"Handle.SpanExporter()"," is registered as an extra exporter on the ",[352,587,588],{},"otelx"," tracer provider (",[352,591,592],{},"otelx.WithSpanExporter","): the same spans go to your collector and to Sentry. An error thus links to the full trace waterfall: the HTTP span, every DB query with its timing, the queue tasks. Sampling stays OTel-governed (",[352,595,596],{},"OTEL_TRACES_SAMPLER","); there is no separate Sentry sample rate.",[576,599,600,581,603,606,607,610,611,616,617,619,620,623,624,623,627,630,631,634,635,638],{},[357,601,602],{},"Errors → Sentry.",[352,604,605],{},"Handle.SlogHandler()"," is one branch of the log fanout: every ",[352,608,609],{},"ERROR","-level record becomes a Sentry event. The record's first error-valued attr is the captured exception; an ",[366,612,613],{"href":79},[352,614,615],{},"errs"," error brings along the stack recorded at its point of origin, its code, public message and wrap chain (in the event's ",[352,618,615],{}," context). Lower-level records (",[352,621,622],{},"DEBUG","\u002F",[352,625,626],{},"INFO",[352,628,629],{},"WARN",") accumulate as ",[357,632,633],{},"breadcrumbs",", so the event shows the log trail that led to it, honoring ",[352,636,637],{},"LOG_LEVEL"," like any sink.",[576,640,641,644],{},[357,642,643],{},"Error ↔ trace linking."," The OTel integration stamps each event with the active trace\u002Fspan ID, so the error lands on the correct span in the waterfall.",[348,646,647,648,651,652,655],{},"Breadcrumb isolation is per request: at all three entry points (a Fiber middleware, a chi middleware, a worker task middleware) the chassis calls ",[352,649,650],{},"sentryx.WithRequestHub",", which puts a fresh cloned hub on the context, so one request's log lines never bleed into another request's event. On a context without such a hub (say, your own goroutine on ",[352,653,654],{},"context.Background()",") breadcrumbs are dropped rather than polluting the global hub.",[447,657,659],{"id":658},"one-error-one-issue-the-errs-code-as-fingerprint","One error = one issue: the errs code as fingerprint",[348,661,662,663,665,666,669,670,672,673,675],{},"Sentry titles and groups by the outermost exception's type. In Go that would be the type name, and since every level of an ",[352,664,615],{}," chain carries the same ",[352,667,668],{},"*errs.Error"," type, all your errors would merge into a single issue named ",[352,671,668],{},". So ",[352,674,354],{}," rewrites the event before sending:",[573,677,678,687,697],{},[576,679,680,686],{},[357,681,682,683,685],{},"The issue title becomes the error's ",[352,684,615],{}," code"," (or, absent a code, its outermost wrap message).",[576,688,689,692,693,696],{},[357,690,691],{},"The code is also the grouping fingerprint",": every occurrence of a ",[366,694,695],{"href":79},"defined error"," groups into one issue, no matter how many different code paths produced it.",[576,698,699,706,707,710,711,713],{},[357,700,701,702,705],{},"The secondary line becomes the ",[352,703,704],{},"Public"," message"," (when set): the issue list reads as ",[352,708,709],{},"code \u002F client-facing text",", with the full internal chain one click away in the event's ",[352,712,615],{}," context.",[348,715,716,717,720],{},"On the ",[366,718,719],{"href":41},"shop","'s canonical error, it looks like this:",[381,722,726],{"className":723,"code":724,"language":725,"meta":386,"style":386},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","var ErrOutOfStock = errs.Define(\"shop_out_of_stock\",\n    errs.Public(\"One or more items are out of stock.\"))\n\n\u002F\u002F repository:\nreturn ErrOutOfStock.New(\"inventory: decrement: insufficient stock\")\n\u002F\u002F service:\nreturn errs.Wrap(err, \"shop: place order\")\n","go",[352,727,728,762,784,791,798,825,831],{"__ignoreMap":386},[390,729,730,733,736,738,741,744,748,751,754,757,759],{"class":392,"line":393},[390,731,732],{"class":400},"var",[390,734,735],{"class":396}," ErrOutOfStock ",[390,737,401],{"class":400},[390,739,740],{"class":396}," errs",[390,742,743],{"class":400},".",[390,745,747],{"class":746},"s2Zo4","Define",[390,749,750],{"class":400},"(",[390,752,753],{"class":400},"\"",[390,755,756],{"class":404},"shop_out_of_stock",[390,758,753],{"class":400},[390,760,761],{"class":400},",\n",[390,763,765,768,770,772,774,776,779,781],{"class":392,"line":764},2,[390,766,767],{"class":396},"    errs",[390,769,743],{"class":400},[390,771,704],{"class":746},[390,773,750],{"class":400},[390,775,753],{"class":400},[390,777,778],{"class":404},"One or more items are out of stock.",[390,780,753],{"class":400},[390,782,783],{"class":400},"))\n",[390,785,787],{"class":392,"line":786},3,[390,788,790],{"emptyLinePlaceholder":789},true,"\n",[390,792,794],{"class":392,"line":793},4,[390,795,797],{"class":796},"sHwdD","\u002F\u002F repository:\n",[390,799,801,805,808,810,813,815,817,820,822],{"class":392,"line":800},5,[390,802,804],{"class":803},"s7zQu","return",[390,806,807],{"class":396}," ErrOutOfStock",[390,809,743],{"class":400},[390,811,812],{"class":746},"New",[390,814,750],{"class":400},[390,816,753],{"class":400},[390,818,819],{"class":404},"inventory: decrement: insufficient stock",[390,821,753],{"class":400},[390,823,824],{"class":400},")\n",[390,826,828],{"class":392,"line":827},6,[390,829,830],{"class":796},"\u002F\u002F service:\n",[390,832,834,836,838,840,843,845,848,851,854,857,859],{"class":392,"line":833},7,[390,835,804],{"class":803},[390,837,740],{"class":396},[390,839,743],{"class":400},[390,841,842],{"class":746},"Wrap",[390,844,750],{"class":400},[390,846,847],{"class":396},"err",[390,849,850],{"class":400},",",[390,852,853],{"class":400}," \"",[390,855,856],{"class":404},"shop: place order",[390,858,753],{"class":400},[390,860,824],{"class":400},[348,862,863,864,867,868,870,871,874,875,878],{},"However many orders fail, however the stack shifts along the way, in Sentry it is ",[357,865,866],{},"a single issue",": ",[352,869,756],{},", with the public message beneath it, and every event carrying the full stack, the wrap chain, the request's breadcrumbs and the trace link. And when the team decides that running out of stock is expected client behavior rather than an incident, add ",[352,872,873],{},"errs.Status(http.StatusConflict)"," to the definition: from then on it goes out as a 409, producing no ",[352,876,877],{},"request failed"," log line and no Sentry event, and the issue dies out on its own.",[880,881,882,883,887],"note",{},"Sentry's OTLP ingestion accepts traces but drops OTel span ",[884,885,886],"em",{},"events",": the lifecycle view is assembled from real spans (HTTP, DB, queue, S3) plus the breadcrumb trail. Source context in the Sentry UI comes from the GitHub\u002FSCM integration; Go binaries carry no source.",[447,889,891],{"id":890},"works-in-dev-mode-too-no-collector","Works in dev mode too: no collector",[348,893,894,895,898,899,902,903,905,906,909],{},"With ",[352,896,897],{},"OTEL_DEV_MODE=true",", OTel ",[366,900,901],{"href":233},"builds no exporters",", but if ",[352,904,397],{}," is set, the kit spins up a Sentry-only tracer provider, so you get the full trace and the error in Sentry ",[357,907,908],{},"locally, without any collector",". This is the cheapest way to see the \"follow the order\" trace live: dev mode plus the DSN of a dev Sentry project.",[447,911,913],{"id":912},"why-a-wrapper-the-exception-that-proves-the-rule","Why a wrapper: the exception that proves the rule",[348,915,916,917,920,921,923,924,927,928,931,932,934,935,937,938,941,942,945,946,743],{},"The kit's principle is ",[366,918,919],{"href":12},"centralize, don't abstract",", and ",[352,922,354],{}," is one of the three declared exceptions: it really does wrap sentry-go. The reason is ",[357,925,926],{},"omittability",". Sentry is an optional integration: it toggles via env, and since only the ",[352,929,930],{},"telemetry"," facade and the chassis import ",[352,933,354],{},", a non-chassis binary (a CLI, a migrator, anything using just ",[352,936,588],{}," or ",[352,939,940],{},"dbx",") ",[357,943,944],{},"never even links sentry-go",". If sentry-go types flowed through the kit's API, that guarantee would be gone. In daily work you don't call it anyway: your errors reach Sentry via ",[352,947,948],{},"return err",[348,950,951,952,954],{},"The API is still there when needed (it is what ",[352,953,930],{}," itself works through):",[381,956,958],{"className":723,"code":957,"language":725,"meta":386,"style":386},"func Setup(ctx context.Context, cfg Config, serviceName, serviceVersion string, dev bool) (*Handle, error)\n\nfunc (h *Handle) Enabled() bool\nfunc (h *Handle) SpanExporter() sdktrace.SpanExporter  \u002F\u002F nil when disabled \u002F SENTRY_TRACES=false\nfunc (h *Handle) SlogHandler() slog.Handler            \u002F\u002F nil when disabled\nfunc (h *Handle) Flush(ctx context.Context) error      \u002F\u002F drain the event transport\n\nfunc WithRequestHub(ctx context.Context) context.Context \u002F\u002F per-request hub, called by the chassis\n",[352,959,960,1029,1033,1059,1089,1119,1153,1157],{"__ignoreMap":386},[390,961,962,965,968,970,974,978,980,983,985,988,991,993,996,998,1001,1005,1007,1010,1013,1016,1019,1022,1024,1027],{"class":392,"line":393},[390,963,964],{"class":400},"func",[390,966,967],{"class":746}," Setup",[390,969,750],{"class":400},[390,971,973],{"class":972},"sHdIc","ctx",[390,975,977],{"class":976},"sBMFI"," context",[390,979,743],{"class":400},[390,981,982],{"class":976},"Context",[390,984,850],{"class":400},[390,986,987],{"class":972}," cfg",[390,989,990],{"class":976}," Config",[390,992,850],{"class":400},[390,994,995],{"class":972}," serviceName",[390,997,850],{"class":400},[390,999,1000],{"class":972}," serviceVersion",[390,1002,1004],{"class":1003},"spNyl"," string",[390,1006,850],{"class":400},[390,1008,1009],{"class":972}," dev",[390,1011,1012],{"class":1003}," bool",[390,1014,1015],{"class":400},")",[390,1017,1018],{"class":400}," (*",[390,1020,1021],{"class":976},"Handle",[390,1023,850],{"class":400},[390,1025,1026],{"class":1003}," error",[390,1028,824],{"class":400},[390,1030,1031],{"class":392,"line":764},[390,1032,790],{"emptyLinePlaceholder":789},[390,1034,1035,1037,1040,1043,1046,1048,1050,1053,1056],{"class":392,"line":786},[390,1036,964],{"class":400},[390,1038,1039],{"class":400}," (",[390,1041,1042],{"class":972},"h ",[390,1044,1045],{"class":400},"*",[390,1047,1021],{"class":976},[390,1049,1015],{"class":400},[390,1051,1052],{"class":746}," Enabled",[390,1054,1055],{"class":400},"()",[390,1057,1058],{"class":1003}," bool\n",[390,1060,1061,1063,1065,1067,1069,1071,1073,1076,1078,1081,1083,1086],{"class":392,"line":793},[390,1062,964],{"class":400},[390,1064,1039],{"class":400},[390,1066,1042],{"class":972},[390,1068,1045],{"class":400},[390,1070,1021],{"class":976},[390,1072,1015],{"class":400},[390,1074,1075],{"class":746}," SpanExporter",[390,1077,1055],{"class":400},[390,1079,1080],{"class":976}," sdktrace",[390,1082,743],{"class":400},[390,1084,1085],{"class":976},"SpanExporter",[390,1087,1088],{"class":796},"  \u002F\u002F nil when disabled \u002F SENTRY_TRACES=false\n",[390,1090,1091,1093,1095,1097,1099,1101,1103,1106,1108,1111,1113,1116],{"class":392,"line":800},[390,1092,964],{"class":400},[390,1094,1039],{"class":400},[390,1096,1042],{"class":972},[390,1098,1045],{"class":400},[390,1100,1021],{"class":976},[390,1102,1015],{"class":400},[390,1104,1105],{"class":746}," SlogHandler",[390,1107,1055],{"class":400},[390,1109,1110],{"class":976}," slog",[390,1112,743],{"class":400},[390,1114,1115],{"class":976},"Handler",[390,1117,1118],{"class":796},"            \u002F\u002F nil when disabled\n",[390,1120,1121,1123,1125,1127,1129,1131,1133,1136,1138,1140,1142,1144,1146,1148,1150],{"class":392,"line":827},[390,1122,964],{"class":400},[390,1124,1039],{"class":400},[390,1126,1042],{"class":972},[390,1128,1045],{"class":400},[390,1130,1021],{"class":976},[390,1132,1015],{"class":400},[390,1134,1135],{"class":746}," Flush",[390,1137,750],{"class":400},[390,1139,973],{"class":972},[390,1141,977],{"class":976},[390,1143,743],{"class":400},[390,1145,982],{"class":976},[390,1147,1015],{"class":400},[390,1149,1026],{"class":1003},[390,1151,1152],{"class":796},"      \u002F\u002F drain the event transport\n",[390,1154,1155],{"class":392,"line":833},[390,1156,790],{"emptyLinePlaceholder":789},[390,1158,1160,1162,1165,1167,1169,1171,1173,1175,1177,1179,1181,1183],{"class":392,"line":1159},8,[390,1161,964],{"class":400},[390,1163,1164],{"class":746}," WithRequestHub",[390,1166,750],{"class":400},[390,1168,973],{"class":972},[390,1170,977],{"class":976},[390,1172,743],{"class":400},[390,1174,982],{"class":976},[390,1176,1015],{"class":400},[390,1178,977],{"class":976},[390,1180,743],{"class":400},[390,1182,982],{"class":976},[390,1184,1185],{"class":796}," \u002F\u002F per-request hub, called by the chassis\n",[447,1187,1189],{"id":1188},"flush-at-the-very-end","Flush at the very end",[348,1191,1192,1193,867,1196,1199,1200,1203,1204,1207],{},"Sentry's event transport is asynchronous: capturing never blocks a request. Closing it down is handled by the ",[366,1194,1195],{"href":224},"telemetry shutdown",[352,1197,1198],{},"Flush"," runs ",[357,1201,1202],{},"after"," the OTel providers stop, last in the ",[366,1205,1206],{"href":74},"lifecycle",", so errors produced during shutdown still ship before the process exits.",[447,1209,1211],{"id":1210},"patterns-used","Patterns used",[348,1213,1214,1216,1217,1221,1222,1225,1226,1230],{},[352,1215,354],{}," is one of the kit's three stated exceptions to hiding a dependency behind an interface; see ",[366,1218,1220],{"href":1219},"\u002Fen\u002Fconcepts\u002Fdesign-patterns#architectural-principles","Design patterns: Architectural principles",". Its plug-in via ",[352,1223,1224],{},"WithSpanExporter"," is a concrete example of the nil-tolerant ",[366,1227,1229],{"href":1228},"\u002Fen\u002Fconcepts\u002Fdesign-patterns#functional-options","functional options"," variant.",[348,1232,1233,1234,743],{},"Sentry's official Go documentation: ",[366,1235,1239],{"href":1236,"rel":1237},"https:\u002F\u002Fdocs.sentry.io\u002Fplatforms\u002Fgo\u002F",[1238],"nofollow","docs.sentry.io\u002Fplatforms\u002Fgo",[1241,1242,1243],"style",{},"html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .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 .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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":386,"searchDepth":764,"depth":764,"links":1245},[1246,1247,1248,1249,1250,1251,1252],{"id":449,"depth":764,"text":52},{"id":555,"depth":764,"text":556},{"id":658,"depth":764,"text":659},{"id":890,"depth":764,"text":891},{"id":912,"depth":764,"text":913},{"id":1188,"depth":764,"text":1189},{"id":1210,"depth":764,"text":1211},"Env-gated error reporting on top of OTel: with errs-code issue grouping and full trace linking.","md",null,{},{"icon":240},{"title":237,"description":1253},"NVdT2Fqx0HG_TBx38xjfGsmDmhtEQbSQxZN4MlC2FIE",[1261,1263],{"title":232,"path":233,"stem":234,"description":1262,"icon":235,"children":-1},"Traces, metrics and logs in one call, HTTP, database, queue and S3 instrumentation, configured via standard OTEL_* variables.",{"title":248,"path":249,"stem":250,"description":1264,"icon":243,"children":-1},"Object storage through the storage.Store interface, with an S3-compatible implementation, without importing the AWS SDK.",1784668709991]