application.id; Fiddler authorizes every span against the applications your key is allowed to write to, stores the authorized ones under the right application, and reports the rest back to you.
Overview
In the single-application flow (Exporting OTel Traces to Fiddler), each request targets one application — you set afiddler-application-id header and every span in that request lands in that one application.
Multi-application routing removes that one-application-per-request limit. A single stream can mix spans for any number of applications, and Fiddler does the routing for you:
- One endpoint, one API key. A shared gateway or collector fronting many applications sends everything to the same
/v1/tracesendpoint with a single API key — no per-application pipeline, and no separate key wired in per application. - No routing infrastructure to build or run. You do not stand up and maintain your own collector or configure routing connectors to split traffic by application. You tag each span with its
application.id— one attribute, set once in your emitter’s config — and Fiddler handles the routing server-side. - Authorization-aware routing. Fiddler verifies each span’s
application.idagainst the applications your API key is permitted to write to, and rejects the rest — so a span can never reach an application your API key cannot write to. This bounds routing to your API key’s scope; it does not isolate a shared gateway’s callers from each other — see Trust Model and Caller-Supplied Application IDs. - Everything in one call. Authorized and unauthorized spans can coexist in the same batch; the authorized ones are ingested and the unauthorized ones are reported back in the response.
How It Works
Tag each span with its application
application.id on each span (or on its resource, when a whole ResourceSpans belongs to one application). One batch can contain spans for many different applications.Send with one API key
/v1/traces with a single Authorization: Bearer <YOUR_API_KEY> header. No fiddler-application-id header is used in this flow — routing is driven by each span’s application.id.Fiddler authorizes each span
application.id against that set — no single application is declared up front.Authorized spans are stored, the rest are reported
partialSuccess block whenever any span is rejected — see The partialSuccess Response. Authorized spans in the same batch are still ingested.
fiddler-application-id header) and Fiddler answers a single yes/no. Multi-application routing instead authorizes against your API key’s full set of permitted applications and matches each span’s application.id against it. Nothing is declared up front, so one API key serves every application it is allowed to write to.Prerequisites
- One or more Fiddler applications created — you will need each Application UUID.
- A valid Fiddler API key (from Settings > Credentials) whose user has write access to each application you intend to send to. Access is governed by your role assignments — see Access Control.
- Multi-application routing enabled on your Fiddler deployment.
How the Application ID Reaches Each Span
This is the question every shared-pipeline setup has to answer, so it is worth stating plainly. The component that emits telemetry — a gateway, a collector, an egress service — is usually not the component that knows which Fiddler application a request belongs to. The caller knows that. So the application ID has to travel from the caller, through the emitter, and onto each span as theapplication.id attribute. Where and how you set it depends on what is emitting the spans:
- One application per process (an instrumented service) — set
application.idon the resource, via an environment variable or the SDK. See One Application per Process. - Many applications from one process (a gateway, or a service that switches application per request) — set
application.idper span. See Many Applications from One Process. - A batch or replay pipeline — set
application.idas you assemble each span; see the protobuf example below.
Resource or Span by Topology
Fiddler resolves each span’s application resource-preferred, span-fallback: a resource-levelapplication.id decides for every span under it, a span-level application.id is used only when the resource sets none, and a span with neither fails closed (rejected as unauthorized). Which level you set depends on your topology — and for the shared-pipeline case this page targets, resource-level is the wrong choice:
- One application per process (an instrumented service) — an OpenTelemetry
TracerProvidercarries exactly oneResource, so a resource-levelapplication.idtags every span the process emits with the same application. That is correct when a process serves one application — the single-application flow. - Many applications from one process (a gateway, collector, or shared exporter — what this page is about) — set
application.idper span, and do not set it on the resource.
Setting application.id
One Application per Process
When a process serves a single application, setapplication.id on the resource. The cheapest form is environment variables — no code — and works with any OpenTelemetry SDK:
Resource helper (rather than hand-building protobuf):
Many Applications from One Process
When one process emits spans for several applications — a gateway, or a service that switches application per request — setapplication.id per span and leave it off the resource (see the trap above).
With the OpenTelemetry SDK, set it on each span as you create it, and do not put application.id on the Resource:
gen_ai.conversation.id:
- Move
application.idout ofresourcesand intoattributes. The single-application config setsresources.application.idto a fixed value; leaving it there pins every span to one application (resource beats span) and the header is ignored. - Drop the
fiddler-application-idrequest header that the single-application config adds viarequestHeaderModifier. On a multi-application deployment that header is ignored, so it is dead config — removing it is a cleanup, not a correctness fix.
X-Fiddler-Application-Id: <APPLICATION_UUID> (exactly as it already sends X-Fiddler-Conversation-Id).
Assembling batches as protobuf (pipelines, replay, ETL)
Assembling batches as protobuf (pipelines, replay, ETL)
ResourceSpans with that application’s application.id on the resource (here a resource-level value is correct, because each ResourceSpans belongs to exactly one application), and send the whole batch with one API key.AnyValue helper, see Exporting OTel Traces to Fiddler and Span and Resource Attributes.Producer Support
Any producer that can setapplication.id per span can drive multi-application routing. Today that is:
application.id (whether sent as a header or in request metadata) is captured only inside namespaced metadata attributes such as metadata.requester_custom_headers, which Fiddler resolves after the routing decision has already been made. Routing keys off the bare application.id at ingest, and LiteLLM never sets that per request — so a per-request application ID cannot influence which application a span lands in. (This is the same reason per-request gen_ai.conversation.id works but application.id does not: a conversation ID is a display field resolved late in the pipeline, while an application ID is a routing field needed at ingest — same transport, different timing.) Use LiteLLM for single-application export: set one application.id for the proxy via OTEL_RESOURCE_ATTRIBUTES. Per-request routing through LiteLLM would require a Fiddler-supplied callback that sets application.id at emit time — contact your Fiddler Customer Success Manager if you need it.Migrating from the Single-Application Header
Trust Model and Caller-Supplied Application IDs
Multi-application routing authorizes the API key, not the caller. Fiddler checks each span’sapplication.id against the applications your API key is permitted to write to, and rejects the rest. This protects Fiddler’s boundary between tenants: a caller cannot route a span to an application your API key has no access to.
It does not, on its own, isolate a shared gateway’s callers from one another. The application.id on a span is caller-supplied input, and an API key that can write to many applications can write to any of them — so any caller of that gateway can tag a span as any application the gateway’s API key can reach. If a shared gateway must keep its own callers in separate applications, enforce that at the gateway — for example, derive the application ID from an authenticated caller identity rather than trusting a raw client header. Per-span authorization protects Fiddler’s tenancy boundary, not the gateway’s internal one.
The partialSuccess Response
When every span is authorized, the response is a plain200 with an empty body. When one or more spans are rejected, Fiddler still returns 200 and populates the standard OTLP partialSuccess block:
Access Control
Authorization is per span: Fiddler compares each span’sapplication.id against the set of applications the API key’s user is allowed to write to. A span is stored only if its application is in that set; otherwise it is rejected and reported in partialSuccess.
To let an API key send to an application, ensure its user has a role that grants write access to that application’s project. See Role-Based Access Control for the available roles, and API Keys for creating and managing API keys.
Frequently Asked Questions
How does the application ID get onto a span through a gateway?
How does the application ID get onto a span through a gateway?
application.id attribute. For AgentGateway this is a one-line CEL expression — see Many Applications from One Process. The gateway itself does not know which application a request belongs to; the caller does.Do I still need the fiddler-application-id header?
Do I still need the fiddler-application-id header?
application.id and the header is ignored. The single-application fiddler-application-id header still works for one-application-per-request exports on deployments without multi-application routing.Resource-level or span-level application.id — which wins?
Resource-level or span-level application.id — which wins?
ResourceSpans sets application.id on its resource, that value applies to every span under it; the span-level attribute is a fallback used only when the resource does not set one. From a shared emitter, set it per span so one process can route to many applications — see the trap above.What if a span has no application.id at all?
What if a span has no application.id at all?
rejectedSpans.What if application.id is malformed, or names an application that doesn't exist?
What if application.id is malformed, or names an application that doesn't exist?
rejectedSpans and named in errorMessage. Fiddler matches each span’s application.id against the set of applications your API key can write to; a well-formed UUID that no application matches, or a value that isn’t a valid UUID at all, is simply not in that set (Fiddler does not validate UUID format at ingest). Only a missing or empty application.id behaves differently — it fails closed (see the previous question).Why is every span coming back rejected?
Why is every span coming back rejected?
application.id (or header-only setup) is overriding the per-span value. Verify the API key’s roles, confirm the capability is enabled with your Fiddler Customer Success Manager, and check that application.id is set per span.