Stream logs to an OpenTelemetry collector
An OpenTelemetry log stream sends each request of a gateway environment as one trace to a collector or backend that accepts OTLP over HTTP, about 30 seconds after the request ends.
Before you begin
- A collector with an OTLP/HTTP receiver, reachable from the internet over
https://. Faustine does not send to private addresses. See Collector configuration in the OpenTelemetry docs. - The headers the collector requires for authentication, if any.
The stream sends OTLP/HTTP with a JSON body. It does not send OTLP over gRPC.
Add the stream
- In the portal, go to Agent Gateway and select your gateway.
- Select the Logs tab, then Log settings.
- Under Log streams, select Add a stream.
- Under Destination, select OpenTelemetry.
- Fill in the fields in the table.
- Select Send test event. Faustine sends a trace of one request marked
test: trueand shows Delivered when the collector accepts it. - Select Continue.
- Under What to send, choose All requests or Errors and denials, and turn on Discovery calls or Payloads if you want them. Select Continue.
- Under Review and create, enter a Name and select Create stream.
| Field | Value |
|---|---|
| OTLP/HTTP endpoint | The address of the collector, such as https://otel.example.com:4318. Faustine adds /v1/traces. |
| Headers | Headers sent with every batch, such as Authorization. Optional, up to 10. The values are stored encrypted. |
| Service name | The service.name of the traces. Optional. Defaults to faustine-gateway. |
The stream's page opens. The first trace reaches the collector about 30 seconds after the next request ends.
What the collector receives
Each batch is one OTLP/HTTP request in JSON, posted to /v1/traces on the endpoint. A request is one trace.
| Span | Kind | Name | Main attributes |
|---|---|---|---|
| The request | Server | tools/call <tool> over MCP, REST <operation> over REST |
gen_ai.tool.name, mcp.method.name, mcp.session.id, faustine.request.id, faustine.request.status, faustine.actor.name, faustine.client.name |
| Each call | Internal | The operation key, such as crm.deals.get |
faustine.op.key, faustine.connection, faustine.call.status, faustine.upstream.status |
| Each exchange with your API | Client | The HTTP method, or <service>/<method> for gRPC |
http.request.method, url.full, http.response.status_code, server.address, or rpc.system, rpc.service, rpc.method |
The resource has service.name, deployment.environment.name (the environment's slug) and faustine.gateway.id, faustine.gateway.slug and faustine.gateway.name. A span that failed has the status ERROR and an error.type attribute. When the stream includes payloads, the request span has gen_ai.tool.call.arguments and gen_ai.tool.call.result, each cut at 8192 characters.
The span of each exchange with your API has the span ID the gateway sent to your API in the traceparent header. If your API sends its own traces to the same backend, its spans appear inside the gateway's trace.
The instrumentation scope is faustine.gateway. Each batch also has an X-Faustine-Delivery header that identifies it.
Other attributes
| Span | Attributes |
|---|---|
| The request | gen_ai.operation.name (execute_tool), jsonrpc.request.id, client.address, user_agent.original, faustine.request.kind, faustine.request.channel, faustine.deny_reason, faustine.op.key, faustine.actor.kind, faustine.actor.id, faustine.client.version, faustine.client.trace_id, faustine.client.request_id, faustine.run_execution.id |
| Each call | faustine.deny_reason, faustine.upstream.ms, faustine.recipe, faustine.replayed, and with payloads faustine.call.input and faustine.call.output |
| Each exchange with your API | server.port, rpc.grpc.status_code, faustine.attempt.purpose, faustine.attempt.number, faustine.upstream.request_id |
An exchange that signed in to your API has (sign-in) after its name. An attribute without a value is left out.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| The test shows "Log streams only reach public hosts." | The endpoint resolves to a private or reserved address. | Expose the collector on a public address with TLS. |
| The test shows "Nothing at that path" | The endpoint already has a path the collector does not serve. | Enter the base address. Faustine adds /v1/traces unless the URL already ends with it. |
| The test shows "The destination rejected the credentials" | The collector requires a header that is missing or wrong. | Add it under Headers. |
Next steps
- Log streams: delivery, retries and the fields of a request.
- Redact sensitive fields: decide what a stream can carry.
- Set recording and retention: record the payloads a stream sends.
Last updated November 11, 2026