> ## Documentation Index
> Fetch the complete documentation index at: https://keyring.docs.composio.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Set up telemetry delivery

> Send Keyring audit events, logs, traces, and metrics through a collector or direct OTLP endpoint.

Set up telemetry delivery before connecting a production project to Keyring. Keyring uses this path to
record credential use and give your team the evidence needed to investigate a request.

<Warning>
  Production deployments should use `AUDIT_DURABILITY=required`. A protected response is released
  only after the configured OTLP logs endpoint acknowledges its audit event.
</Warning>

## Choose a delivery path

<CardGroup cols={2}>
  <Card title="OpenTelemetry Collector" icon="waypoints" href="#recommended-open-telemetry-collector">
    Recommended. Keep the acknowledgment path close to Keyring, then let the collector handle vendor
    authentication, queuing, retries, and routing.
  </Card>

  <Card title="Direct OTLP endpoint" icon="cloud-upload" href="#direct-vendor-endpoint">
    Fewer components, but vendor latency and availability become part of the protected request path.
  </Card>
</CardGroup>

| Path             | Best fit                                       | Main tradeoff                                 |
| ---------------- | ---------------------------------------------- | --------------------------------------------- |
| Local collector  | ECS, Cloud Run, Kubernetes, and Docker         | One small service or sidecar to operate       |
| Shared collector | Organizations with an observability platform   | Requires a private, reliable network path     |
| Direct endpoint  | Serverless platforms that cannot run a sidecar | External intake is on the acknowledgment path |

## What Keyring expects

`OTEL_COLLECTOR_URL` is a base URL. Keyring sends OTLP/HTTP Protobuf to:

* `<base>/v1/logs` for logs and acknowledged audit events;
* `<base>/v1/traces` for traces; and
* `<base>/v1/metrics` for metrics.

In required mode, the logs endpoint must return a synchronous 2xx response. Redirects do not count as
acknowledgment. Keyring retries retryable failures up to three times, with a two-second limit on each
attempt, before withholding the protected response.

## Recommended: OpenTelemetry Collector

Run the collector beside Keyring whenever your platform supports a sidecar or nearby service. For ECS,
Cloud Run multi-container services, and Kubernetes pods, both containers can communicate over
`127.0.0.1` without exposing the collector receiver publicly.

Configure Keyring with the local collector base URL:

```bash Keyring environment theme={"theme":{"light":"github-light","dark":"github-dark"}}
AUDIT_DURABILITY=required
OTEL_COLLECTOR_URL=http://127.0.0.1:4318
```

Use this as a starting collector configuration. Replace the exporter endpoint and header with values
from your observability provider:

```yaml otel-collector.yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
extensions:
  file_storage:
    directory: /var/lib/otelcol

receivers:
  otlp:
    protocols:
      http:
        endpoint: 127.0.0.1:4318

exporters:
  otlp_http/vendor:
    endpoint: ${env:VENDOR_OTLP_ENDPOINT}
    headers:
      Authorization: "Bearer ${env:VENDOR_OTLP_TOKEN}"
    retry_on_failure:
      enabled: true
      max_elapsed_time: 0s
    sending_queue:
      enabled: true
      storage: file_storage

service:
  extensions: [file_storage]
  pipelines:
    logs:
      receivers: [otlp]
      exporters: [otlp_http/vendor]
    traces:
      receivers: [otlp]
      exporters: [otlp_http/vendor]
    metrics:
      receivers: [otlp]
      exporters: [otlp_http/vendor]
```

Mount `/var/lib/otelcol` on storage that matches your recovery requirements. Keep provider credentials
on the collector, not in the Keyring container. This configuration uses `file_storage` from the
Collector Contrib distribution. Pin a reviewed
[OpenTelemetry Collector distribution and version](https://opentelemetry.io/docs/collector/installation/)
instead of tracking a floating image tag.

The logs pipeline intentionally sends directly to the exporter's persistent queue. Do not add an
in-memory batch processor in front of that queue without reviewing how it changes acknowledgment and
recovery behavior.

<Note>
  The receiver address above is for a sidecar that shares Keyring's network namespace. A standalone
  collector should use a private listener protected by network policy and TLS.
</Note>

## Direct vendor endpoint

Use a direct endpoint only when it accepts OTLP/HTTP Protobuf on all three standard paths. The logs
endpoint must return a final 2xx response quickly enough to sit on the protected request path.

Keyring treats that 2xx response as the acknowledgment. Confirm the provider's intake and retention
semantics meet your audit requirements.

Store `OTEL_COLLECTOR_HEADERS` as a secret. It uses comma-separated `Name=value` pairs, with spaces and
other reserved characters percent-encoded.

<Tabs>
  <Tab title="Datadog">
    Datadog recommends an Agent or OpenTelemetry Collector for production. Its direct OTLP intake is a
    fallback when a collector is not feasible and may require signal-specific settings.

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    AUDIT_DURABILITY=required
    OTEL_COLLECTOR_URL=https://otlp.datadoghq.com
    OTEL_COLLECTOR_HEADERS=dd-api-key=<DATADOG_API_KEY>
    ```

    The example is for Datadog US1. Select the endpoint for your Datadog site and review its current
    [direct OTLP intake requirements](https://docs.datadoghq.com/opentelemetry/setup/otlp_ingest/).
  </Tab>

  <Tab title="Dash0">
    Copy the regional ingress base URL and an ingest token from your Dash0 organization settings.

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    AUDIT_DURABILITY=required
    OTEL_COLLECTOR_URL=https://ingress.<REGION>.<CLOUD>.dash0.com
    OTEL_COLLECTOR_HEADERS=Authorization=Bearer%20<DASH0_AUTH_TOKEN>,Dash0-Dataset=<DATASET>
    ```

    Do not add `/v1/logs` to the base URL. Keyring adds the signal path. See Dash0's
    [endpoint guidance](https://www.dash0.com/docs/dash0/miscellaneous/glossary/endpoints).
  </Tab>

  <Tab title="Other OTLP provider">
    Confirm that one base URL accepts logs, traces, and metrics before using it here:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    AUDIT_DURABILITY=required
    OTEL_COLLECTOR_URL=https://otlp.example.com
    OTEL_COLLECTOR_HEADERS=Authorization=Bearer%20<INGEST_TOKEN>
    ```

    A trace-only endpoint is not sufficient. Put an OpenTelemetry Collector in front of providers that
    use different hosts, paths, protocols, or credentials for each signal.
  </Tab>
</Tabs>

## Verify before enabling a project

1. Start Keyring and confirm there are no collector configuration errors.
2. Run one read-only tool call through a test Composio project.
3. Find `service.name=keyring` and an `audit.operation` record in your telemetry backend.
4. Join the audit event to its logs and trace using the Keyring request ID.
5. In a test environment, interrupt telemetry delivery and confirm Keyring does not release a
   protected success response.

`best_effort` keeps requests moving without acknowledged audit delivery. Use it only for local
evaluation or when your organization has explicitly accepted that production risk.

For the event fields and security guarantees, see [Audit and observability](/security/audit_and_observability).
