OpenTelemetry Protocol (OTLP)
Synopsis
Creates a target that forwards telemetry data to any OpenTelemetry Protocol (OTLP)-compatible receiver. Supports HTTP and gRPC transports, protobuf and JSON encoding, gzip compression, custom headers, TLS, and configurable retry logic.
This target has no GUI creation wizard. Configure it directly in the target YAML file.
Schema
- name: <string>
description: <string>
type: otlp
pipelines: <pipeline[]>
status: <boolean>
properties:
url: <string>
address: <string>
port: <numeric>
protocol: <string>
path: <string>
format: <string>
compression: <boolean>
timeout: <numeric>
batch_size: <numeric>
max_retries: <numeric>
retry_delay: <numeric>
grpc_passthrough: <boolean>
headers:
<key>: <value>
tls:
status: <boolean>
verify: <boolean>
cert_name: <string>
key_name: <string>
server_name: <string>
min_tls_version: <string>
debug:
status: <boolean>
dont_send_logs: <boolean>
Configuration
The following fields are used to define the target:
| Field | Required | Default | Description |
|---|---|---|---|
name | Y | Target name | |
description | N | - | Optional description |
type | Y | Must be otlp | |
pipelines | N | - | Optional post-processor pipelines |
status | N | true | Enable/disable the target |
Connection
| Field | Required | Default | Description |
|---|---|---|---|
url | Y* | - | Full endpoint URL for HTTP (e.g. http://collector:4318) or host:port for gRPC |
address | Y* | - | Remote host; alternative to url |
port | Y* | - | Remote port; alternative to url |
* = Provide url or both address and port. Exactly one form is required.
Transport
| Field | Required | Default | Description |
|---|---|---|---|
protocol | N | http | Wire transport: http or grpc |
path | N | /v1/logs | HTTP URL path; leading / is added automatically. Use /v1/metrics or /v1/traces for other signals. HTTP only. |
format | N | protobuf | Encoding: protobuf or json. json is invalid with protocol: grpc. |
compression | N | true | Enable gzip compression |
Performance
| Field | Required | Default | Description |
|---|---|---|---|
timeout | N | 30 | Request or RPC timeout in seconds |
batch_size | N | 1000 | Maximum events per batch; must be >= 1 |
max_retries | N | 3 | Maximum delivery attempts on failure; must be >= 0 |
retry_delay | N | 1 | Seconds between retry attempts |
gRPC
| Field | Required | Default | Description |
|---|---|---|---|
grpc_passthrough | N | true | When true, sends raw OTLP bytes using content-subtype: raw-otlp (VirtualMetric-to-VirtualMetric only). When false, re-encodes as standard typed OTLP/gRPC for interoperability with any spec-compliant receiver. |
Headers
| Field | Required | Default | Description |
|---|---|---|---|
headers | N | - | Map of string key-value pairs added to every HTTP request or gRPC metadata (e.g. authorization tokens, tenant IDs) |
TLS
| Field | Required | Default | Description |
|---|---|---|---|
tls.status | N | false | Enable TLS |
TLS material is resolved through the shared client builder, so these keys mean the same thing on every
target that uses it. They are nested under a tls: block.
| Field | Required | Default | Description |
|---|---|---|---|
tls.verify | N | true | Verify the server certificate. On by default — set it to false only to accept an untrusted certificate, and only where you control the network path |
tls.server_name | N | - | SNI hostname override for the handshake. Use it when the certificate's name does not match the address you connect to |
tls.ca_name | N | - | CA bundle used to verify the server certificate. When unset the host trust store is used; when set it replaces the host trust store rather than adding to it |
tls.cert_name | N* | - | Client certificate, for mutual TLS |
tls.key_name | N* | - | Client private key, for mutual TLS |
tls.passphrase | N | - | Passphrase for an encrypted client private key |
tls.min_tls_version | N | tls1.2 | Lowest protocol version accepted (tls1.0, tls1.1, tls1.2, tls1.3) |
tls.max_tls_version | N | tls1.3 | Highest protocol version accepted (tls1.0, tls1.1, tls1.2, tls1.3) |
* cert_name and key_name are individually optional but must be supplied together — a certificate
without its key, or a key without its certificate, is a configuration error.
tls.max_tls_version is accepted but not applied on this target — the sender deliberately leaves the maximum version unset, so only tls.min_tls_version takes effect here.
Scheduling
See Scheduling and Pool Behavior for interval and cron fields shared by all targets.
Debug Options
| Field | Required | Default | Description |
|---|---|---|---|
debug.status | N | false | Enable debug logging |
debug.dont_send_logs | N | false | Process logs but don't send to target (testing) |
Details
The OTLP target delivers telemetry to any OpenTelemetry-compatible receiver — otel-collector, rotel, Grafana Alloy, vendor ingest endpoints, or another VirtualMetric Director.
Record translation
Records originating from this Director's own OTEL listener carry a JSON envelope with full Resource and Scope context. The target parses the envelope and reassembles each record as a one-record ExportLogsServiceRequest, preserving the original Resource and Scope end-to-end. This path is lossless.
Records from non-OTEL sources (TCP listener, syslog, etc.) are wrapped as a synthetic LogRecord with the body set to the raw message bytes and minimal resource attributes (service.name = the device name). This path is lossy by definition — non-OTEL sources have no OTLP context — but produces valid OTLP that any downstream collector accepts.
HTTP transport
HTTP is the default transport. Each worker maintains its own http.Client to avoid idle-connection contention. Batches are POSTed to endpoint + path. The Content-Type header is set to application/x-protobuf for format: protobuf and application/json for format: json. When compression: true, the body is gzip-compressed and Content-Encoding: gzip is set.
The path field controls the signal type delivered: /v1/logs (default), /v1/metrics, or /v1/traces. The wire payload for all three is the corresponding OTLP proto message — only the path and embedded message type differ.
gRPC transport
When protocol: grpc, each worker maintains its own grpc.ClientConn. The gRPC method path is fixed to /opentelemetry.proto.collector.logs.v1.LogsService/Export (logs only in v1; metrics and traces require the HTTP path via path).
grpc_passthrough: true (default): sends raw OTLP bytes using grpcraw.Codec with content-subtype: raw-otlp. This is the fast path for VirtualMetric-to-VirtualMetric relay — one Director to another with no re-serialization. Standard OTLP/gRPC receivers (otel-collector, rotel, vendor gateways) reject this subtype as Unimplemented.
grpc_passthrough: false: re-encodes each batch into the typed proto message (ExportLogsServiceRequest, etc.) using the standard gRPC codec and marshals with UnmarshalVT. This produces spec-compliant OTLP/gRPC that any receiver accepts, at the cost of one additional unmarshal+marshal per outbound batch. Use false for cross-vendor deployments.
Configuration validation
The following rules are enforced at config load:
urlor (address+port) must be provided; providing neither is rejected.formatmust beprotobuforjson.format: jsoncombined withprotocol: grpcis rejected — OTLP/gRPC is protobuf-only on the wire.batch_sizemust be >= 1.max_retriesmust be >= 0.tls.cert_nameandtls.key_namemust both be present or both be absent.
Examples
Basic HTTP
Forwarding logs to an OTLP/HTTP collector with default settings... | |
JSON Format over HTTP
Sending telemetry as JSON-encoded OTLP to an HTTP endpoint... | |
gRPC Spec-Compliant
Delivering logs over gRPC to a third-party collector using typed OTLP encoding... | |
TLS-Secured
Sending logs over HTTPS with mutual TLS client certificate authentication... | |
Performance Tuning
High-volume configuration with large batches, retry logic, and auth header... | |