Skip to content

Send traces to your backend

IRIS records every turn in its own session logs, and the web console's Call trace and Sessions screens read those. You need nothing else to see what a turn did.

For span-level detail (each pipeline stage, each model call, each outbound HTTP call) IRIS emits OpenTelemetry traces and sends them over OTLP to a backend you run: Arize Phoenix, Jaeger, Grafana Tempo, Honeycomb, an OpenTelemetry Collector, or anything else that accepts OTLP. IRIS bundles no trace UI.

With no endpoint set, nothing is exported, and /healthz reports "tracing_enabled": false with no error.

The settings

IRIS reads the standard OpenTelemetry variables, the way the OpenTelemetry SDK reads them:

Variable What it does
OTEL_EXPORTER_OTLP_ENDPOINT Base URL of the backend. For OTLP/HTTP, /v1/traces is appended. Setting it turns export on.
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT Full traces URL, used as given. Wins over the base URL.
OTEL_EXPORTER_OTLP_PROTOCOL http/protobuf (default, port 4318) or grpc (port 4317). OTEL_EXPORTER_OTLP_TRACES_PROTOCOL overrides it for traces.
OTEL_EXPORTER_OTLP_HEADERS Headers to send, such as an API key: key1=value1,key2=value2.
OTEL_SERVICE_NAME The service name traces are filed under. Default: iris. OTEL_RESOURCE_ATTRIBUTES works too.
OTEL_SDK_DISABLED=true or OTEL_TRACES_EXPORTER=none Turns export off even with an endpoint set.

The exporter also reads the standard timeout, compression and TLS certificate variables (OTEL_EXPORTER_OTLP_TIMEOUT, OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_CERTIFICATE and their _TRACES_ forms).

Two IRIS settings choose which libraries get automatic client spans while export is on. Both default to on:

Variable What it does
IRIS_OTEL_LANGCHAIN_ENABLED LangChain spans (OpenInference attributes: model, messages, tokens).
IRIS_OTEL_HTTPX_ENABLED A span for every outbound httpx call.

The IRIS API traces when an endpoint is set. The channel gateway also needs IRIS_CHANNEL_GATEWAY_TRACING_ENABLED=1.

Spans are batched before they are sent. Each batch sent is logged as one iris.egress line naming the host, like every other outbound call.

Traces carry your conversations

LangChain spans include prompts and model replies. A backend on this machine keeps them here; a hosted backend receives them. Point the endpoint at a remote service only if you mean to send it that data.

Put the variables in .env (see .env.example) or export them before iris serve. Under Docker Compose, .env is passed to the containers. From inside a container, the host is host.docker.internal, not 127.0.0.1.

Phoenix

Arize Phoenix runs as its own process. Its UI and its OTLP/HTTP receiver share port 6006:

pip install arize-phoenix          # in an environment of its own, not IRIS's
phoenix serve                      # UI at http://127.0.0.1:6006
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:6006
iris serve

Phoenix files traces under a project. IRIS sets the openinference.project.name resource attribute to the service name, so they land in the iris project.

Jaeger

The all-in-one image accepts OTLP on 4317 (gRPC) and 4318 (HTTP):

docker run --rm --name jaeger \
  -p 127.0.0.1:16686:16686 -p 127.0.0.1:4317:4317 -p 127.0.0.1:4318:4318 \
  jaegertracing/all-in-one:latest
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318
iris serve

Open http://127.0.0.1:16686 and pick the iris service. For gRPC instead, set OTEL_EXPORTER_OTLP_PROTOCOL=grpc and use port 4317.

Any backend, through an OpenTelemetry Collector

A collector receives OTLP from IRIS and forwards it wherever you like: Grafana Tempo, Honeycomb, a vendor, or several at once. A minimal collector.yaml that receives OTLP and forwards to Tempo:

receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318
      grpc:
        endpoint: 0.0.0.0:4317
processors:
  batch: {}
exporters:
  otlp/tempo:
    endpoint: tempo:4317
    tls:
      insecure: true
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp/tempo]
docker run --rm -p 127.0.0.1:4318:4318 -p 127.0.0.1:4317:4317 \
  -v "$PWD/collector.yaml:/etc/otelcol-contrib/config.yaml" \
  otel/opentelemetry-collector-contrib:latest
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318
iris serve

A hosted backend that speaks OTLP directly needs no collector. Honeycomb, for example:

export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io
export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=<your API key>"

Check it

curl -s localhost:8003/healthz

tracing_enabled is true, otlp_endpoint shows where spans go (without any credentials), otel_targets lists the instrumented libraries, and observability_error is null. Send a chat message and the trace appears in your backend within a few seconds.