Deno's built-in OpenTelemetry
Turn on OTEL_DENO so Deno creates spans for Deno.serve and fetch and sends console output as logs; the no-retry limitation and how to work around it.
On this page
Deno 2 has OpenTelemetry built in. With one variable it creates a server span for every Deno.serve request, a client span for every fetch, sends console.* output as log records with the active trace id, and exports with the standard variables. No packages to install.
Tested on 2026-10-24 with deno 2.6.10: traces passed, logs passed, logs carry the request's trace and span. Proven limitation: no retry on 429/503.
Run#
export OTEL_DENO=truedeno run --allow-net --allow-env main.tsDeno 2.2 and 2.3 also needed the --unstable-otel flag; current versions do not.
Logs#
console.log becomes an INFO record, console.warn a WARN record and console.error an ERROR record, each with the trace id and span id of the request it ran in. Output still goes to the terminal as before.
Limitation: no retry#
Belvador's run shows that Deno's built-in exporter does not send a batch again after a 429 or 503 answer — that batch is lost. Belvador answers those codes only when your quota or rate limit is reached or the edge is briefly unable to take data, but if losing a batch then matters, run a local Collector next to the app and point Deno at it; the Collector queues and retries:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318unset OTEL_EXPORTER_OTLP_HEADERS # the Collector holds the Belvador keyThis check runs on every certification, so the note disappears when Deno starts retrying.
Deno Deploy#
Deno Deploy configures its own telemetry; sending it to Belvador has not been tested.
Spotted something wrong or missing? Tell us: hello@belvador.dev