Skip to content

Send telemetry with OpenTelemetry (OTLP)

Pulse accepts logs, traces and metrics over OTLP/HTTP. You use the standard OpenTelemetry SDKs and exporters, with no proprietary agent. This page covers the endpoints, how to authenticate, the limits and how Pulse maps what you send.

You need a project ingest key; see Send your first logs for how to create one.

Through the web address of your company:

Signal URL
Logs https://acme.orbit.inortix.com/otlp/v1/logs
Traces https://acme.orbit.inortix.com/otlp/v1/traces
Metrics https://acme.orbit.inortix.com/otlp/v1/metrics

Bodies are application/x-protobuf or application/json. The Content-Encoding header may be gzip, deflate, zstd or br. Errors are answered with a google.rpc.Status body in the encoding of the request.

Send the ingest key in one of two headers:

Headers
X-Pulse-Key: <ingest key>
Authorization: Bearer <ingest key>

The key decides the project. Anything in the payload that names a project is ignored.

The standard OpenTelemetry environment variables work. The exporter appends /v1/traces, /v1/logs and /v1/metrics to the base endpoint.

Environment
OTEL_EXPORTER_OTLP_ENDPOINT=https://acme.orbit.inortix.com/otlp
OTEL_EXPORTER_OTLP_HEADERS=X-Pulse-Key=<ingest key>
OTEL_SERVICE_NAME=checkout
OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=staging
OTEL_TRACES_SAMPLER_ARG=1

OTEL_TRACES_SAMPLER_ARG is the sampling ratio when you use a ratio sampler.

OTLP resource attribute Pulse field
service.name service
service.version version
deployment.environment.name env
host.name host
telemetry.sdk.language source

All resource attributes are also kept as tags. OTLP severity numbers map to Pulse statuses (FATAL becomes critical). The bounds are the same as for JSON logs: 256 attributes, 128 tags, keys 256 bytes, values 16 KiB, messages 64 KiB, nesting depth 8.

A request can succeed in part. Pulse answers 200 with a partialSuccess object and keeps the valid records:

Signal What partialSuccess counts as rejected
Logs rejectedLogRecords: records outside the project’s retention window or more than 2 hours in the future
Traces rejectedSpans: spans outside retention, more than 2 hours in the future, or without a trace or span id
Metrics rejectedDataPoints: points outside retention or in the future, exponential histograms and summaries (not supported yet), invalid names or buckets, and points of new series over the daily series limit. The first reason is in errorMessage.

When a daily quota is crossed, the records that fit are kept and the rest rejected, with the reason in errorMessage.

  • At most 10,000 records.
  • Body size per key: default 5 MiB, at most 16 MiB (set when the key is created).
  • Decompressed size at most 8 times the key’s body limit, capped at 64 MiB.
  • Each key has a records-per-minute budget that is all-or-nothing per request: an over-budget request gets 429 with Retry-After and stores nothing.
Field Source
kind OTLP span kind: server, client, producer, consumer, otherwise internal
status error when the OTLP status code is ERROR, otherwise ok; the status message is kept
entry span true for service entry spans: no parent, server or consumer kind, or a remote parent. Entry spans define a service’s requests, errors and latency.
resource (the endpoint) http.request.method plus http.route for HTTP servers (GET /orders/{id}); db.query.summary or db.operation.name plus db.collection.name for databases; messaging.operation.type plus messaging.destination.name; rpc.service and rpc.method; otherwise the span name (at most 512 bytes)
peer.service For client and producer spans: peer.service, else db.system.name, messaging.system, server.address or the host of url.full
error The first exception event (exception.type, exception.message, exception.stacktrace, stack up to 32 KiB); otherwise the status message and the error.type attribute on error spans
events Up to 128 events with their attributes

Pulse rolls entry spans and client spans up per minute (hits, errors, duration and a latency sketch for quantiles). All error traces and slow traces are retained; the rest are sampled at a configured rate, and the rollups stay complete.

Use the same service name (service.name) in your logs and in your traces, so that logs, traces and errors meet under one service. If your logging library adds the current trace_id and span_id to log records, a log opens its trace and a trace opens its logs.