Cloudflare Workers observability: logs and traces
By Flavio Copes
Learn how to see what your Cloudflare Worker does in production using console.log, observability in wrangler.jsonc, and live tailing with wrangler tail.
Code that runs on someone else’s servers can feel like a black box. When something breaks in production, you need to see what happened.
Cloudflare Workers have observability built in: logs you can search, live tailing, and traces. Let me show you how I keep an eye on things.
Just use console.log
The simplest tool is the one you already know. console.log works in a Worker, and the output is captured for you:
export default {
async fetch(request, env) {
console.log('Handling', request.url)
try {
// ... your code ...
} catch (err) {
console.error('Something broke:', err)
}
return new Response('ok')
},
}
console.error is good for problems, console.log for everything else.
Turn on observability
To keep your logs so you can search them later, enable observability in wrangler.jsonc:
{
"observability": {
"enabled": true,
"logs": { "enabled": true }
}
}
Now your logs are stored and searchable in the Cloudflare dashboard. You can filter by status, by message, by time. When a user reports a bug, you go look at what actually happened.
Watch logs live
When you’re actively debugging, you don’t want to refresh a dashboard. Stream the logs straight to your terminal:
npx wrangler tail
Every request and every console.log from your live Worker shows up as it happens. I keep this running in a terminal while I test a change in production.
You can filter, for example to only see errors:
npx wrangler tail --status error
Sampling for high traffic
If your Worker handles a lot of requests, logging every single one gets noisy and adds up. You can sample: keep a fraction of them.
{
"observability": {
"enabled": true,
"logs": { "enabled": true, "head_sampling_rate": 1 },
"traces": { "enabled": true, "head_sampling_rate": 0.01 }
}
}
head_sampling_rate is a number from 0 to 1. 1 keeps everything. 0.01 keeps 1%.
I keep logs at 1 so I never miss an error, and traces at 0.01, since a small sample is enough to spot performance patterns.
Traces
That traces setting unlocks the other half of observability. A trace shows the timeline of a single request: how long the database query took, how long an external call took, where the time went.
Logs tell you what happened. Traces tell you why it was slow. Together they cover most of what you need to debug a live app.
My habit
I turn observability on from the very first deploy. It costs nothing to set up, and the day something goes wrong, having searchable logs and wrangler tail ready is the difference between a five-minute fix and an afternoon of guessing.
The full reference is in the observability docs.
Related posts about cloudflare: