Info
License: Free — part of the universal collection tier.
OTLP Receiver Probe¶
The otlp_receiver probe turns the agent into an edge OTLP
collector: applications and SDKs push OTLP metrics to it (gRPC or
HTTP), and the ingested datapoints flow through the agent exactly
like locally collected metrics — out to PRTG, Nagios, Prometheus,
OTLP or the SenHub cloud, whichever storages are configured.
Use it when instrumented applications run next to the agent and you want one egress point per host instead of a separate collector deployment.
Quick start¶
# probes.d/10-otlp-receiver.yaml — each file under probes.d/ is a YAML array of probes
- name: otlp-in
type: otlp_receiver
params:
protocol: grpc # listens on 127.0.0.1:4317
# address: "0.0.0.0:4317" # required to accept remote senders
Point any OTel SDK or collector at the agent:
Parameters¶
| Parameter | Default | Description |
|---|---|---|
protocol |
grpc |
grpc (OTLP/gRPC) or http (OTLP/HTTP protobuf) |
signals |
[metrics] |
Which OTLP signals the listener accepts: any combination of metrics, logs, traces. Logs and traces are relayed onward through a configured OTLP export strategy (see Behavior) |
address |
127.0.0.1:4317 (grpc), 127.0.0.1:4318 (http) |
Listen address. Loopback by default — accepting remote OTLP requires an explicit address (e.g. "0.0.0.0:4317"); pair it with the protections below |
port |
from address |
Convenience override: replaces only the port part of the address |
http_path |
/v1/metrics |
Route the HTTP receiver serves metrics on (ignored for gRPC). Logs are always served on /v1/logs, traces on /v1/traces |
bearer_token |
none | When set, senders must present Authorization: Bearer <token> (HTTP header or gRPC metadata). Reference a stored secret via ${secret:<name>.bearer_token}, ${env:VAR} or ${file:/path}; inline plaintext is auto-sealed into the OS secret store on install |
allowed_cidrs |
none | Source IP allow-list (CIDR notation, IPv4/IPv6). Checked against the transport peer address — proxy headers are not trusted |
rate_limit_rps |
0 (off) |
Accepted requests per second (token bucket). Excess requests get HTTP 429 / gRPC ResourceExhausted |
rate_limit_burst |
2 × rps |
Bucket burst capacity |
Opening the receiver to the network with all protections:
# probes.d/10-otlp-receiver.yaml
- name: otlp-in
type: otlp_receiver
params:
protocol: grpc
address: "0.0.0.0:4317"
bearer_token: ${secret:otlp-in.bearer_token} # OS secret store; inline plaintext is auto-sealed on install
allowed_cidrs: ["10.0.0.0/8"]
rate_limit_rps: 100
Run two instances to serve both protocols at once:
# probes.d/10-otlp-receiver.yaml
- name: otlp-grpc
type: otlp_receiver
params:
protocol: grpc
- name: otlp-http
type: otlp_receiver
params:
protocol: http
Behavior¶
- Resource attributes become tags.
host.name,service.nameand every other resource attribute is folded onto each datapoint, so downstream sinks can group by origin. Per-datapoint attributes win on key collisions. This is what PRTG, Nagios, Prometheus, the web UI and the cloud sink read, and it is unchanged. - The OTLP output relays the original batch. Those same points are
also forwarded verbatim on the OTLP export, under the emitting
application's resource rather than re-encoded under the agent's.
Without it a reserved identity key such as
service.namewould carry two different values in one export — the agent's on the resource, the application's on the datapoint — and the backend would silently keep one. Agent context is added on top, never substituted, exactly as for logs and traces. Only the OTLP output is affected; every other sink keeps reading the tags above. - All metric types. Gauges and Sums map to one value each.
Explicit-bucket histograms are ingested natively: re-exported over
OTLP as a genuine histogram (buckets, sum, count, min/max preserved)
and on the Prometheus endpoint as a classic histogram — cumulative
<name>_bucket{le="…"},<name>_sum,<name>_count. Sinks without histogram rendering (PRTG, Nagios, cloud) show the observation count. Summaries are ingested as their component series —<name>_count,<name>_sum,<name>{quantile="…"}— and exponential histograms contribute their_count/_sum/_min/_maxaggregates (the base-2 buckets are not expanded yet). Only a metric with an unrecognized or unset data type is dropped, reported in the OTLP partial-success response. - Pass-through naming. Ingested metric names are forwarded unchanged; nothing is renamed or prefixed.
-
Logs are relayed. With
signals: [logs], OTLP log records are accepted (gRPCLogsService, or HTTP on/v1/logs) and forwarded verbatim by a configured OTLP export strategy (an OTLP-in → OTLP-out relay). Severity, body, attributes and the emitting application's resource are preserved: a record sent withservice.name=my-apparrives asmy-app, so applications stay distinguishable at the backend. Agent context (tenant, site, environment, thetelemetry.relay.*identity) is only ever added on top — an attribute the sender already set is never replaced. The pull sinks (Prometheus/PRTG/Nagios) are metrics-only, so logs need an OTLP export strategy — without one, ingested logs are discarded and the agent logs a throttled warning.Changed behaviour
Before this release, ingested logs were re-emitted through the agent's own log pipeline, which replaced the sender's resource with the agent's — a record sent with
service.name=my-appwas stored under the agent'sservice.name, making applications indistinguishable by that attribute. If a dashboard or query relies on ingested logs carrying the agent'sservice.name, point it at the agent's own logs or attelemetry.relay.instance.idinstead.- Traces are relayed. With
signals: [traces], OTLP trace spans are accepted (gRPCTracesService, or HTTP on/v1/traces) and forwarded as a raw pass-through: spans are relayed verbatim — trace IDs, span IDs, attributes, events, and resource are untouched (an OTLP-in → OTLP-out relay). Traces need an OTLP export strategy withsignals.traces.enabled: true— the traces signal on the export side gates the relay; without it, ingested spans are discarded and the agent logs a throttled warning. - Limits. gRPC accepts payloads up to 4 MiB (the OTel SDK default); the HTTP server applies a 30-second read timeout.
- Traces are relayed. With
Operational notes¶
- Observability. The agent exposes
senhub_agent_otlp_receiver_ingested_total(items accepted, bysignal) andsenhub_agent_otlp_receiver_dropped_total(discarded, bysignal+reason—no_sinkwhen logs/traces arrive with no export strategy,unmappedfor a metric with an unrecognized data type). A risingdropped{reason="no_sink"}means a sender is pushing logs/traces the agent has nowhere to relay to. - A bind failure (port already taken) surfaces at probe start, not silently at runtime.
- The listener accepts plaintext OTLP. Keep it on localhost or a trusted network segment; for cross-network ingestion put a TLS terminator or an OTel collector in front.
- Shutdown is graceful on both protocols: in-flight requests finish before the agent exits.