Skip to main content
Request records always stay in your organization’s own database. Log destinations sends a copy to your own systems as well: spans to an OpenTelemetry collector, and Parquet files to a storage bucket. Neither ever carries prompt or response text. Open Logs and choose Log destinations in the table’s toolbar. Make your changes and choose Save changes.

OpenTelemetry

Log destinations panel with Add destination and the OpenTelemetry collector endpoint and headers

Log destinations: a storage bucket and an OpenTelemetry collector.

  1. Store your collector’s headers, such as its API key, as a secret in Secrets (Platform > Agents > Secrets). The value is JSON, such as {"api-key": "..."}, or key=value pairs separated by commas.
  2. In Log destinations, under OpenTelemetry, turn on Send traces to a collector.
  3. Enter the collector’s Endpoint. The gateway sends OTLP over HTTP (JSON), so use the collector’s HTTP port, usually 4318. /v1/traces is added when the URL has no path.
  4. Under Headers, pick the secret from step 1.
  5. Choose Save changes.
Only OTLP over HTTP is supported. A gRPC endpoint (usually port 4317) receives nothing. If a collector was saved for gRPC, it shows This collector was saved for gRPC. Point the endpoint at the HTTP port and save again.

What each span carries

One span per request, named with the OpenTelemetry GenAI conventions:
  • the provider, the model asked for and the model that answered
  • input, output, cache and reasoning tokens, and the cost in USD
  • timings: start and end, time to first token and total time
  • IDs: trace, person, group, agent, task and conversation, the API key’s name, the client and its version, what started the call, and the license model
  • the status, and the error type of a failed call
A span never carries prompt or response text, an email address, or an error’s text. The calls of one agent run or coding session share one trace ID, so they show as one trace in your observability backend. Spans are sent every 30 seconds, about 2 minutes after the request, so a request reaches your collector within roughly two and a half minutes. A new collector receives requests from the moment you save it. Earlier requests are not sent. When the collector is unreachable, sending pauses and resumes where it stopped, without losing requests. The endpoint must be reachable from where your agents run: a public address on xpander cloud, or an address your cluster can reach on a self-hosted install.

Coralogix

  1. In Coralogix, create a Send-Your-Data API key.
  2. In xpander, create a secret with this JSON value:
    The application and subsystem names are yours to choose; they are how the spans are grouped in Coralogix.
  3. Set Endpoint to https://ingress.<your Coralogix domain>/v1/traces, such as https://ingress.eu2.coralogix.com/v1/traces.
  4. Pick the secret under Headers and choose Save changes.
The spans arrive in Coralogix as traces with the service name xpander-llm-gateway, under the application and subsystem names you set.

Other collectors

Any backend that accepts OTLP over HTTP works the same way: its OTLP HTTP endpoint, and its authentication headers in the secret.

Storage bucket

A copy of every request record, as Parquet files in your own Amazon S3 bucket, Google Cloud Storage bucket or Azure Blob Storage container.

1. Store a credential

Create a secret in Secrets (Platform > Agents > Secrets) holding a credential that can write to the bucket: Log export does not support AWS IAM roles. Use an access key.

2. Add the destination

  1. In Logs, choose Log destinations.
  2. Under Destination, choose Add destination and pick Amazon S3, Google Cloud or Azure Blob Storage.
  3. Fill in the fields:
  1. Choose Send test. It writes <prefix>/_xpander_test.json with the settings on screen, saved or not. Test row written means the export can write there. The test failed says why, for example:
    • the bucket does not exist;
    • the bucket is in another region, naming the region it is in;
    • the key may not write to the bucket (access denied);
    • the provider did not accept the key;
    • the storage endpoint is at an address the export does not write to: a metadata address, or, on xpander cloud, a private or cluster address.
  2. Choose Save changes.
Turn off stops the copy. Requests stay in your organization’s database either way.

What lands in the bucket

Parquet files under <prefix>/dt=YYYY-MM-DD/hour=HH/, split by the hour of the call (UTC), one row per request. A request arrives within about two minutes of the call. Export starts from the moment you save the destination: earlier requests are not sent, and changing the bucket or prefix starts again from that moment. When the bucket can’t be written, the export pauses and resumes where it stopped, without losing or duplicating rows. Each row has these columns: Rows never hold prompt or response text, email addresses, IP addresses or error text. Keep requests for in Policies does not delete exported files. To delete old files, set a lifecycle rule on your bucket.

Self-hosted installs

On a Hybrid or Air-Gapped install, both destinations are sent from inside your install, so the collector and the bucket only need to be reachable from your cluster. An Air-Gapped install can use S3-compatible storage inside your network through endpoint_url in the credential.