# Traces and logs with OpenTelemetry

> Belvador takes OTLP traces and logs from standard OpenTelemetry SDKs, stores them on your node and links them to errors; metrics when you turn them on; which runtimes are tested and what is not collected.

Errors tell you *that* something broke. **Traces** show the path one request took — which service called which, what each step cost — and **logs** show what your code said along the way. Belvador takes both from the standard [OpenTelemetry](https://opentelemetry.io) SDKs your services may already use, over OTLP/HTTP, and keeps them on your own node next to your errors.

| You want to see… | Use |
|---|---|
| A request's path across services and where the time went | Traces (this section) |
| What the code logged during that request | Logs (this section) |
| A number over time — request rate, memory, queue depth | [Metrics](https://belvador.dev/en/docs/otel/metrics) |
| The exception, stack trace and how often it happens | Error tracking ([quickstart](https://belvador.dev/en/docs/quickstart)) |
| A scheduled job that did not run | [Monitors](https://belvador.dev/en/docs/monitors/overview) |

## What you get

- **Traces** — a list of traces and spans with a time histogram, filters by project, environment, service and time, and a waterfall of every span in one trace with its attributes and events.
- **Logs** — search by text, service, environment, severity or trace id, and open the lines written just before and after one line.
- **Links to errors** — an issue shows **Logs around this error**: the logs of the error's trace when the error carries a trace id, otherwise the same project and environment around that moment. An error event and the trace it happened in share a trace id, so you can move between them.
- **Connection evidence** — the project's **Connection** tab lists which services sent traces or logs, with which SDK, and when last.

## What it is not

- **Metrics are opt-in.** Belvador stores OTLP metrics (one point a minute) when you turn them on — see [Metrics](https://belvador.dev/en/docs/otel/metrics). The standard variables leave them off.
- **No browser tracing.** Ingest keys are secret: send traces and logs from servers, workers and the Collector, never from code that runs in a browser.
- **No full APM.** There are no service maps, profiling or session replay. Traces and logs are kept for debugging, for a limited time (see [Sampling and cost](https://belvador.dev/en/docs/otel/sampling-and-cost)).

## Tested runtimes

Belvador runs a real application on each runtime below against a complete local copy of its pipeline (edge, relay, node and storage) and reads every span and log back. A runtime is marked *tested* only when that run passes: one trace with a server and a client span, one log line with the right severity and the request's trace id, no secret from the request stored, exporter retry after a `503`, and — on the reference runtime — wrong key rejected, two minutes with the node offline without loss, and an app that keeps answering when Belvador is unreachable.

| Runtime | Traces | Logs | Tested with |
|---|---|---|---|
| [Node.js (OpenTelemetry, CJS + ESM)](https://belvador.dev/en/docs/otel/node) | Automatic · tested | Automatic · tested · linked to traces | node 22.23.4, @opentelemetry/sdk-node 0.300.0, @opentelemetry/auto-instrumentations-node 0.82.0, pino 10.4.0 (2026-10-24) |
| [Python (OpenTelemetry)](https://belvador.dev/en/docs/otel/python) | Automatic · tested | Automatic · tested · linked to traces | python 3.12.15, opentelemetry-distro 0.66b1, opentelemetry-sdk 1.45.1, flask 3.1.3 (2026-10-25) |
| [Go (OpenTelemetry)](https://belvador.dev/en/docs/otel/go) | You call it · tested | You call it · tested · linked to traces | go 1.27.3, go.opentelemetry.io/otel v1.47.0, otelhttp v0.72.0, otelslog v0.21.0 (2026-10-24) |
| [Java (OpenTelemetry Java agent)](https://belvador.dev/en/docs/otel/java) | Automatic · tested | Automatic · tested · linked to traces | java 21.0.12.1, opentelemetry-javaagent 2.32.0 (2026-10-24) |
| [Deno (built-in OpenTelemetry)](https://belvador.dev/en/docs/otel/deno) | Automatic · tested · no retry on 429/503 | Automatic · tested · linked to traces · no retry on 429/503 | deno 2.6.10 (2026-10-24) |
| [OpenTelemetry Collector](https://belvador.dev/en/docs/otel/collector) | You call it · tested | You call it · tested | otelcol-contrib 0.163.1, telemetrygen v0.163.0 (2026-10-27) |
| [Cloudflare Workers (built-in OTLP export)](https://belvador.dev/en/docs/otel/cloudflare-workers) | Automatic · untested, planned | Automatic · untested, planned | — |
| [Vercel (Trace Drains)](https://belvador.dev/en/docs/otel/nextjs-vercel) | Automatic · untested, planned | Not possible | — |
| [Supabase (OTLP log drain)](https://belvador.dev/en/docs/otel/supabase-log-drains) | Not possible | Automatic · untested, planned | — |

Other languages (.NET, Ruby, PHP, Rust, Bun) work the same way — any OpenTelemetry SDK that exports OTLP/HTTP reads the [same variables](https://belvador.dev/en/docs/otel/quickstart#2-set-the-standard-variables) — but Belvador has not run them, so they are not marked tested.

## Where the data lives

Spans and log records are stored only on your workspace's node. Belvador's edge receives each OTLP request over TLS, checks the key and limits, and passes it to your node; if the node is offline, the request waits at the edge encrypted to your node's key — for up to 15 minutes for traces and logs — and is delivered when it reconnects. Belvador's own database keeps only metadata: which services and SDKs sent data, counts and sizes per signal, and connection check receipts.

## One tracing owner

Run one tracing setup per process. If a process already has OpenTelemetry, add Belvador as an exporter target with the variables from the quickstart — do not add a second SDK that also creates spans. The Belvador SDKs (`@belvador/*`) are errors-only: they never create spans, and with the `otel` option they attach the active OpenTelemetry span's ids to each error so the error and the trace line up (see [Link requests](https://belvador.dev/en/docs/sdk/tracing#with-opentelemetry)).

## Next

1. [Send your first traces and logs](https://belvador.dev/en/docs/otel/quickstart).
2. Pick your runtime: [Node.js](https://belvador.dev/en/docs/otel/node), [Python](https://belvador.dev/en/docs/otel/python), [Go](https://belvador.dev/en/docs/otel/go), [Java](https://belvador.dev/en/docs/otel/java), [Deno](https://belvador.dev/en/docs/otel/deno), or forward everything through the [Collector](https://belvador.dev/en/docs/otel/collector).
3. Read [Privacy](https://belvador.dev/en/docs/otel/privacy) before turning on extra instrumentation.
