Skip to main content

OpenTelemetry Protocol (OTLP)

Network

Synopsis

Receives OpenTelemetry logs, metrics, and traces over OTLP/gRPC (default port 4317) and OTLP/HTTP (default port 4318) concurrently. Supports per-signal and per-transport enable/disable toggles, basic and bearer authentication, server TLS and mutual TLS, and configurable worker fan-out via SO_REUSEPORT.

To forward telemetry to an external OTLP-compatible receiver instead, see the OTLP target.

Schema

- id: <numeric>
name: <string>
description: <string>
type: otel
tags: <string[]>
pipelines: <pipeline[]>
status: <boolean>
properties:
address: <string>
otlp_grpc_status: <boolean>
otlp_grpc_port: <numeric>
otlp_http_status: <boolean>
otlp_http_port: <numeric>
otlp_logs_status: <boolean>
otlp_metrics_status: <boolean>
otlp_traces_status: <boolean>
otlp_logs_http_path: <string>
otlp_metrics_http_path: <string>
otlp_traces_http_path: <string>
otlp_max_recv_msg_mib: <numeric>
authentication:
type: <string>
username: <string>
password: <string>
tokens:
- token: <string>
tenant_id: <string>
expire_date: <numeric>
tenants:
- tenant_id: <string>
ip_blocks: <string[]>
tls:
status: <boolean>
cert_name: <string>
key_name: <string>
passphrase: <string>
min_tls_version: <string>
max_tls_version: <string>
client_ca_name: <string>
client_auth_required: <boolean>
insecure_skip_verify: <boolean>
reuse: <boolean>
workers: <numeric>
timezone: <string>
otel_resource_attributes: <string>

Configuration

The following fields are used to define the device:

Device

FieldRequiredDefaultDescription
idY-Unique numeric identifier
nameY-Device name
descriptionN-Optional description
typeY-Must be otel
tagsN-Optional tags
pipelinesN-Optional pre-processor pipelines
statusNtrueEnable/disable the device
addressN0.0.0.0Listen address applied to both transports

Transports

Both transports run concurrently and are individually toggleable. At least one transport must be enabled. The gRPC and HTTP ports must be distinct.

gRPC

FieldRequiredDefaultDescription
otlp_grpc_statusNtrueEnable the OTLP/gRPC endpoint
otlp_grpc_portN4317gRPC listen port

HTTP

FieldRequiredDefaultDescription
otlp_http_statusNtrueEnable the OTLP/HTTP endpoint
otlp_http_portN4318HTTP listen port

Signals

Logs, metrics, and traces are individually toggleable. At least one signal must be enabled. HTTP paths apply to the OTLP/HTTP transport only.

FieldRequiredDefaultDescription
otlp_logs_statusNtrueEnable the logs signal
otlp_metrics_statusNtrueEnable the metrics signal
otlp_traces_statusNtrueEnable the traces signal
otlp_logs_http_pathN/v1/logsHTTP path for the logs signal
otlp_metrics_http_pathN/v1/metricsHTTP path for the metrics signal
otlp_traces_http_pathN/v1/tracesHTTP path for the traces signal

Access List

The access_list property is a source-IP firewall: an ordered list of accept/drop rules over IP blocks, evaluated before the listener parses or authenticates the connection. When it is not set, the firewall is off and adds no overhead.

FieldRequiredDefaultDescription
access_listN-Ordered list of source-IP rules. Omit to disable the firewall.
access_list[].actionYaccept or drop (synonyms: allow/permit and deny/reject/block). Unrecognized actions are ignored.
access_list[].ip_blocksYOne or more IP blocks the rule matches. Comma-separated string or a list. Accepts CIDR (10.0.0.0/24), single IP (172.16.5.10), dotted-netmask (192.168.1.0/255.255.255.0, IPv4 only), and inclusive range (10.5.0.1-10.5.0.50). IPv4 and IPv6.
access_list_defaultNautoVerdict for a source IP that matches no rule: accept or drop. When omitted, it is derived automatically (see below).

Rules are evaluated top to bottom and the first rule whose blocks contain the source IP decides the outcome. A source IP that matches no rule follows the default policy:

  • If any accept rule is present, the list is treated as an allowlist and unmatched IPs are dropped.
  • Otherwise the list is treated as a denylist and unmatched IPs are accepted.

Set access_list_default to override this. An unparseable source IP is judged by the default policy, so an allowlist fails closed.

access_list:
- action: accept
ip_blocks: "10.0.0.0/8, 192.168.0.0/16, 172.16.5.10"
note

Editing or removing access_list rules applies on the next configuration reconcile with no listener restart. Enabling access_list for the first time on a device that had none takes effect on the next collector restart.

The firewall runs before authentication on both transports. When a source IP is denied, a gRPC request fails with PermissionDenied and an HTTP request receives 403 Forbidden, with no body read.

Authentication

An optional header/metadata authentication layer applied identically to both transports. none disables authentication enforcement.

FieldRequiredDefaultDescription
authentication.typeNnoneAuth scheme: none, basic, or bearer
authentication.usernameY*-Basic-auth username
authentication.passwordY*-Basic-auth password
tokensY**-Array of accepted bearer tokens (bare or Bearer-prefixed). Each entry is a plain string or an object (see Multi-Tenancy)

* = Required when authentication.type is basic.

** = Required when authentication.type is bearer.

Multi-Tenancy

Both transports can attach a tenant_id to each record, resolved from the bearer token first and the source IP as a fallback.

Token-Based

Each entry in the tokens list may be a plain string (matched as-is, with no tenant) or an object that binds the token to a tenant and an optional expiry. Both forms can be mixed in the same list.

FieldRequiredDefaultDescription
tokens[].tokenYThe accepted token secret. Quote long numeric-looking values to preserve them exactly.
tokens[].tenant_idN-Tenant identifier attached to records authenticated with this token. Omit for no tenant.
tokens[].expire_dateNneverExpiry as epoch seconds (e.g. 1924905600). The token is rejected at and after this instant. Omit for a token that never expires.

A request presenting an expired or unknown token is rejected with 401 and no record is ingested. When a request authenticates with a token that carries a tenant_id, that tenant is written to _vmetric.event.tenant_id; the client IP always stays at _vmetric.event.request. Use _vmetric.event.tenant_id to route or isolate each customer's data downstream (see Routes).

tokens:
- token: "acme-9f3c...key"
tenant_id: "acme"
expire_date: 1924905600
- token: "globex-7a1b...key"
tenant_id: "globex"
- "legacy-plain-token"
note

Token changes take effect on the next collector restart.

Requires authentication.type: bearer.

IP-Based

The tenants property maps a source IP to a tenant: an ordered list of rules matched against the connection's (or datagram's) source address before the record enters the pipeline. Multiple IP blocks can map to the same tenant, and multiple tenants are supported. When it is not set, no tenant is attached.

FieldRequiredDefaultDescription
tenantsN-Ordered list of source-IP-to-tenant rules. Omit to disable IP-based tenancy.
tenants[].tenant_idYTenant identifier attached to records arriving from the matching IP blocks.
tenants[].ip_blocksYOne or more IP blocks the rule matches. Comma-separated string or a list. Accepts CIDR (10.0.0.0/24), single IP (172.16.5.10), dotted-netmask (192.168.1.0/255.255.255.0, IPv4 only), and inclusive range (10.5.0.1-10.5.0.50). IPv4 and IPv6.

Rules are evaluated top to bottom and the first rule whose blocks contain the source IP wins. A source IP that matches no rule receives no tenant — the record is still ingested. When a tenant is resolved it is written to _vmetric.event.tenant_id; the client IP always stays at _vmetric.event.request. Use _vmetric.event.tenant_id to route or isolate each customer's data downstream (see Routes).

tenants:
- tenant_id: acme
ip_blocks: "10.0.0.0/24, 10.1.2.3, 192.168.10.0/255.255.255.0"
- tenant_id: globex
ip_blocks: "10.2.0.0/16, 172.16.5.1-172.16.5.50"
note

Editing or removing tenants rules applies on the next configuration reconcile with no listener restart. Enabling tenants for the first time on a device that had none takes effect on the next collector restart.

When a request presents a valid bearer token whose entry carries a tenant_id, that tenant wins; the tenants IP map is consulted only when the token supplies no tenant.

TLS

TLS applies to both transports.

FieldRequiredDefaultDescription
tls.statusNfalseEnable TLS encryption
tls.cert_nameY*cert.pemTLS certificate
tls.key_nameY*key.pemTLS private key
tls.passphraseN-Passphrase for an encrypted private key
tls.min_tls_versionNtls1.2Minimum accepted TLS version (tls1.0, tls1.1, tls1.2, tls1.3)
tls.max_tls_versionN-Maximum accepted TLS version. When unset, the highest mutually supported version is negotiated.
tls.client_ca_nameN-CA bundle used to verify client certificates (mTLS)
tls.client_auth_requiredN**falseRequire connecting clients to present a valid certificate. When false, a client certificate is verified only if one is presented.
tls.insecure_skip_verifyNfalseSkip peer certificate verification. Use only for testing.

* = Required when tls.status is true.

** = Requires tls.client_ca_name. If tls.client_auth_required is true or tls.client_ca_name is set and the named CA cannot be loaded, the configuration is rejected and the device fails to start.

note

tls.min_version is a deprecated alias for tls.min_tls_version, honored only when tls.min_tls_version is unset. Use tls.min_tls_version in new configurations.

note

TLS material fields (cert_name, key_name, ca_name, client_ca_name) accept any of the following:

  • File name — resolved relative to the service root directory. Nested paths such as certs/prod/server.pem are supported.
  • Absolute path — honored only if it resolves inside the service root. Any path that escapes the root is refused.
  • Inline PEM content — used verbatim when the value contains -----BEGIN.
  • Environment variable${ENV_VAR}.
  • Vault reference$secret{id=...} or $secret{store=...,ref=...}.

Performance and Advanced

FieldRequiredDefaultDescription
otlp_max_recv_msg_mibN4Maximum per-RPC gRPC receive size in MiB (floored at 1). Applies to gRPC only.
reuseNtrueEnable socket address reuse (SO_REUSEPORT) for worker fan-out
workersNCPU coresConcurrent processing workers per transport (default: min(NumCPU, 8))
timezoneN-Per-device timestamp offset adjustment
otel_resource_attributesN-Comma-separated key=value resource attributes (currently a no-op — see warning below)
warning

otel_resource_attributes is parsed and validated but is currently a no-op — the raw-bytes ingest path does not apply resource-attribute upserts. Setting it emits a startup warning and does not modify emitted records.

Details

Transports and Ports

The gRPC endpoint (default port 4317) and HTTP endpoint (default port 4318) start concurrently. Each is independently toggleable via otlp_grpc_status and otlp_http_status. Disabling both transports is rejected at config load. The two transports must bind distinct ports — sharing a port between gRPC and HTTP is not supported.

The gRPC listener negotiates h2 (ALPN) and the HTTP listener uses http/1.1. A top-level port or protocol field on the device is forced internally per-transport and has no effect; use otlp_grpc_port and otlp_http_port to set ports.

Signals

Logs, metrics, and traces are individually toggleable. Disabling all three signals is rejected at config load. The per-signal HTTP paths (otlp_logs_http_path, otlp_metrics_http_path, otlp_traces_http_path) apply to the OTLP/HTTP transport; gRPC routes by OTLP service method and the path fields have no effect on it.

Authentication

Three schemes are available: none (open, no credentials required), basic (HTTP Basic Auth using authentication.username and authentication.password), and bearer (token matching against the tokens array). Bearer token matching accepts both bare tokens and Bearer -prefixed values. The authentication layer is applied identically to both transports — gRPC metadata and HTTP headers are checked with the same logic.

TLS and mTLS

Server TLS is enabled via tls.status together with tls.cert_name and tls.key_name. Mutual TLS is configured independently by setting tls.client_ca_name (CA bundle for client certificate verification) and tls.client_auth_required: true. The mTLS layer operates independently of the header/token authentication layer — both can be active simultaneously.

Message Size Limits

otlp_max_recv_msg_mib caps the per-RPC payload size on the gRPC transport (value is converted from MiB to bytes; floored at 1 MiB). The HTTP transport is not bound by this setting.

Performance and Workers

workers sets the per-transport concurrent processing fan-out. The default is min(NumCPU, 8). reuse enables SO_REUSEPORT so multiple workers can accept on the same socket address without lock contention. Both settings apply to each transport independently.

Configuration Reload

Changing any of the following restarts the listener: transport enable flags, port assignments, signal enable flags, HTTP signal paths, TLS material, authentication credentials, worker count, or otlp_max_recv_msg_mib.

note

The device type for this listener is otel, not otlp. The OTLP target uses type: otlp; this device uses type: otel. Using the wrong type string will cause the device to fail to load.

Examples

The following are commonly used configuration types.

Basic

A minimal OTLP device using default ports and all signals enabled:

Creating an OTLP listener accepting logs, metrics, and traces on default ports...

devices:
- id: 1
name: basic_otel
type: otel

Logs-Only on Custom Ports

Receiving only log signals on non-default gRPC and HTTP ports:

Restricting to logs and moving transports off the default OTLP ports...

devices:
- id: 2
name: logs_only_otel
type: otel
properties:
otlp_grpc_port: 14317
otlp_http_port: 14318
otlp_metrics_status: false
otlp_traces_status: false

HTTP-Only with Custom Paths

Disabling gRPC and overriding the default OTLP/HTTP signal paths:

Running only the HTTP transport with application-specific path prefixes...

devices:
- id: 3
name: http_only_otel
type: otel
properties:
otlp_grpc_status: false
otlp_logs_http_path: /ingest/v1/logs
otlp_metrics_http_path: /ingest/v1/metrics
otlp_traces_http_path: /ingest/v1/traces

TLS

Enabling server-side TLS on both transports:

Securing the OTLP listener with a server certificate and minimum TLS version...

devices:
- id: 4
name: tls_otel
type: otel
properties:
tls:
status: true
cert_name: otel.crt
key_name: otel.key
min_tls_version: "tls1.2"

mTLS with Bearer Authentication

Requiring mutual TLS client certificates and bearer token authentication:

Combining mTLS client verification with bearer token enforcement for zero-trust ingestion...

devices:
- id: 5
name: mtls_bearer_otel
type: otel
properties:
tls:
status: true
cert_name: otel.crt
key_name: otel.key
min_tls_version: "tls1.3"
client_ca_name: ca-bundle.pem
client_auth_required: true
authentication:
type: bearer
tokens:
- eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
- prod-collector-token-abc123

Multi-Tenant Ingestion

Serving multiple customers through one OTLP endpoint — collectors that authenticate resolve their tenant by token, while unauthenticated senders fall back to the source-IP map:

Token tenants take precedence; the IP map covers senders that present no tenant-bearing token...

devices:
- id: 7
name: saas_otel
type: otel
properties:
authentication:
type: bearer
tokens:
- token: "acme-collector-key"
tenant_id: "acme"
tenants:
- tenant_id: "globex"
ip_blocks: "10.2.0.0/16"

A gRPC export from 10.2.0.7 with no tenant token is tagged from the IP map...

{
"_vmetric": {
"device": { "id": 7, "name": "saas_otel", "type": "otel" },
"event": {
"request": "10.2.0.7",
"tenant_id": "globex"
}
}
}

High-Volume Tuning

Optimizing for large telemetry volumes with increased workers, message size, and pipeline pre-processing:

Scaling worker fan-out and gRPC message limits for high-throughput environments...

devices:
- id: 6
name: highvol_otel
type: otel
pipelines:
- otel_normalizer
- resource_enricher
properties:
workers: 16
reuse: true
otlp_max_recv_msg_mib: 32