Skip to content

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:

export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc

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.name and 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.name would 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 / _max aggregates (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 (gRPC LogsService, 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 with service.name=my-app arrives as my-app, so applications stay distinguishable at the backend. Agent context (tenant, site, environment, the telemetry.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-app was stored under the agent's service.name, making applications indistinguishable by that attribute. If a dashboard or query relies on ingested logs carrying the agent's service.name, point it at the agent's own logs or at telemetry.relay.instance.id instead.

    • Traces are relayed. With signals: [traces], OTLP trace spans are accepted (gRPC TracesService, 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 with signals.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.

Operational notes

  • Observability. The agent exposes senhub_agent_otlp_receiver_ingested_total (items accepted, by signal) and senhub_agent_otlp_receiver_dropped_total (discarded, by signal + reasonno_sink when logs/traces arrive with no export strategy, unmapped for a metric with an unrecognized data type). A rising dropped{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.