# Cloudflare Workers' built-in traces and logs export to Belvador

> Two OTLP destinations in the Cloudflare dashboard, the observability block in wrangler.jsonc, what you get and the current limits.

Cloudflare Workers can export their own traces and logs to any OTLP endpoint — no SDK in your code. Cloudflare instruments each request, `fetch` and binding call and sends the result from its servers. You need access to the Worker's Cloudflare account; apps hosted by a platform that owns the account (such as Lovable) cannot set this up — see [TanStack Start](https://belvador.dev/en/docs/otel/tanstack-start).

> **Not tested yet:** this setup follows the vendor's documentation; Belvador has not run it end to end.

## 1. Create two destinations

In the Cloudflare dashboard, open **Observability → Destinations → Add destination** twice, once per signal. Use an [ingest key](https://belvador.dev/en/docs/otel/quickstart#1-create-an-ingest-key) with **Traces** and **Logs** and no environment restriction (Cloudflare sends no environment):

| Field | Traces destination | Logs destination |
|---|---|---|
| Destination name | `belvador-traces` | `belvador-logs` |
| Destination type | Traces | Logs |
| OTLP endpoint | `https://ingest.belvador.dev/otlp/<project-id>/v1/traces` | `https://ingest.belvador.dev/otlp/<project-id>/v1/logs` |
| Custom header | `Authorization: Bearer <ingest key>` | `Authorization: Bearer <ingest key>` |

Cloudflare wants the full URL of each signal, not the base endpoint.

## 2. Point the Worker at them

```jsonc
// wrangler.jsonc
{
  "observability": {
    "traces": {
      "enabled": true,
      "destinations": ["belvador-traces"],
      "head_sampling_rate": 0.1
    },
    "logs": {
      "enabled": true,
      "destinations": ["belvador-logs"],
      "head_sampling_rate": 1
    }
  }
}
```

Deploy again. `head_sampling_rate` keeps that share of requests (`0.1` = one in ten). Delivery can take a few minutes. Your `console.log` output is exported as log records.

## What you get

- **Service name** is the Worker's name; Cloudflare adds `cloud.provider`, `cloud.platform` and its own ids.
- **No environment**: records are stored with an empty one. Filter by service, or use one Worker name per environment.
- **Errors** still come from the [Belvador Workers SDK](https://belvador.dev/en/docs/sdk/cloudflare). Belvador has not checked whether Cloudflare's trace ids match the ones the SDK puts on errors, so treat the two as separate for now.

## Status

Cloudflare calls Workers tracing open beta: span and attribute names may change. Belvador accepts both OTLP encodings Cloudflare may send, but has not run this export end to end yet, so it is marked untested. Run the [connection check](https://belvador.dev/en/docs/otel/verify) after setup and look for your Worker under **Services seen**.
