[{"data":1,"prerenderedAt":1791},["ShallowReactive",2],{"docs-nav:en":3,"docs:\u002Fdocs\u002Finfra\u002Fobservability":186},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","\u002Fdocs","docs",[9,12,16,20,24,28,50,75,120,145],{"title":10,"path":6,"stem":11},"What is Fougere","docs\u002Findex",{"title":13,"path":14,"stem":15},"Getting started","\u002Fdocs\u002Fgetting-started","docs\u002F01.getting-started",{"title":17,"path":18,"stem":19},"An app you already have","\u002Fdocs\u002Fexisting-app","docs\u002F02.existing-app",{"title":21,"path":22,"stem":23},"Bring your schema","\u002Fdocs\u002Fbring-your-schema","docs\u002F03.bring-your-schema",{"title":25,"path":26,"stem":27},"The CLI","\u002Fdocs\u002Fcli","docs\u002F04.cli",{"title":29,"path":30,"stem":31,"children":32,"page":49},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",[33,37,41,45],{"title":34,"path":35,"stem":36},"Philosophy","\u002Fdocs\u002Fconcepts\u002Fphilosophy","docs\u002F2.concepts\u002F1.philosophy",{"title":38,"path":39,"stem":40},"The Frond","\u002Fdocs\u002Fconcepts\u002Ffrond","docs\u002F2.concepts\u002F2.frond",{"title":42,"path":43,"stem":44},"The shortest path","\u002Fdocs\u002Fconcepts\u002Fshortest-path","docs\u002F2.concepts\u002F3.shortest-path",{"title":46,"path":47,"stem":48},"The base","\u002Fdocs\u002Fconcepts\u002Fthe-base","docs\u002F2.concepts\u002F4.the-base",false,{"title":51,"path":52,"stem":53,"children":54,"page":49},"Schema","\u002Fdocs\u002Fschema","docs\u002F3.schema",[55,59,63,67,71],{"title":56,"path":57,"stem":58},"Entities","\u002Fdocs\u002Fschema\u002Fentities","docs\u002F3.schema\u002F1.entities",{"title":60,"path":61,"stem":62},"Views","\u002Fdocs\u002Fschema\u002Fviews","docs\u002F3.schema\u002F2.views",{"title":64,"path":65,"stem":66},"The identity card","\u002Fdocs\u002Fschema\u002Fcard","docs\u002F3.schema\u002F3.card",{"title":68,"path":69,"stem":70},"Standard Schema","\u002Fdocs\u002Fschema\u002Fstandard-schema","docs\u002F3.schema\u002F4.standard-schema",{"title":72,"path":73,"stem":74},"How a schema moves","\u002Fdocs\u002Fschema\u002Fevolution","docs\u002F3.schema\u002F5.evolution",{"title":76,"path":77,"stem":78,"children":79,"page":49},"Business","\u002Fdocs\u002Fbusiness","docs\u002F4.business",[80,84,88,92,96,100,104,108,112,116],{"title":81,"path":82,"stem":83},"Handlers","\u002Fdocs\u002Fbusiness\u002Fhandlers","docs\u002F4.business\u002F1.handlers",{"title":85,"path":86,"stem":87},"Ports","\u002Fdocs\u002Fbusiness\u002Fports","docs\u002F4.business\u002F10.ports",{"title":89,"path":90,"stem":91},"Presenters","\u002Fdocs\u002Fbusiness\u002Fpresenters","docs\u002F4.business\u002F2.presenters",{"title":93,"path":94,"stem":95},"Collectors","\u002Fdocs\u002Fbusiness\u002Fcollectors","docs\u002F4.business\u002F3.collectors",{"title":97,"path":98,"stem":99},"Errors","\u002Fdocs\u002Fbusiness\u002Ferrors","docs\u002F4.business\u002F4.errors",{"title":101,"path":102,"stem":103},"Seeds","\u002Fdocs\u002Fbusiness\u002Fseeds","docs\u002F4.business\u002F5.seeds",{"title":105,"path":106,"stem":107},"Facts","\u002Fdocs\u002Fbusiness\u002Ffacts","docs\u002F4.business\u002F6.facts",{"title":109,"path":110,"stem":111},"Storage","\u002Fdocs\u002Fbusiness\u002Fstorage","docs\u002F4.business\u002F7.storage",{"title":113,"path":114,"stem":115},"Writes that stand or fall as one","\u002Fdocs\u002Fbusiness\u002Ftogether","docs\u002F4.business\u002F8.together",{"title":117,"path":118,"stem":119},"Repositories","\u002Fdocs\u002Fbusiness\u002Frepositories","docs\u002F4.business\u002F9.repositories",{"title":121,"path":122,"stem":123,"children":124,"page":49},"Client","\u002Fdocs\u002Fclient","docs\u002F5.client",[125,129,133,137,141],{"title":126,"path":127,"stem":128},"Queries & commands","\u002Fdocs\u002Fclient\u002Fqueries-commands","docs\u002F5.client\u002F1.queries-commands",{"title":130,"path":131,"stem":132},"Forms","\u002Fdocs\u002Fclient\u002Fforms","docs\u002F5.client\u002F2.forms",{"title":134,"path":135,"stem":136},"Session","\u002Fdocs\u002Fclient\u002Fsession","docs\u002F5.client\u002F3.session",{"title":138,"path":139,"stem":140},"invoke","\u002Fdocs\u002Fclient\u002Finvoke","docs\u002F5.client\u002F4.invoke",{"title":142,"path":143,"stem":144},"Back-office","\u002Fdocs\u002Fclient\u002Fadmin","docs\u002F5.client\u002F5.admin",{"title":146,"path":147,"stem":148,"children":149,"page":49},"Infrastructure","\u002Fdocs\u002Finfra","docs\u002F6.infra",[150,154,158,162,166,170,174,178,182],{"title":151,"path":152,"stem":153},"The gradient","\u002Fdocs\u002Finfra\u002Fgradient","docs\u002F6.infra\u002F1.gradient",{"title":155,"path":156,"stem":157},"Surfaces — REST & GraphQL","\u002Fdocs\u002Finfra\u002Fsurfaces","docs\u002F6.infra\u002F2.surfaces",{"title":159,"path":160,"stem":161},"Deployment","\u002Fdocs\u002Finfra\u002Fdeployment","docs\u002F6.infra\u002F3.deployment",{"title":163,"path":164,"stem":165},"Hosts","\u002Fdocs\u002Finfra\u002Fhosts","docs\u002F6.infra\u002F4.hosts",{"title":167,"path":168,"stem":169},"Sources","\u002Fdocs\u002Finfra\u002Fsources","docs\u002F6.infra\u002F5.sources",{"title":171,"path":172,"stem":173},"Lifecycle","\u002Fdocs\u002Finfra\u002Flifecycle","docs\u002F6.infra\u002F6.lifecycle",{"title":175,"path":176,"stem":177},"Identity across Fronds","\u002Fdocs\u002Finfra\u002Fidentity","docs\u002F6.infra\u002F7.identity",{"title":179,"path":180,"stem":181},"Observability","\u002Fdocs\u002Finfra\u002Fobservability","docs\u002F6.infra\u002F8.observability",{"title":183,"path":184,"stem":185},"Testing","\u002Fdocs\u002Finfra\u002Ftesting","docs\u002F6.infra\u002F9.testing",{"id":187,"title":179,"body":188,"description":1786,"extension":1787,"meta":1788,"navigation":292,"path":180,"seo":1789,"stem":181,"__hash__":1790},"docs_en\u002Fdocs\u002F6.infra\u002F8.observability.md",{"type":189,"value":190,"toc":1774},"minimark",[191,195,207,232,351,359,364,367,446,539,550,556,560,567,575,582,588,595,599,660,667,678,687,697,703,710,714,721,732,894,905,912,934,938,997,1017,1025,1044,1047,1051,1057,1151,1172,1185,1191,1198,1281,1296,1300,1310,1328,1371,1386,1411,1415,1418,1487,1504,1514,1521,1531,1535,1545,1556,1567,1571,1581,1630,1640,1643,1726,1741,1770],[192,193,179],"h1",{"id":194},"observability",[196,197,198,202,203,206],"p",{},[199,200,201],"code",{},"@fougere\u002Fobservability"," is optional in the strong sense: core holds no tracing code at\nall, only a ",[199,204,205],{},"trace"," field on the invocation that it carries and never reads. An app that\ndoes not install it pays nothing.",[208,209,214],"pre",{"className":210,"code":211,"language":212,"meta":213,"style":213},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","pnpm add @fougere\u002Fobservability\n","bash","",[199,215,216],{"__ignoreMap":213},[217,218,221,225,229],"span",{"class":219,"line":220},"line",1,[217,222,224],{"class":223},"sbgvK","pnpm",[217,226,228],{"class":227},"s_sjI"," add",[217,230,231],{"class":227}," @fougere\u002Fobservability\n",[208,233,237],{"className":234,"code":235,"language":236,"meta":213,"style":213},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { trace, onSpan, otlp, metrics } from '@fougere\u002Fobservability';\n\napp.use(trace());                       \u002F\u002F every operation\napp.use('post', trace());               \u002F\u002F one entity's\n","ts",[199,238,239,287,294,322],{"__ignoreMap":213},[217,240,241,245,249,253,256,259,261,264,266,269,272,275,279,281,284],{"class":219,"line":220},[217,242,244],{"class":243},"sVHd0","import",[217,246,248],{"class":247},"sP7_E"," {",[217,250,252],{"class":251},"su5hD"," trace",[217,254,255],{"class":247},",",[217,257,258],{"class":251}," onSpan",[217,260,255],{"class":247},[217,262,263],{"class":251}," otlp",[217,265,255],{"class":247},[217,267,268],{"class":251}," metrics",[217,270,271],{"class":247}," }",[217,273,274],{"class":243}," from",[217,276,278],{"class":277},"sjJ54"," '",[217,280,201],{"class":227},[217,282,283],{"class":277},"'",[217,285,286],{"class":247},";\n",[217,288,290],{"class":219,"line":289},2,[217,291,293],{"emptyLinePlaceholder":292},true,"\n",[217,295,297,300,303,307,310,312,315,318],{"class":219,"line":296},3,[217,298,299],{"class":251},"app",[217,301,302],{"class":247},".",[217,304,306],{"class":305},"sGLFI","use",[217,308,309],{"class":251},"(",[217,311,205],{"class":305},[217,313,314],{"class":251},"())",[217,316,317],{"class":247},";",[217,319,321],{"class":320},"sutJx","                       \u002F\u002F every operation\n",[217,323,325,327,329,331,333,335,338,340,342,344,346,348],{"class":219,"line":324},4,[217,326,299],{"class":251},[217,328,302],{"class":247},[217,330,306],{"class":305},[217,332,309],{"class":251},[217,334,283],{"class":277},[217,336,337],{"class":227},"post",[217,339,283],{"class":277},[217,341,255],{"class":247},[217,343,252],{"class":305},[217,345,314],{"class":251},[217,347,317],{"class":247},[217,349,350],{"class":320},"               \u002F\u002F one entity's\n",[196,352,353,354,358],{},"It is an ordinary ",[355,356,357],"a",{"href":82},"app middleware"," because an operation already\nhas a lifecycle and it is that one — a second hook system would be a second answer to a\nsettled question.",[360,361,363],"h2",{"id":362},"one-span-per-operation","One span per operation",[196,365,366],{},"A span carries an op's duration and its verdict:",[208,368,370],{"className":234,"code":369,"language":236,"meta":213,"style":213},"onSpan((span) => console.log(span.frond, span.entity, span.operation, span.ms, span.error));\n",[199,371,372],{"__ignoreMap":213},[217,373,374,377,379,381,384,387,391,394,396,399,402,404,407,409,412,414,417,419,421,423,426,428,430,432,435,437,439,441,444],{"class":219,"line":220},[217,375,376],{"class":305},"onSpan",[217,378,309],{"class":251},[217,380,309],{"class":247},[217,382,217],{"class":383},"s99_P",[217,385,386],{"class":247},")",[217,388,390],{"class":389},"sbsja"," =>",[217,392,393],{"class":251}," console",[217,395,302],{"class":247},[217,397,398],{"class":305},"log",[217,400,401],{"class":251},"(span",[217,403,302],{"class":247},[217,405,406],{"class":251},"frond",[217,408,255],{"class":247},[217,410,411],{"class":251}," span",[217,413,302],{"class":247},[217,415,416],{"class":251},"entity",[217,418,255],{"class":247},[217,420,411],{"class":251},[217,422,302],{"class":247},[217,424,425],{"class":251},"operation",[217,427,255],{"class":247},[217,429,411],{"class":251},[217,431,302],{"class":247},[217,433,434],{"class":251},"ms",[217,436,255],{"class":247},[217,438,411],{"class":251},[217,440,302],{"class":247},[217,442,443],{"class":251},"error))",[217,445,286],{"class":247},[447,448,449,460],"table",{},[450,451,452],"thead",{},[453,454,455,458],"tr",{},[456,457],"th",{},[456,459],{},[461,462,463,481,490,501,516,525],"tbody",{},[453,464,465,478],{},[466,467,468,471,472,471,475],"td",{},[199,469,470],{},"traceId"," \u002F ",[199,473,474],{},"spanId",[199,476,477],{},"parentId",[466,479,480],{},"where this step sits in the tree",[453,482,483,487],{},[466,484,485],{},[199,486,406],{},[466,488,489],{},"which Frond owned the op — the deployment unit, so the first thing to group by",[453,491,492,498],{},[466,493,494,471,496],{},[199,495,416],{},[199,497,425],{},[466,499,500],{},"what was called",[453,502,503,508],{},[466,504,505],{},[199,506,507],{},"startedAt",[466,509,510,511,515],{},"an ",[512,513,514],"strong",{},"instant",", epoch milliseconds",[453,517,518,522],{},[466,519,520],{},[199,521,434],{},[466,523,524],{},"how long",[453,526,527,532],{},[466,528,529],{},[199,530,531],{},"error",[466,533,534,535,538],{},"the ",[199,536,537],{},"FougereError"," code when it refused, absent when it answered",[196,540,541,542,546,547,549],{},"Two clocks, and they are not the same measurement: the wall clock says ",[543,544,545],"em",{},"when",", so two\nprocesses land on one timeline; the monotonic one says ",[543,548,524],{},", without being moved by\nan NTP correction mid-call.",[196,551,552,553,555],{},"Nothing is opened while no sink is set — observing is a decision, and the cost of one\nnobody asked for is zero rather than small. ",[199,554,376],{}," returns the way to withdraw.",[360,557,559],{"id":558},"the-trace-survives-the-wire","The trace survives the wire",[196,561,562,563,566],{},"The parent rides the ",[512,564,565],{},"invocation",", not a header:",[208,568,573],{"className":569,"code":571,"language":572},[570],"language-text","app                     post.list        traceId a3f… spanId 01\n  └─ blog (split)       post.list        traceId a3f… spanId 02, parent 01\n","text",[199,574,571],{"__ignoreMap":213},[196,576,577,578,581],{},"A header is HTTP's alone, and the same call over a socket would have arrived untraced. The\ninvocation is what ",[543,579,580],{},"every"," transport carries, so the trace crosses whatever the topology\nbecame — and the format is W3C Trace Context, so a collector reads it beside anything else.",[196,583,584,585,302],{},"The same middleware runs on both halves of a split: at the door a call arrives at, and at\nthe stand-in it leaves from. That is why the numbers line up across processes — and why\n",[512,586,587],{},"the difference between the two spans is what the wire cost",[196,589,590,591,594],{},"One case the wire cannot describe: a handler reaching a second Frond builds a fresh\ninvocation, so the parent is not on that call. It is in the context the first one is still\nrunning inside, which ",[199,592,593],{},"currentSpan()"," reads.",[360,596,598],{"id":597},"the-four-signals-from-the-span-that-already-exists","The four signals, from the span that already exists",[208,600,602],{"className":234,"code":601,"language":236,"meta":213,"style":213},"const measured = metrics(app);\nonSpan(measured.sink);\n\nmeasured.snapshot();   \u002F\u002F what to publish now\n",[199,603,604,624,638,642],{"__ignoreMap":213},[217,605,606,609,613,617,619,622],{"class":219,"line":220},[217,607,608],{"class":389},"const",[217,610,612],{"class":611},"s_hVV"," measured",[217,614,616],{"class":615},"smGrS"," =",[217,618,268],{"class":305},[217,620,621],{"class":251},"(app)",[217,623,286],{"class":247},[217,625,626,628,631,633,636],{"class":219,"line":289},[217,627,376],{"class":305},[217,629,630],{"class":251},"(measured",[217,632,302],{"class":247},[217,634,635],{"class":251},"sink)",[217,637,286],{"class":247},[217,639,640],{"class":219,"line":296},[217,641,293],{"emptyLinePlaceholder":292},[217,643,644,647,649,652,655,657],{"class":219,"line":324},[217,645,646],{"class":251},"measured",[217,648,302],{"class":247},[217,650,651],{"class":305},"snapshot",[217,653,654],{"class":251},"()",[217,656,317],{"class":247},[217,658,659],{"class":320},"   \u002F\u002F what to publish now\n",[196,661,662,663,666],{},"Rate, errors and duration are ",[512,664,665],{},"one"," metric — a histogram of durations, dimensioned by the\nop and by whether it refused. Its count is the rate, its dimension is the error rate, its\nbuckets are the latency. Splitting it into three counters would publish the same numbers\nthree times and let them disagree.",[196,668,669,670,673,674,677],{},"The fourth, saturation, cannot come from a finished span, because it is about the ones that\nhave ",[512,671,672],{},"not"," finished. The middleware counts them and ",[199,675,676],{},"activeCalls()"," reads it.",[679,680,681],"note",{},[196,682,683,686],{},[512,684,685],{},"Cardinality is bounded by construction",": frond × entity × operation × {ok, error}, plus\nthe error code when there is one — all declared in the code. Nothing carrying an id, a user\nor a trace ever becomes a dimension; that is the one mistake a metrics layer cannot recover\nfrom.",[196,688,689,690,692,693,696],{},"Passing ",[199,691,299],{}," is optional and only feeds the topology, which is ",[512,694,695],{},"discovered"," rather than\ndeclared, from the two things a process can honestly say: a Frond it SCANNED runs here, and\na Frond it CALLED without having scanned runs elsewhere.",[208,698,701],{"className":699,"code":700,"language":572},[570],"processus catalog   catalog → local        it holds the code\nprocessus shop      shop    → local\nprocessus shop      catalog → remote       it called it, it never scanned it\n",[199,702,700],{"__ignoreMap":213},[196,704,705,706,709],{},"Deliberately not read from ",[199,707,708],{},"remotes:"," — a config key states an intent, while a Frond that\nanswered a call is a fact. The two disagree exactly when something is misconfigured, which\nis when a dashboard has to be right.",[360,711,713],{"id":712},"the-third-signal-logs-and-the-only-thing-that-makes-them-one","The third signal: logs, and the only thing that makes them one",[196,715,716,717,720],{},"A log shipped without a trace id is a log stored somewhere else. What makes it the third\npillar is landing on a trace and reading the lines ",[543,718,719],{},"that call"," produced.",[196,722,723,724,727,728,731],{},"The logger has a door — ",[199,725,726],{},"onLog"," in core — that hands out a ",[512,729,730],{},"structured record"," before any\nformatting, because what reaches the console is already cooked: ANSI codes, a badge, a\ntimestamp. Core emits the record and knows nothing more; this package attaches the span and\nspeaks OTLP.",[208,733,735],{"className":234,"code":734,"language":236,"meta":213,"style":213},"import { onLog, loggerMiddleware, Logger } from '@fougere\u002Fcore';\nimport { logs } from '@fougere\u002Fobservability';\n\napp.use(trace());                                  \u002F\u002F first — the span must exist\napp.use(loggerMiddleware(new Logger('blog')));     \u002F\u002F one line in, one line out, timed\n\nonLog(logs({ service: 'blog' }).sink);\n",[199,736,737,769,790,794,813,851,856],{"__ignoreMap":213},[217,738,739,741,743,746,748,751,753,756,758,760,762,765,767],{"class":219,"line":220},[217,740,244],{"class":243},[217,742,248],{"class":247},[217,744,745],{"class":251}," onLog",[217,747,255],{"class":247},[217,749,750],{"class":251}," loggerMiddleware",[217,752,255],{"class":247},[217,754,755],{"class":251}," Logger",[217,757,271],{"class":247},[217,759,274],{"class":243},[217,761,278],{"class":277},[217,763,764],{"class":227},"@fougere\u002Fcore",[217,766,283],{"class":277},[217,768,286],{"class":247},[217,770,771,773,775,778,780,782,784,786,788],{"class":219,"line":289},[217,772,244],{"class":243},[217,774,248],{"class":247},[217,776,777],{"class":251}," logs",[217,779,271],{"class":247},[217,781,274],{"class":243},[217,783,278],{"class":277},[217,785,201],{"class":227},[217,787,283],{"class":277},[217,789,286],{"class":247},[217,791,792],{"class":219,"line":296},[217,793,293],{"emptyLinePlaceholder":292},[217,795,796,798,800,802,804,806,808,810],{"class":219,"line":324},[217,797,299],{"class":251},[217,799,302],{"class":247},[217,801,306],{"class":305},[217,803,309],{"class":251},[217,805,205],{"class":305},[217,807,314],{"class":251},[217,809,317],{"class":247},[217,811,812],{"class":320},"                                  \u002F\u002F first — the span must exist\n",[217,814,816,818,820,822,824,827,829,832,834,836,838,841,843,846,848],{"class":219,"line":815},5,[217,817,299],{"class":251},[217,819,302],{"class":247},[217,821,306],{"class":305},[217,823,309],{"class":251},[217,825,826],{"class":305},"loggerMiddleware",[217,828,309],{"class":251},[217,830,831],{"class":615},"new",[217,833,755],{"class":305},[217,835,309],{"class":251},[217,837,283],{"class":277},[217,839,840],{"class":227},"blog",[217,842,283],{"class":277},[217,844,845],{"class":251},")))",[217,847,317],{"class":247},[217,849,850],{"class":320},"     \u002F\u002F one line in, one line out, timed\n",[217,852,854],{"class":219,"line":853},6,[217,855,293],{"emptyLinePlaceholder":292},[217,857,859,861,863,866,868,871,875,878,880,882,884,886,888,890,892],{"class":219,"line":858},7,[217,860,726],{"class":305},[217,862,309],{"class":251},[217,864,865],{"class":305},"logs",[217,867,309],{"class":251},[217,869,870],{"class":247},"{",[217,872,874],{"class":873},"skxfh"," service",[217,876,877],{"class":247},":",[217,879,278],{"class":277},[217,881,840],{"class":227},[217,883,283],{"class":277},[217,885,271],{"class":247},[217,887,386],{"class":251},[217,889,302],{"class":247},[217,891,635],{"class":251},[217,893,286],{"class":247},[196,895,896,897,900,901,904],{},"The span is read ",[512,898,899],{},"at the moment the line is written",", never at flush time — by then the\ncall it belongs to is over and the context is somebody else's. A line written outside any\ncall (a boot line, a shutdown line) leaves with ",[512,902,903],{},"no"," trace id rather than a zeroed one:\nabsent means \"not inside a call\", and a forged zero would gather every process's startup\ninto one phantom trace.",[196,906,907,908,911],{},"Forwarding is an addition, never a replacement: the console keeps its line, and a sink that\nthrows costs nobody theirs. ",[199,909,910],{},"setLogLevel"," filters first, so a level that never printed is\nnever shipped either — one place where the level lives.",[679,913,914],{},[196,915,916,917,920,921,920,924,920,927,929,930,933],{},"Each level now takes its own console method (",[199,918,919],{},"debug",", ",[199,922,923],{},"info",[199,925,926],{},"warn",[199,928,531],{},"). They used to\ncollapse onto ",[199,931,932],{},"console.log"," for the first two, so nothing downstream — a terminal filter, a\ncollector — could tell a debug line from an info one.",[360,935,937],{"id":936},"sending-it-somewhere","Sending it somewhere",[208,939,941],{"className":234,"code":940,"language":236,"meta":213,"style":213},"const exporter = otlp({ service: 'blog', metrics: measured });\nonSpan(exporter.sink);\n",[199,942,943,984],{"__ignoreMap":213},[217,944,945,947,950,952,954,956,958,960,962,964,966,968,970,972,974,977,980,982],{"class":219,"line":220},[217,946,608],{"class":389},[217,948,949],{"class":611}," exporter",[217,951,616],{"class":615},[217,953,263],{"class":305},[217,955,309],{"class":251},[217,957,870],{"class":247},[217,959,874],{"class":873},[217,961,877],{"class":247},[217,963,278],{"class":277},[217,965,840],{"class":227},[217,967,283],{"class":277},[217,969,255],{"class":247},[217,971,268],{"class":873},[217,973,877],{"class":247},[217,975,976],{"class":251}," measured ",[217,978,979],{"class":247},"}",[217,981,386],{"class":251},[217,983,286],{"class":247},[217,985,986,988,991,993,995],{"class":219,"line":289},[217,987,376],{"class":305},[217,989,990],{"class":251},"(exporter",[217,992,302],{"class":247},[217,994,635],{"class":251},[217,996,286],{"class":247},[196,998,999,1000,1003,1004,1007,1008,920,1011,920,1014,302],{},"OTLP over HTTP, batched every second, in the JSON encoding — no protobuf, no dependency.\nEndpoints default to the convention (",[199,1001,1002],{},"http:\u002F\u002Flocalhost:4318\u002Fv1\u002Ftraces",", and the metrics one\nwith its last segment swapped) — name ",[199,1005,1006],{},"metricsUrl"," when traces and metrics go to two\ndifferent engines rather than a collector in front. The three signals are three paths on\nthe same door: ",[199,1009,1010],{},"\u002Fv1\u002Ftraces",[199,1012,1013],{},"\u002Fv1\u002Fmetrics",[199,1015,1016],{},"\u002Fv1\u002Flogs",[679,1018,1019],{},[196,1020,1021,1024],{},[512,1022,1023],{},"A metric with no data points makes a collector reject the whole batch."," Measured against\nPrometheus: it answers 500 and every other metric in the payload is lost with it — so a\nprocess that calls nobody, and therefore has no edges, publishes no edge metric rather than\nan empty one.",[196,1026,1027,1028,1031,1032,1035,1036,1039,1040,1043],{},"A process about to exit calls ",[199,1029,1030],{},"flush()","; ",[199,1033,1034],{},"stop()"," ends the timer and sends what is left.\n",[199,1037,1038],{},"onError"," is told when a batch could not go, and defaults to silence: ",[512,1041,1042],{},"a trace must never\nbreak a call",", and a sink that throws is a broken exporter, not a broken call.",[196,1045,1046],{},"Metrics go out on every beat even when no span finished — a gauge that stops being\npublished reads as \"gone\", not as \"idle\".",[360,1048,1050],{"id":1049},"wiring-it-once","Wiring it, once",[196,1052,1053,1054,877],{},"Everything on this page is behind one member of the app's ",[355,1055,1056],{"href":172},"ascent",[208,1058,1060],{"className":234,"code":1059,"language":236,"meta":213,"style":213},"const app = await createApp({\n  root,\n  createContainer,\n  extensions: [observability({ service: 'blog', otlp: 'http:\u002F\u002Flocalhost:4318' })],\n});\n",[199,1061,1062,1082,1090,1097,1143],{"__ignoreMap":213},[217,1063,1064,1066,1069,1071,1074,1077,1079],{"class":219,"line":220},[217,1065,608],{"class":389},[217,1067,1068],{"class":611}," app",[217,1070,616],{"class":615},[217,1072,1073],{"class":243}," await",[217,1075,1076],{"class":305}," createApp",[217,1078,309],{"class":251},[217,1080,1081],{"class":247},"{\n",[217,1083,1084,1087],{"class":219,"line":289},[217,1085,1086],{"class":251},"  root",[217,1088,1089],{"class":247},",\n",[217,1091,1092,1095],{"class":219,"line":296},[217,1093,1094],{"class":251},"  createContainer",[217,1096,1089],{"class":247},[217,1098,1099,1102,1104,1107,1109,1111,1113,1115,1117,1119,1121,1123,1125,1127,1129,1131,1134,1136,1138,1141],{"class":219,"line":324},[217,1100,1101],{"class":873},"  extensions",[217,1103,877],{"class":247},[217,1105,1106],{"class":251}," [",[217,1108,194],{"class":305},[217,1110,309],{"class":251},[217,1112,870],{"class":247},[217,1114,874],{"class":873},[217,1116,877],{"class":247},[217,1118,278],{"class":277},[217,1120,840],{"class":227},[217,1122,283],{"class":277},[217,1124,255],{"class":247},[217,1126,263],{"class":873},[217,1128,877],{"class":247},[217,1130,278],{"class":277},[217,1132,1133],{"class":227},"http:\u002F\u002Flocalhost:4318",[217,1135,283],{"class":277},[217,1137,271],{"class":247},[217,1139,1140],{"class":251},")]",[217,1142,1089],{"class":247},[217,1144,1145,1147,1149],{"class":219,"line":815},[217,1146,979],{"class":247},[217,1148,386],{"class":251},[217,1150,286],{"class":247},[196,1152,1153,1156,1157,1160,1161,1164,1165,1168,1169,302],{},[199,1154,1155],{},"up"," installs the middleware, the accumulator and the sinks ",[512,1158,1159],{},"in the order that matters"," —\n",[199,1162,1163],{},"trace()"," opens the span every log line inside the call will carry, so installed the other\nway round the lines leave uncorrelated. ",[199,1166,1167],{},"down"," withdraws them and flushes what is buffered,\ninside ",[199,1170,1171],{},"dispose()",[196,1173,1174,1175,1177,1178,1180,1181,1184],{},"That release is not decoration. ",[199,1176,376],{}," and ",[199,1179,726],{}," have always RETURNED their withdrawal\nand nothing called it: a discarded app kept feeding the sinks of the app that replaced it,\nso every metric counted twice. Invisible until ",[355,1182,1183],{"href":172},"the ring turns",", and\nthen permanent.",[196,1186,1187,1190],{},[199,1188,1189],{},"otlp"," absent, nothing leaves the process — and the topology below still answers.",[196,1192,1193,1194,1197],{},"Under a host that writes the boot file itself, an extension is ",[512,1195,1196],{},"named"," rather than passed:\nit is a function and the module writes a file, so the options travel beside the name as\ndata.",[208,1199,1201],{"className":234,"code":1200,"language":236,"meta":213,"style":213},"\u002F\u002F nuxt.config.ts\nfougere: {\n  observability: { service: 'blog', otlp: 'http:\u002F\u002Flocalhost:4318' },\n  calls: { panel: true },        \u002F\u002F `false` turns a key off; absent is the same\n}\n",[199,1202,1203,1208,1218,1252,1276],{"__ignoreMap":213},[217,1204,1205],{"class":219,"line":220},[217,1206,1207],{"class":320},"\u002F\u002F nuxt.config.ts\n",[217,1209,1210,1213,1215],{"class":219,"line":289},[217,1211,1212],{"class":223},"fougere",[217,1214,877],{"class":247},[217,1216,1217],{"class":247}," {\n",[217,1219,1220,1223,1225,1227,1229,1231,1233,1235,1237,1239,1241,1243,1245,1247,1249],{"class":219,"line":296},[217,1221,1222],{"class":223},"  observability",[217,1224,877],{"class":247},[217,1226,248],{"class":247},[217,1228,874],{"class":223},[217,1230,877],{"class":247},[217,1232,278],{"class":277},[217,1234,840],{"class":227},[217,1236,283],{"class":277},[217,1238,255],{"class":247},[217,1240,263],{"class":223},[217,1242,877],{"class":247},[217,1244,278],{"class":277},[217,1246,1133],{"class":227},[217,1248,283],{"class":277},[217,1250,1251],{"class":247}," },\n",[217,1253,1254,1257,1259,1261,1264,1266,1270,1273],{"class":219,"line":324},[217,1255,1256],{"class":223},"  calls",[217,1258,877],{"class":247},[217,1260,248],{"class":247},[217,1262,1263],{"class":223}," panel",[217,1265,877],{"class":247},[217,1267,1269],{"class":1268},"syTEX"," true",[217,1271,1272],{"class":247}," },",[217,1274,1275],{"class":320},"        \u002F\u002F `false` turns a key off; absent is the same\n",[217,1277,1278],{"class":219,"line":815},[217,1279,1280],{"class":247},"}\n",[196,1282,1283,1284,1287,1288,1291,1292,1295],{},"The keys are declared, not open: one per extension package, the key being both the package\nsuffix and the export name — ",[199,1285,1286],{},"calls"," is ",[199,1289,1290],{},"import { calls } from '@fougere\u002Fcalls'",". An open\nrecord would accept ",[199,1293,1294],{},"callz: {}"," in silence.",[360,1297,1299],{"id":1298},"the-dev-panel-what-this-process-dispatched","The dev panel — what this process dispatched",[196,1301,1302,1305,1306,1309],{},[199,1303,1304],{},"@fougere\u002Fcalls"," is the second optional extension, and it ",[512,1307,1308],{},"watches"," rather than\nparticipates:",[208,1311,1313],{"className":210,"code":1312,"language":212,"meta":213,"style":213},"pnpm add -D @fougere\u002Fcalls\n",[199,1314,1315],{"__ignoreMap":213},[217,1316,1317,1319,1321,1325],{"class":219,"line":220},[217,1318,224],{"class":223},[217,1320,228],{"class":227},[217,1322,1324],{"class":1323},"stzsN"," -D",[217,1326,1327],{"class":227}," @fougere\u002Fcalls\n",[208,1329,1331],{"className":234,"code":1330,"language":236,"meta":213,"style":213},"extensions: [calls({ max: 500, panel: true })],\n",[199,1332,1333],{"__ignoreMap":213},[217,1334,1335,1338,1340,1342,1344,1346,1348,1351,1353,1357,1359,1361,1363,1365,1367,1369],{"class":219,"line":220},[217,1336,1337],{"class":223},"extensions",[217,1339,877],{"class":247},[217,1341,1106],{"class":251},[217,1343,1286],{"class":305},[217,1345,309],{"class":251},[217,1347,870],{"class":247},[217,1349,1350],{"class":873}," max",[217,1352,877],{"class":247},[217,1354,1356],{"class":1355},"srdBf"," 500",[217,1358,255],{"class":247},[217,1360,1263],{"class":873},[217,1362,877],{"class":247},[217,1364,1269],{"class":1268},[217,1366,271],{"class":247},[217,1368,1140],{"class":251},[217,1370,1089],{"class":247},[196,1372,1373,1374,1377,1378,1381,1382,1385],{},"It subscribes to ",[199,1375,1376],{},"app.observe"," — passive, and its own failure is swallowed — so it sees\nwhat a middleware cannot: a call refused ",[512,1379,1380],{},"before"," any handler (an unknown route, an\nentity hosted elsewhere, a call arriving while the door drains), and the route kind of\nevery call, so a local execution and a hop to another process read the same way. Beside\nthe calls it keeps a bounded ring of log lines, of errors, and — when\n",[199,1383,1384],{},"@fougere\u002Fadapter-sql"," is there — of the statements each call issued.",[196,1387,1388,1389,1392,1393,1396,1397,1403,1404,1407,1408],{},"Nothing is stored and no port is opened unless ",[199,1390,1391],{},"panel"," says so. The ring is served as\n",[199,1394,1395],{},"rpc.calls",", and the reader is ",[355,1398,1400],{"href":1399},"\u002Fdocs\u002Fcli#fougere-devtools--what-the-running-apps-are-dispatching",[199,1401,1402],{},"fougere devtools","\nover ",[199,1405,1406],{},"\u002F_fougere\u002Fcall",", like any other consumer. An app that never installed it answers\n",[199,1409,1410],{},"Unknown rpc operation 'calls'. It serves discover.",[360,1412,1414],{"id":1413},"the-shape-of-the-system-on-the-wire","The shape of the system, on the wire",[196,1416,1417],{},"An app can be asked what shape it is in, on the same wire as everything else:",[208,1419,1421],{"className":234,"code":1420,"language":236,"meta":213,"style":213},"await call({ entity: 'rpc', op: 'topology' });\n\u002F\u002F { fronds: [{ frond: 'shop', placement: 'local', entities: 2, doors: 2 },\n\u002F\u002F             { frond: 'catalog', placement: 'remote', entities: 0, doors: 0 }],\n\u002F\u002F   edges:  [{ from: 'shop', to: 'catalog', count: 12, errors: 1 }],\n\u002F\u002F   active: 0, since: 1755861234567 }\n",[199,1422,1423,1467,1472,1477,1482],{"__ignoreMap":213},[217,1424,1425,1428,1431,1433,1435,1438,1440,1442,1445,1447,1449,1452,1454,1456,1459,1461,1463,1465],{"class":219,"line":220},[217,1426,1427],{"class":243},"await",[217,1429,1430],{"class":305}," call",[217,1432,309],{"class":251},[217,1434,870],{"class":247},[217,1436,1437],{"class":873}," entity",[217,1439,877],{"class":247},[217,1441,278],{"class":277},[217,1443,1444],{"class":227},"rpc",[217,1446,283],{"class":277},[217,1448,255],{"class":247},[217,1450,1451],{"class":873}," op",[217,1453,877],{"class":247},[217,1455,278],{"class":277},[217,1457,1458],{"class":227},"topology",[217,1460,283],{"class":277},[217,1462,271],{"class":247},[217,1464,386],{"class":251},[217,1466,286],{"class":247},[217,1468,1469],{"class":219,"line":289},[217,1470,1471],{"class":320},"\u002F\u002F { fronds: [{ frond: 'shop', placement: 'local', entities: 2, doors: 2 },\n",[217,1473,1474],{"class":219,"line":296},[217,1475,1476],{"class":320},"\u002F\u002F             { frond: 'catalog', placement: 'remote', entities: 0, doors: 0 }],\n",[217,1478,1479],{"class":219,"line":324},[217,1480,1481],{"class":320},"\u002F\u002F   edges:  [{ from: 'shop', to: 'catalog', count: 12, errors: 1 }],\n",[217,1483,1484],{"class":219,"line":815},[217,1485,1486],{"class":320},"\u002F\u002F   active: 0, since: 1755861234567 }\n",[196,1488,1489,1492,1493,1496,1497,1500,1501,1503],{},[512,1490,1491],{},"Nothing in it is declared."," A Frond is ",[199,1494,1495],{},"local"," because this process scanned it, ",[199,1498,1499],{},"remote","\nbecause it answered a call nobody here hosts — deliberately not read from ",[199,1502,708],{},", which\nstates an intent. The two disagree exactly when something is misconfigured, which is when a\ndashboard has to be right.",[196,1505,1506,1509,1510,1513],{},[199,1507,1508],{},"rpc.topology"," is declared by this package, not by core — so an app that never installed it\nrefuses the op by name, and that refusal is the whole degradation a reader needs. It sits\nbeside ",[199,1511,1512],{},"rpc.discover",": the card says what a process HOSTS, this says what shape it is in.",[196,1515,1516,1517,1520],{},"A remote's ",[199,1518,1519],{},"entities: 0, doors: 0"," is not an empty Frond — its shape is published by the\nprocess that owns it, under its own service name.",[196,1522,1523,1526,1527,1530],{},[199,1524,1525],{},"@fougere\u002Fadmin"," reads it on its ",[512,1528,1529],{},"Topology"," page, which is the same answer drawn: what\nruns here, what answered from elsewhere, and every call path observed between them.",[360,1532,1534],{"id":1533},"what-is-signal-and-what-is-not","What is signal, and what is not",[196,1536,1537,1538,1540,1541,1544],{},"Spans are named for the subject rather than for today's reading of it: a duration and a\nverdict are the matter of a metric as much as of a trace, and an exporter for either hangs\noff the same ",[199,1539,376],{},". That is why ",[199,1542,1543],{},"sinks"," is a list — the two exporters read the same\nvalue instead of the middleware producing it twice.",[196,1546,1547,1548,1551,1552,1555],{},"The caller of a split call is ",[355,1549,1550],{"href":176},"established, not asserted",": once a\nreceiver verifies an envelope, ",[199,1553,1554],{},"invocation.caller"," names the Frond that signed, and absent\nmeans nothing was established — never \"unknown peer\".",[196,1557,1558,1559,1562,1563,1566],{},"Nothing here reads it yet. A service graph drawn from a verified caller would be a ",[512,1560,1561],{},"fact","\nrather than an inference from an address, and the dimension is bounded like the others, so\nthe two fit together — but the span carries no ",[199,1564,1565],{},"caller"," today, and this page would rather\nsay so than let you look for it.",[360,1568,1570],{"id":1569},"on-a-dashboard","On a dashboard",[196,1572,1573,1574,1577,1578,1580],{},"Anything that speaks OTLP reads this as-is. Two collectors were run against it while it was\nbeing written — Jaeger with Prometheus, then SigNoz — and moving between them changed ",[512,1575,1576],{},"two\nURL strings",": no instrumentation, no span field, no metric. That is what following the\nstandard buys, and it is the same bargain ",[199,1579,708],{}," makes for topology.",[208,1582,1584],{"className":210,"code":1583,"language":212,"meta":213,"style":213},"pnpm -C demos\u002Fobservability dev      # three Fronds, three processes\npnpm -C demos\u002Fobservability load     # k6, in stages\npnpm -C demos\u002Fobservability signoz   # a collector, OTLP on 4318, UI on 8080\n",[199,1585,1586,1602,1616],{"__ignoreMap":213},[217,1587,1588,1590,1593,1596,1599],{"class":219,"line":220},[217,1589,224],{"class":223},[217,1591,1592],{"class":1323}," -C",[217,1594,1595],{"class":227}," demos\u002Fobservability",[217,1597,1598],{"class":227}," dev",[217,1600,1601],{"class":320},"      # three Fronds, three processes\n",[217,1603,1604,1606,1608,1610,1613],{"class":219,"line":289},[217,1605,224],{"class":223},[217,1607,1592],{"class":1323},[217,1609,1595],{"class":227},[217,1611,1612],{"class":227}," load",[217,1614,1615],{"class":320},"     # k6, in stages\n",[217,1617,1618,1620,1622,1624,1627],{"class":219,"line":296},[217,1619,224],{"class":223},[217,1621,1592],{"class":1323},[217,1623,1595],{"class":227},[217,1625,1626],{"class":227}," signoz",[217,1628,1629],{"class":320},"   # a collector, OTLP on 4318, UI on 8080\n",[196,1631,1632,1635,1636,1639],{},[199,1633,1634],{},"demos\u002Fobservability"," is this page, running: a ",[199,1637,1638],{},"cart.checkout"," that reaches a catalog and a\nshipping Frond in two other processes, under staged load. Its domain code says nothing about\nbeing observed.",[196,1641,1642],{},"What to build there, in the order a reader needs it:",[447,1644,1645,1654],{},[450,1646,1647],{},[453,1648,1649,1651],{},[456,1650,1391],{},[456,1652,1653],{},"query",[461,1655,1656,1666,1678,1688,1698,1709],{},[453,1657,1658,1661],{},[466,1659,1660],{},"Throughput",[466,1662,1663],{},[199,1664,1665],{},"sum(rate(fougere_operation_duration_seconds_count[1m]))",[453,1667,1668,1671],{},[466,1669,1670],{},"Error rate",[466,1672,1673,1674,1677],{},"the same, over ",[199,1675,1676],{},"fougere_outcome=\"error\"",", divided by the total",[453,1679,1680,1683],{},[466,1681,1682],{},"Latency p95",[466,1684,1685],{},[199,1686,1687],{},"histogram_quantile(0.95, sum by (le) (rate(…_bucket[1m])))",[453,1689,1690,1693],{},[466,1691,1692],{},"Saturation",[466,1694,1695],{},[199,1696,1697],{},"fougere_operations_active",[453,1699,1700,1703],{},[466,1701,1702],{},"Per Frond",[466,1704,1705,1706],{},"any of the above, ",[199,1707,1708],{},"sum by (fougere_frond)",[453,1710,1711,1714],{},[466,1712,1713],{},"Service graph",[466,1715,1716,1719,1720,471,1723],{},[199,1717,1718],{},"fougere_calls_total"," by ",[199,1721,1722],{},"fougere_from",[199,1724,1725],{},"fougere_to",[196,1727,1728,1729,1732,1733,1736,1737,1740],{},"Two things are worth more than a fifth chart. A ",[512,1730,1731],{},"heatmap"," of\n",[199,1734,1735],{},"sum by (le) (rate(…_bucket[1m]))"," shows where calls actually live — a p95 hides a bimodal\ndistribution, a heatmap cannot. And a ",[512,1738,1739],{},"table of operations sorted by p95",": one slow op at\n20 % of the traffic drags a global quantile far from anything real, and only the sort says\nwhich one.",[679,1742,1743],{},[196,1744,1745,1746,1749,1750,1753,1754,1757,1758,1761,1762,1765,1766,1769],{},"Prometheus renames OTLP metrics on ingestion: ",[199,1747,1748],{},"fougere.operation.duration"," with unit ",[199,1751,1752],{},"s","\nbecomes ",[199,1755,1756],{},"fougere_operation_duration_seconds",", and ",[199,1759,1760],{},"fougere.frond"," becomes the label\n",[199,1763,1764],{},"fougere_frond",". Read the names off ",[199,1767,1768],{},"\u002Fapi\u002Fv1\u002Flabel\u002F__name__\u002Fvalues"," rather than guessing\nthem.",[1771,1772,1773],"style",{},"html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":213,"searchDepth":289,"depth":289,"links":1775},[1776,1777,1778,1779,1780,1781,1782,1783,1784,1785],{"id":362,"depth":289,"text":363},{"id":558,"depth":289,"text":559},{"id":597,"depth":289,"text":598},{"id":712,"depth":289,"text":713},{"id":936,"depth":289,"text":937},{"id":1049,"depth":289,"text":1050},{"id":1298,"depth":289,"text":1299},{"id":1413,"depth":289,"text":1414},{"id":1533,"depth":289,"text":1534},{"id":1569,"depth":289,"text":1570},"One span per operation, a trace that survives any transport, and the four signals derived from it — optional, and free when not installed.","md",{},{"title":179,"description":1786},"hMd4qtjmFmEO0IYxPbfX12Z5X5xmwRh--asSFeOfvXQ",1788560231369]