# Log streams

A log stream sends the requests of one gateway environment to a destination outside Faustine, about 30 seconds after each request ends. You add streams under **Log streams** in the environment's **Log settings**. An environment can have up to 5 streams.

## How it works

The gateway sends requests in batches of up to 500 requests and 4 MB. A stream starts with the requests that end after you create it. Earlier requests are not sent.

A stream sends what the logs hold, after the environment's redaction. It never carries more than the log.

## Destinations

| Destination | What it receives | Guide |
| --- | --- | --- |
| Datadog | One log per request. | [Stream logs to Datadog](https://docs.faustine.ai/technologies/datadog/) |
| Splunk | One HTTP Event Collector event per request. | [Stream logs to Splunk](https://docs.faustine.ai/technologies/splunk/) |
| Grafana Cloud | One trace per request, over OTLP/HTTP. | [Stream logs to Grafana Cloud](https://docs.faustine.ai/technologies/grafana-cloud/) |
| Honeycomb | One trace per request, over OTLP/HTTP. | [Stream logs to Honeycomb](https://docs.faustine.ai/technologies/honeycomb/) |
| New Relic | One trace per request, over OTLP/HTTP. | [Stream logs to New Relic](https://docs.faustine.ai/technologies/new-relic/) |
| Amazon S3, DigitalOcean Spaces, Cloudflare R2, Google Cloud Storage, S3-compatible | One gzip NDJSON object per batch. | [Stream logs to Amazon S3 and S3-compatible storage](https://docs.faustine.ai/technologies/s3/) |
| OpenTelemetry | One trace per request to any OTLP/HTTP collector. | [Stream logs to an OpenTelemetry collector](https://docs.faustine.ai/technologies/opentelemetry/) |
| HTTPS endpoint | Signed batches posted to your own receiver. | [Stream logs to an HTTPS endpoint](https://docs.faustine.ai/technologies/https-endpoint/) |

A destination has to be a public `https://` host. Redirects are not followed.

## Add a stream

The wizard has four steps: **Destination**, a connect step named after the destination, such as **Connect Datadog**, **What to send** and **Review and create**. Each destination guide lists the fields of its connect step.

1. In the portal, go to [**Agent Gateway**](https://auth.faustine.ai/go?to=%2Fintegrations%2Fagent-gateway) and select your gateway.
2. Select the **Logs** tab, then **Log settings**.
3. Under **Log streams**, select **Add a stream**.
4. Under **Destination**, select the destination.
5. Fill in the fields and select **Send test event**. The test sends one sample request marked `test: true` and shows whether it was delivered.
6. Select **Continue**.
7. Under **What to send**, choose what the stream includes, then select **Continue**.
8. Under **Review and create**, enter a **Name** and select **Create stream**.

The stream's page opens. Its state is **Waiting for traffic** until the first request is sent, then **Delivering**.

## What a stream sends

| Option | What it does | Default |
| --- | --- | --- |
| **Requests** | **All requests**, or **Errors and denials**: errors, upstream errors, denials and requests waiting for a confirmation. | **All requests** |
| **Discovery calls** | Includes the calls where an agent looks up operations, such as `search_operations` and `get_operation`. | Off |
| **Payloads** | Includes arguments, results, scripts, console output and upstream bodies and headers, as stored. | Off |

If the environment records metadata only, there are no payloads to send. See [Set recording and retention](https://docs.faustine.ai/agent-gateway/retention/).

The **What to send** step shows a preview of your latest request in the format of the destination.

## The request document

Destinations that receive JSON get one document per request. Trace destinations get the same data as spans.

| Field | Content |
| --- | --- |
| `schema` | `faustine.gateway.request/v1` |
| `id`, `traceId`, `parentTraceId` | The request ID and its trace. |
| `startedAt`, `endedAt`, `durationMs` | Timing. |
| `gateway`, `env` | The `id`, `slug` and `name` of each. |
| `status`, `denyReason`, `errorType`, `errorMessage` | How the request ended. |
| `channel`, `kind`, `tool`, `opKey` | MCP or REST, and what was called. |
| `actor` | The credential: `kind`, `id`, `name`. |
| `client` | `hint`, `name`, `version`, `userAgent`, `ip`. |
| `calls` | Each operation the request ran, with its status, connection and timings. |
| `attempts` | Each exchange with your API: `method`, `url`, `status`, `durationMs`, `spanId`. |
| `payloads` | Present when the stream includes payloads. |

## Delivery

Delivery is at least once. A batch can arrive twice after a failure, so deduplicate by the request `id`.

| Behavior | Detail |
| --- | --- |
| Timeout | A delivery fails if the destination does not answer within 15 seconds. |
| Retries | A failed batch is retried after 10 seconds, 30 seconds, 1 minute and 5 minutes, then every 15 minutes. |
| Failing state | The stream's state is **Failing** from the first delivery that fails. Its page shows the answer it got and what it most likely means. After 3 failures in a row, Activity records that the stream is failing, and later that it recovered. |
| Give-up | Requests that ended more than 24 hours ago and were never accepted are skipped. The stream's page counts them. |
| **Pause** | Stops delivery. On **Resume** the stream sends the requests that ended meanwhile, up to 24 hours back. |

The stream's page lists every delivery of the last 7 days with its result, size and duration.

## Joined traces

For trace destinations, 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 traces with OpenTelemetry to the same backend, its own spans appear inside the gateway's trace.

## Next steps

- [Stream logs to an HTTPS endpoint](https://docs.faustine.ai/technologies/https-endpoint/): receive the batches yourself and verify their signature.
- [Stream logs to an OpenTelemetry collector](https://docs.faustine.ai/technologies/opentelemetry/): the span attributes of a request.
- [Redact sensitive fields](https://docs.faustine.ai/agent-gateway/redact-sensitive-fields/): decide what a stream can carry.
