> ## 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.

# OpenTelemetry

> Set OTEL_EXPORTER_OTLP_ENDPOINT to your Sazabi intake URL to forward logs and traces from any OpenTelemetry SDK directly to Sazabi.

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

## About

Point your OpenTelemetry SDK's OTLP exporter at Sazabi to send logs and traces from any language or framework. Sazabi's intake is OTLP/HTTP-compatible — no custom exporter or plugin required.

> [!NOTE]
>
> **Already running Datadog, New Relic, or Elastic APM?** With the Datadog Agent, use the [Datadog Agent](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/datadog.md) source to add Sazabi as a second logs endpoint, with no app changes. With an in-process APM agent, keep it for traces and send only logs with the [Python logs-only](#python-logs-only) setup or your language's log exporter. Do not run two auto-instrumentation agents in one process: both patch the same libraries and compete for the global tracer provider.

Logs and traces arrive as separate streams. Metrics are not stored by this source; use [OpenTelemetry Metrics](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/opentelemetry-metrics.md) instead.

## Prerequisites

* An application instrumented with any OpenTelemetry SDK (Node.js, Python, Go, Java, Ruby, etc.)
* Your Sazabi intake URL, shown above — open the log source and copy the **Intake URL** from its setup screen (the public key is embedded in the URL).

## Set up in the dashboard

**Step 1**

### Install and initialize the OpenTelemetry SDK

Add the OpenTelemetry SDK for your runtime and initialize it with OTLP exporters before your application handles requests.

For Node.js:

```bash theme={"system"}
bun add @opentelemetry/api @opentelemetry/sdk-node \
  @opentelemetry/auto-instrumentations-node \
  @opentelemetry/exporter-trace-otlp-proto \
  @opentelemetry/exporter-logs-otlp-proto \
  @opentelemetry/sdk-logs
```

For Python, add the packages to your dependency manifest so locked builds keep working (`uv` shown; `poetry add` or a pinned `requirements.txt` work the same), then start your app with `opentelemetry-instrument` and set `OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true` so `logging` records are exported:

```bash theme={"system"}
uv add opentelemetry-distro opentelemetry-exporter-otlp-proto-http
# List the instrumentation packages for the libraries you use, then add those to the manifest too
uv run opentelemetry-bootstrap -a requirements
# Start inside the project environment (or with .venv/bin on PATH in your image)
uv run opentelemetry-instrument <your start command>
```

Avoid `opentelemetry-bootstrap -a install`: it installs outside the manifest and breaks `uv sync --locked`.

#### Python logs only

To send only `logging` records with no auto-instrumentation, install the SDK and the OTLP exporter:

```bash theme={"system"}
uv add opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
```

Then attach a `LoggingHandler` once per process:

```python theme={"system"}
import logging

from opentelemetry._logs import set_logger_provider
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor


def setup_otel_logging() -> LoggerProvider:
    # Reads OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_SERVICE_NAME
    provider = LoggerProvider()
    provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter()))
    set_logger_provider(provider)
    # The root logger defaults to WARNING: set your app's level (for example logging.basicConfig(level=logging.INFO)) so INFO records reach the handler
    logging.getLogger().addHandler(LoggingHandler(logger_provider=provider))
    return provider
```

Under gunicorn or Celery prefork, call `setup_otel_logging()` in each worker after the fork (gunicorn's `post_fork` hook, Celery's `worker_process_init` signal), not at import time in the master process. Call `get_logger_provider().shutdown()` when the worker exits (`worker_exit`, `worker_process_shutdown`) so the last batch is sent. The [Porter](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/porter.md#send-python-logs-without-auto-instrumentation) page has complete hook examples.

**Step 2**

### Set the exporter environment variables

Configure the following environment variables so they are present when the process starts:

```bash theme={"system"}
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT=<your intake URL>
```

Your intake URL is shown above. It already encodes your project public key.

> [!WARNING]
>
> Sazabi does not store OpenTelemetry metrics sent to this endpoint. To store
> metrics, use the [OpenTelemetry
> Metrics](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/opentelemetry-metrics.md)
> source, which routes to the correct intake path.

**Step 3**

### Redeploy the application

Restart or redeploy the application so it picks up the new environment variables and initializes the SDK before handling traffic.

**Step 4**

### 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 OpenTelemetry 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 otel --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

Generate a request or event in your application to produce fresh telemetry. Open the [Intake page](https://docs.sazabi.com/guides/instrument/intake.md) in the Sazabi dashboard and confirm records from the **OpenTelemetry** source appear. Logs and traces typically arrive within a minute or two.

You can also start a thread in the dashboard and search for a log attribute you expect to see, such as a service name or route.

To check counts from your side, ask the [Sazabi CLI](https://docs.sazabi.com/reference/cli.md) for lines per service over a window:

```bash theme={"system"}
sazabi logs ask "how many log lines did each service send in the last 24 hours"
```

## Troubleshooting

**No records after redeploying** — Confirm `OTEL_EXPORTER_OTLP_ENDPOINT` and `OTEL_EXPORTER_OTLP_PROTOCOL` are set in the same process that runs your application, not only in a build step or CI environment. Check application output for OpenTelemetry SDK initialization errors.

**Traces appear but logs do not** — Auto-instrumentation for Node.js configures trace export but not log export. Add an explicit `BatchLogRecordProcessor` with `OTLPLogExporter` to your SDK initialization so log records are also exported.

**Some log lines are missing under load** — SDK batch processors buffer a bounded number of records per process (`OTEL_BLRP_MAX_QUEUE_SIZE`, default 2048) and drop records when the queue is full. The queue only fills when exports fall behind, for example while intake is slow or retrying. Current Python SDKs log a `Queue full, dropping` warning when this happens. Raise the queue size to cover your peak lines per second per process times the longest export stall you want to ride out.

**Metrics are not stored** — This source does not store OpenTelemetry metrics. Use [OpenTelemetry Metrics](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/opentelemetry-metrics.md) for metric data.

**Export errors in application logs** — Verify the intake URL is correct and includes the `https://` scheme. The intake endpoint does not require additional authentication headers — the public key is encoded in the URL hostname.

## 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.