> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sawmills.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# How to send logs to VictoriaLogs

> Configure Sawmills to send logs to managed or self-hosted VictoriaLogs using the OTLP HTTP destination, with cloud and Kubernetes setup steps.

This guide explains how to configure Sawmills to send logs to [VictoriaLogs](https://docs.victoriametrics.com/victorialogs/) using the OTLP HTTP destination. VictoriaLogs natively supports OTLP log ingestion over HTTP, so no custom destination type is needed — you can use the existing **OTLP** destination in Sawmills.

<Note>
  VictoriaLogs only supports **OTLP over HTTP** (not gRPC). Make sure to select **HTTP** as the protocol when creating the destination.
</Note>

## Prerequisites

* A running VictoriaLogs instance (managed or self-hosted)
* A Sawmills pipeline with a log source configured (e.g., OTLP, Loki, Datadog)

## VictoriaLogs Cloud (Managed)

### 1. Get your VictoriaLogs Cloud credentials

1. Log in to [VictoriaMetrics Cloud](https://console.victoriametrics.cloud)
2. Create a **VictoriaLogs** deployment (type: "Vlogs single")
3. Note the **Access endpoint** from the deployment overview (e.g., `https://gw-c21-1a.cloud.victoriametrics.com`)
4. Go to the **Access Tokens** tab and copy your deployment access token

### 2. Create an OTLP destination in Sawmills

Navigate to your pipeline, click **+ Add Destination**, select **OTLP**, and fill in:

| Field              | Value                                                                        |
| :----------------- | :--------------------------------------------------------------------------- |
| Name               | e.g., `victorialogs-cloud`                                                   |
| Protocol           | **HTTP**                                                                     |
| Endpoint           | `https://<your-deployment-endpoint>/insert/opentelemetry`                    |
| Enable Basic Auth  | **Off**                                                                      |
| Enabled Data Types | **Logs** only (uncheck Metrics and Traces)                                   |
| Logs Endpoint      | Leave empty (Sawmills appends `/v1/logs` to the base endpoint automatically) |

<Warning>
  VictoriaLogs is a log storage backend. Uncheck **Metrics** and **Traces** under Enabled Data Types — VictoriaLogs does not accept these signals.
</Warning>

### 3. Configure authentication

Expand **Advanced Options** and under **Additional Headers**, click **+ Add Header**:

| Name            | Value                        |
| :-------------- | :--------------------------- |
| `Authorization` | `Bearer <your-access-token>` |

Leave the other advanced settings at their defaults:

* **Timeout**: 30 seconds
* **Compression**: gzip

### 4. Deploy and verify

1. Click **Save**, then deploy the pipeline
2. Send test logs through your pipeline source
3. Verify logs arrive in VictoriaLogs using the **Explore** tab in VictoriaMetrics Cloud, or query via the API:

```bash theme={null}
curl -s \
  "https://<your-deployment-endpoint>/select/logsql/query" \
  -H "Authorization: Bearer <your-access-token>" \
  --data-urlencode 'query=*' \
  --data-urlencode 'limit=10'
```

## VictoriaLogs Self-Hosted

### 1. Identify your VictoriaLogs endpoint

The default OTLP ingestion endpoint for self-hosted VictoriaLogs is:

```
http://<victorialogs-host>:9428/insert/opentelemetry
```

The default port is **9428**. Sawmills appends `/v1/logs` automatically when sending log data.

If VictoriaLogs runs in the same Kubernetes cluster as the Sawmills collector, use the in-cluster DNS:

```
http://victorialogs.<namespace>.svc.cluster.local:9428/insert/opentelemetry
```

### 2. Create an OTLP destination in Sawmills

Navigate to your pipeline, click **+ Add Destination**, select **OTLP**, and fill in:

| Field              | Value                                                                      |
| :----------------- | :------------------------------------------------------------------------- |
| Name               | e.g., `victorialogs-onprem`                                                |
| Protocol           | **HTTP**                                                                   |
| Endpoint           | `http://victorialogs.sawmills.svc.cluster.local:9428/insert/opentelemetry` |
| Enable Basic Auth  | **Off**                                                                    |
| Enabled Data Types | **Logs** only (uncheck Metrics and Traces)                                 |
| Logs Endpoint      | Leave empty                                                                |

No authentication headers are needed for self-hosted VictoriaLogs (unless you have placed an auth proxy like `vmauth` in front of it).

### 3. Deploy and verify

1. Click **Save**, then deploy the pipeline
2. Query VictoriaLogs to confirm logs are arriving:

```bash theme={null}
curl -s "http://<victorialogs-host>:9428/select/logsql/query" \
  --data-urlencode 'query=* | stats count() as total'
```

## Multi-Tenancy

VictoriaLogs supports multi-tenancy via `AccountID` and `ProjectID` HTTP headers. Tenants are created implicitly on first write — no server-side setup required.

### When to use multi-tenancy

* Isolate logs by team, environment, or business unit within a shared VictoriaLogs instance
* Separate infrastructure logs from application logs
* Provide per-tenant query isolation (each tenant can only see its own data)

### How to configure

Create a separate OTLP destination for each tenant, all pointing to the **same** VictoriaLogs endpoint. Under **Advanced Options → Additional Headers**, set:

| Name        | Value                                   |
| :---------- | :-------------------------------------- |
| `AccountID` | Tenant ID (uint32, e.g., `1`, `2`, `3`) |

**Example setup with two tenants:**

**Destination 1 — "VL Infra Logs"**

| Field              | Value                                           |
| :----------------- | :---------------------------------------------- |
| Endpoint           | `http://victorialogs:9428/insert/opentelemetry` |
| Enabled Data Types | Logs only                                       |
| Additional Header  | `AccountID` = `1`                               |

**Destination 2 — "VL App Logs"**

| Field              | Value                                           |
| :----------------- | :---------------------------------------------- |
| Endpoint           | `http://victorialogs:9428/insert/opentelemetry` |
| Enabled Data Types | Logs only                                       |
| Additional Header  | `AccountID` = `2`                               |

Then use Sawmills **filter rules** on each destination to route the right logs to each tenant (e.g., filter by `service.name`, `k8s.namespace.name`, or other attributes).

### Querying a specific tenant

Pass the same `AccountID` header when querying to isolate reads:

```bash theme={null}
# Query infra logs (tenant 1)
curl -s "http://<victorialogs-host>:9428/select/logsql/query" \
  -H "AccountID: 1" \
  --data-urlencode 'query=*' \
  --data-urlencode 'limit=10'

# Query app logs (tenant 2)
curl -s "http://<victorialogs-host>:9428/select/logsql/query" \
  -H "AccountID: 2" \
  --data-urlencode 'query=*' \
  --data-urlencode 'limit=10'
```

<Note>
  If no `AccountID` header is set, logs are stored and queried under the default tenant `(0, 0)`. `ProjectID` is an optional second dimension for finer grouping within an account.
</Note>

### Multi-tenancy with VictoriaLogs Cloud

VictoriaMetrics Cloud uses **deployment-level isolation** — each deployment is a separate tenant. Multi-tenancy via `AccountID`/`ProjectID` headers is typically not needed. Create separate Cloud deployments if you need tenant isolation.

## How it works

The data flow through Sawmills is:

```
Your applications → Sawmills Collector → VictoriaLogs
                    (OTLP HTTP export)
```

Sawmills uses the standard OpenTelemetry Collector `otlphttp` exporter to send logs. VictoriaLogs receives them at its `/insert/opentelemetry/v1/logs` endpoint using protobuf encoding.

**What gets preserved:**

* All OpenTelemetry resource attributes (e.g., `service.name`, `host.name`, `k8s.*`)
* Log severity and body
* Scope name and version
* Sawmills-injected metadata (`sawmills.pipeline_id`, `sawmills.pipeline_name`, `sawmills.collector_id`)

**Log streams:** VictoriaLogs automatically uses all OTel resource attributes as log stream identifiers. To customize which fields define a log stream, add the `VL-Stream-Fields` header (comma-separated field names) under Additional Headers.

## Troubleshooting

| Symptom                                  | Cause                                   | Fix                                                                                               |
| :--------------------------------------- | :-------------------------------------- | :------------------------------------------------------------------------------------------------ |
| HTTP 401 Unauthenticated                 | Invalid or missing bearer token (Cloud) | Verify the `Authorization` header value matches your VictoriaLogs access token                    |
| HTTP 400 "json encoding isn't supported" | Endpoint misconfiguration               | Ensure you are using the OTLP destination (protobuf), not sending raw JSON                        |
| Logs not appearing                       | Wrong endpoint path                     | Verify the endpoint ends with `/insert/opentelemetry` (Sawmills appends `/v1/logs` automatically) |
| Logs in wrong tenant                     | Missing or wrong `AccountID` header     | Check the Additional Headers section in your destination config                                   |
| High cardinality warning in VL           | Too many unique stream combinations     | Add a `VL-Stream-Fields` header to limit which attributes define log streams                      |
| Export timeout                           | Network or firewall issue               | Check that the collector can reach the VictoriaLogs endpoint; verify TLS settings                 |
