Skip to content

OTLP ingestion

Perseval embeds a loopback-only OTLP/HTTP trace receiver. It accepts POST /v1/traces and exposes no UI, query, MCP, health, or administration routes on that listener.

CapabilitySupport
OTLP/HTTP JSONYes, application/json
OTLP/HTTP protobufYes, application/x-protobuf
Gzip request bodyYes
Official named JSON enumsYes
Numeric JSON enumsYes
OTLP/gRPCNot yet
Remote/non-loopback bindingRejected

The default endpoint is http://127.0.0.1:4318/v1/traces, but the effective endpoint shown in Sources is authoritative.

An accepted request is acknowledged only after Perseval has:

  1. stored the exact compressed wire payload as a content-addressed blob;
  2. stored the normalized span batch as another versioned blob; and
  3. committed the journal row that references both.

DuckDB projection, analysis, and UI updates occur after acknowledgement. This keeps ingest latency independent from trace rendering while preserving admitted data across restart.

  • 200 means the admitted part of the request was durably journaled.
  • 200 with OTLP partial_success.rejected_spans means some individual spans were permanently rejected; inspect and repair the producer data.
  • 400 means malformed permanent input; retry only after changing it.
  • 413 means a wire, decoded-size, span-count, or attribute-count limit was exceeded; split the batch.
  • 415 means the content type is unsupported.
  • 429 means the bounded admission queue is full. Honor Retry-After, back off, and retry the same batch.
  • 503 means the writer is unavailable or shutting down. Retry with backoff.

Perseval never silently drops an admitted span. Identical redelivery is a no-op by canonical content hash. Changed content for the same live span identity creates a new version.

  • 16 MiB maximum wire body;
  • 64 MiB maximum decoded body;
  • 100,000 spans per request;
  • 1,024 attributes per span;
  • 64 queued batches and 256 MiB queued bytes;
  • Retry-After: 1 on overload.

These are request and queue limits, not a recommendation to send 100,000 spans in one batch. Prefer smaller retryable batches.

Sources → Import trace file accepts bounded OTLP JSON or protobuf while the network receiver is disabled or enabled. Import uses the same decoder, journal, projection, deduplication, project routing, and committed-delta path as the live receiver.

Normalization retains resource and instrumentation scope, trace state, flags, status, dropped counts, nanosecond timestamps, typed attributes, events, and SpanLinks. Known prompts, messages, inputs, outputs, reasoning, source code, and tool payloads are externalized to blobs rather than displayed automatically.

Continue with the agent telemetry contract for deterministic failure analysis.