# Send your first traces and logs

> Create an ingest key, set the standard OTEL_* environment variables, run your app with its runtime's instrumentation and check the OTLP connection in Belvador.

Three steps: a key, the standard OpenTelemetry variables, and your runtime's instrumentation. Nothing here is Belvador-specific code — any OpenTelemetry SDK or Collector that exports OTLP/HTTP works the same way.

## 1. Create an ingest key

Open the project, then **Settings → Ingest keys → Create ingest key**. Give it a name (for example the service or the machine), tick **Traces** and **Logs**, and optionally limit it to some environments — records from other environments are then dropped.

The key starts with `bvi_` and is shown **once**. It is a secret that can only send data: keep it in your server's environment or secret store, never in code that runs in a browser (the edge refuses requests that come from one). A project can have up to 10 keys on the default plan; revoking one stops every sender using it within 60 seconds.

## 2. Set the standard variables

Every OpenTelemetry SDK reads these. Replace `<project-id>` and the key placeholder; the **Ingest keys** card shows the block with your project id filled in.

```bash
export OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.belvador.dev/otlp/<project-id>
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20<your-ingest-key>
export OTEL_TRACES_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=none
export OTEL_SERVICE_NAME=my-service
export OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=production
```

- `OTEL_SERVICE_NAME` names the service in Traces, Logs and the **Connection** tab. Use one name per deployable.
- `deployment.environment.name` is the environment (`production`, `staging`, …) — the same idea as an error's environment, so filters line up.
- The header value is percent-encoded (`%20` is the space after `Bearer`), as the OpenTelemetry specification requires for this variable.
- Metrics are off here: they have their own monthly budget. To send them, see [Metrics](https://belvador.dev/en/docs/otel/metrics#turn-them-on).

## 3. Run with your runtime's instrumentation

| Runtime | What to add |
|---|---|
| [Node.js](https://belvador.dev/en/docs/otel/node) | Three packages and one `--require` (CommonJS) or `--import` (ES modules) flag |
| [Python](https://belvador.dev/en/docs/otel/python) | `opentelemetry-distro`, then start the app with `opentelemetry-instrument` |
| [Go](https://belvador.dev/en/docs/otel/go) | One setup function, `otelhttp` and `otelslog` |
| [Java](https://belvador.dev/en/docs/otel/java) | The OpenTelemetry Java agent with `-javaagent` |
| [Deno](https://belvador.dev/en/docs/otel/deno) | `OTEL_DENO=true` |
| Anything else | Point your apps at a local [Collector](https://belvador.dev/en/docs/otel/collector) and let it forward |

Then send one request through your app. Traces appear in **Traces** and logs in **Logs** within seconds; exporters batch for a few seconds before sending.

## 4. Check the connection

Open the project's **Connection** tab. **Evidence per signal** shows when traces and logs were last seen and from which service and SDK. To prove the whole path end to end, press **Check the OTLP connection**:

1. Belvador shows a `curl` command with a fresh marker. Run it from any machine with internet access, with your ingest key in place of the placeholder. It sends one span and one log carrying the attribute `belvador.verification_id`.
2. The panel follows the steps: **Sent from your machine → Belvador's edge accepted it → Your node stored the receipt → Read back from your node**.

Your own SDK can do the same: any span or log with the `belvador.verification_id` attribute set to the marker counts. A passed check proves that this key, this project and this environment reach your node at that moment — it does not certify a runtime or prove that every service is instrumented.

## If nothing shows up

Start with [Troubleshooting](https://belvador.dev/en/docs/otel/troubleshooting). The most common causes are a wrong time range or environment filter, a key without the **Traces** or **Logs** box ticked, and a process that exits before its exporter flushes.
