Name a route
You have one trace in the dashboard. Look at what it is called. Unless you already passed a route, it is showing up as something like Unlabeled template · 6f3a9c2d, which is not a name anybody chose. This page fixes that, and teaches the route concept by making you use it.
Budget five minutes. You need the application from send your first trace and the ability to run it again.
Why the fingerprint is there
Section titled “Why the fingerprint is there”Every captured call carries a template_hash: a SHA-256 over the structure of
your request with the variable parts normalized away, so two calls from the same
prompt template hash the same even though the customer name inside them differs.
It is content-free by construction.
When a row arrives with no route, the server falls back to that fingerprint and
files the call under template:<hash>. The dashboard renders it as Unlabeled
template plus the first eight characters. So your traffic is grouped
correctly, but the group has no name, and nothing downstream can tell you what
that group is for.
Give it a name
Section titled “Give it a name”-
Pick the call you already instrumented
Section titled “Pick the call you already instrumented”Find the function containing the
client.chat.completions.create(...)call that produced your first trace. -
Wrap it in a route
Section titled “Wrap it in a route”A route is a scope. Every wrapped provider call made inside it, at any depth, is attributed to it.
app/llm.py import metergraphdef classify(ticket):with metergraph.route("ticket-classifier"):return client.chat.completions.create(model="gpt-5.6-luna",messages=[{"role": "user", "content": ticket.body}],)route()is also a decorator, which is usually tidier when the whole function belongs to one surface:@metergraph.route("ticket-classifier")def classify(ticket):return client.chat.completions.create(...)src/llm.ts import * as mg from "metergraph";export async function classify(ticket: Ticket) {return mg.route("ticket-classifier", () =>client.chat.completions.create({model: "gpt-5.6-luna",messages: [{ role: "user", content: ticket.body }],}));} -
Run it again
Section titled “Run it again”Make at least one call through the newly routed path, then let the batch flush or call
flush(). -
Look at the dashboard
Section titled “Look at the dashboard”On Spend, the workload breakdown now carries
ticket-classifieras a row of its own, with its own call count, error count, latency percentiles and cost. The oldtemplate:group stops growing and keeps whatever it already collected. Nothing is rewritten: rows captured before the route existed keep the identity they were captured with.
That is the whole mechanism. A route is a label you attach at the call site, the server takes it verbatim, and everything downstream groups on it.
What the name buys you
Section titled “What the name buys you”A route is not decoration. Three things key off it.
Attribution. Spend, latency and error rate are reported per route, which is the only breakdown that survives a refactor. Function names move; a route name is something you chose.
Analysis. The engine evaluates one route at a time and calls it a workload. It picks the three eligible workloads with the most samples in the window and tests candidate models against each. A route that does not exist cannot be picked, and each workload needs a minimum number of traces before it can be analyzed at all. See run your first analysis.
Alerts. The cost-drift, failure-spike, latency-drift and retry-loop detectors compare a route against its own recent history. Splitting two unrelated surfaces into two routes is what stops one of them masking a regression in the other.
Naming them well
Section titled “Naming them well”Two rules carry most of the weight.
Name the job, never how the job is currently done. ticket-classifier is a
good name. gpt-5.6-luna is a bad one, because swapping the model erases the
history that justified swapping the model. So are app.services.tickets.classify
(that is the function, and you already have that column) and prod (that is an
environment, and there is a field for it).
Keep the count in the tens. Route cardinality should track your product
surfaces, not your traffic. user-8412 is a session ID wearing a route’s
clothes, and it produces thousands of groups of one.
The full table of names to copy and names to avoid, with the reason for each, is on the identity model.