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

# Cloudflare Workers

> Add OTLP log and trace destinations in Cloudflare Workers Observability settings and opt each Worker in via wrangler config to stream telemetry to Sazabi.

[All Cloudflare integration capabilities](https://docs.sazabi.com/catalogs/integrations/cloudflare)

## About

Stream console output and OTLP traces from your Cloudflare Workers directly to Sazabi using Cloudflare's native Workers Observability feature. You configure OTLP destinations at the account level and then opt each Worker in through its `wrangler.jsonc` or `wrangler.toml` configuration.

Cloudflare Logpush datasets (HTTP requests, Firewall events, DNS logs) come from a separate source. See [Cloudflare](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/cloudflare.md) for that setup.

### Cloudflare Sandbox and Containers

[Sandbox SDK](https://developers.cloudflare.com/sandbox/) and [Containers](https://developers.cloudflare.com/containers/) apps run behind a Worker and a Durable Object, so part of their logging already flows through this source.

* **Included:** `console.log` output from the Worker and the Durable Object, and the Sandbox SDK's own structured events. These are ordinary Workers logs, so they reach Sazabi once the Worker that hosts the sandbox lists `sazabi-logs` under `observability.logs.destinations`.
* **Not included:** stdout and stderr of processes running inside the container. Cloudflare shows them in its dashboard but documents no OpenTelemetry export for them. Its [Containers FAQ](https://developers.cloudflare.com/containers/faq/#how-do-container-logs-work) mentions Logpush export without naming a dataset, so the [Cloudflare Logpush source](https://docs.sazabi.com/catalogs/log-sources/connect-your-account/cloudflare.md) cannot select one. The Sandbox SDK's events also [leave out command output](https://github.com/cloudflare/sandbox-sdk/pull/926).

To capture process output, read it in the Worker or Durable Object and log it with `console.log`. Log an object rather than a string so the fields stay [structured](https://developers.cloudflare.com/workers/observability/logs/workers-logs/#logging-structured-json-objects).

With Sandbox SDK 0.x, follow a background process with [`streamProcessLogs()`](https://developers.cloudflare.com/sandbox/sdk/api/commands/#streamprocesslogs):

```ts theme={"system"}
import { getSandbox, parseSSEStream, type LogEvent } from "@cloudflare/sandbox";

const sandbox = getSandbox(env.Sandbox, "my-sandbox");
const proc = await sandbox.startProcess("node server.js");
const stream = await sandbox.streamProcessLogs(proc.id);
for await (const log of parseSSEStream<LogEvent>(stream)) {
  console.log({ sandbox: "my-sandbox", processId: proc.id, output: log.data });
}
```

With the [Container API](https://developers.cloudflare.com/containers/api/durable-object-container/#exec) that `@cloudflare/sandbox` 1.0 uses, read the `stdout` stream of `exec()` inside your Durable Object:

```ts theme={"system"}
const process = await this.ctx.container!.exec(["node", "job.js"], {
  stderr: "combined",
});
for await (const output of process.stdout!.pipeThrough(
  new TextDecoderStream(),
)) {
  console.log({ pid: process.pid, output });
}
```

`stderr: "combined"` merges standard error into `stdout`, so one loop reads both.

## Prerequisites

* Cloudflare Workers Observability access on your Cloudflare account
* Your Sazabi OTLP intake URLs for logs and traces (shown above)
* Workers deployed via Wrangler

## Set up in the dashboard

**Step 1**

### Open Workers Observability in the Cloudflare dashboard

In the Cloudflare dashboard, navigate to **Workers & Pages > Observability > Telemetry > Add Destination**.

**Step 2**

### Add a logs destination

Create a new destination with the following settings:

* **Destination type:** Logs
* **Name:** `sazabi-logs`
* **Endpoint:** your Sazabi OTLP logs intake URL (shown above, ending with `/v1/logs`)

**Step 3**

### Add a traces destination

Create a second destination with the following settings:

* **Destination type:** Traces
* **Name:** `sazabi-traces`
* **Endpoint:** your Sazabi OTLP traces intake URL (shown above, ending with `/v1/traces`)

**Step 4**

### Opt each Worker in via wrangler config

In each Worker's `wrangler.jsonc` or `wrangler.toml`, enable Workers observability and list the log and trace destination names you created (`sazabi-logs` and `sazabi-traces`):

```jsonc theme={"system"}
{
  "observability": {
    "logs": {
      "enabled": true,
      "destinations": ["sazabi-logs"],
      // optional: send to Sazabi without also storing logs in Cloudflare
      "persist": false
    },
    "traces": {
      "enabled": true,
      "destinations": ["sazabi-traces"]
    }
  }
}
```

`persist` defaults to `true`. From December 1, 2026, logs and traces that Cloudflare also stores count toward Cloudflare Observability usage. See Cloudflare's [OpenTelemetry export](https://developers.cloudflare.com/workers/observability/opentelemetry-export/) reference.

**Step 5**

### Redeploy each Worker

Run `wrangler deploy` for each Worker whose configuration you updated. Workers Observability takes effect on the next deployment.

**Step 6**

### Hand off the change

Commit these changes on a new branch, push it, and open a pull request. Keep the intake URL and any keys in environment variables or a secret store, and commit only configuration that references them.

## Set up with the CLI

You can also register the Cloudflare Workers log source with the [Sazabi CLI](https://docs.sazabi.com/reference/cli.md) (installed and authenticated — see [CLI reference](https://docs.sazabi.com/reference/cli/log-sources.md)).

Registering the source mints the same intake URL the dashboard shows above (the public key is embedded in its hostname):

```bash theme={"system"}
sazabi log-sources create cloudflare_workers --mode manual
```

The command prints the intake URL for the new source — copy the whole URL and point your sender at it using the configuration shown above. Run `sazabi log-sources get <log-source-id>` at any time to reprint the endpoint, or `sazabi log-sources list` to see every log source in the project.

## Verify

Invoke a Worker that you opted in (for example, make an HTTP request to its route). Open the [Intake page](https://docs.sazabi.com/guides/instrument/intake.md) in the Sazabi dashboard and confirm logs or traces from the **Cloudflare Workers** source appear within a minute or two.

## Troubleshooting

**No telemetry after redeploying** — Confirm the Worker's `wrangler.jsonc`/`wrangler.toml` enables observability and lists the destination names, and that those names match exactly what you created in the Cloudflare dashboard (case-sensitive).

**Logs appear but traces do not** — Verify both the logs and traces destinations are created in the Cloudflare dashboard and both destination names appear in the Worker's `wrangler` config.

**Destination not found error** — Destinations are account-scoped. Confirm you created the destination in the same Cloudflare account that owns the Workers you are configuring.

## Further reading

> [card] [Intake](https://docs.sazabi.com/guides/instrument/intake.md)
>
> See per-source ingestion volume and health.

> [card] [Log sources](https://docs.sazabi.com/catalogs/log-sources.md)
>
> Browse the full log source catalog.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.