Skip to main content
Spree supports OpenTelemetry, the open standard for distributed tracing. Install the optional spree_opentelemetry gem, point it at your collector with the same environment variables every other OpenTelemetry service uses, and Spree exports traces — no code changes, no vendor lock-in. Traces flow to any OpenTelemetry-compatible backend: Grafana Tempo, Jaeger, Datadog, Honeycomb, New Relic, Dynatrace, and others.

Setup

Add the gem to your application’s Gemfile:
Then configure the exporter through the standard OpenTelemetry environment variables:
That is the entire setup. Without an exporter configured, the gem stays dormant and adds no overhead. OTEL_SDK_DISABLED=true turns telemetry off regardless of any other setting. Other standard variables work as documented in the OpenTelemetry SDK configuration reference, including sampling:

What gets traced

Two layers combine into one trace per request or job. Framework spans come from the official Rails auto-instrumentation: HTTP requests, controller actions, database queries, background job enqueues and executions, mail deliveries, and outbound HTTP calls. Trace context carries across the job boundary, so work that happens in a background job stays connected to the request that caused it. Commerce spans come from Spree itself: A completed checkout, for example, produces one trace containing the HTTP request, the carts.complete workflow and its steps, the payment gateway call, the database work, and — linked from it — the background jobs and webhook deliveries the order triggered. Spree also propagates W3C Trace Context headers on outbound webhooks, so a system receiving your webhooks can join its own spans to the trace that produced the event.

Span attributes and personal data

Span attributes never contain personal or sensitive data. They are limited to workflow and step names, gateway action names, payment method class names, event names, webhook destination hosts, and HTTP status codes. Order contents, customer emails, addresses, payment details, and webhook payloads are never attached to spans.

Metrics

Spree exports the trace signal. Request rates, error rates, and latency percentiles per endpoint, workflow, or gateway are derived from spans in the OpenTelemetry Collector with the span metrics connector:

Using with Sentry

Sentry and OpenTelemetry are complementary — Sentry’s error capture works independently of tracing, so having both installed (as spree-starter does) requires no special setup. For traces there are three arrangements: Sentry for errors, OpenTelemetry for traces (default). Nothing to configure. Just don’t also enable Sentry’s own performance tracing (traces_sample_rate) — that would instrument every request twice and produce two disconnected trace systems. Sentry as the trace backend. Sentry ingests OpenTelemetry spans directly through its OTLP integration. Order matters here: Sentry registers its span processor inside Sentry.init, which only works if the OpenTelemetry SDK is already installed — so install Spree’s telemetry explicitly at the top of the same initializer:
A DSN alone does not enable tracing; config.otlp.enabled is the explicit opt-in (Sentry bills for ingested spans, so error capture never silently becomes span ingestion). Spree’s commerce spans — workflows, gateway calls, webhook deliveries — show up in Sentry’s trace view, and Sentry errors are linked automatically to the span that was active when they were captured. Both, via the collector. Point Spree at an OpenTelemetry Collector and fan out from there — one pipeline exporting to your tracing backend and another to Sentry’s OTLP endpoint. This is the most flexible arrangement for teams that want Grafana/Jaeger for latency work and Sentry for error triage over the same traces.

Correlating logs

To connect log lines to traces, tag your Rails logs with the current trace:

Trying it locally

Run Jaeger with an OTLP receiver and point Spree at it:
Place a test order and open http://localhost:16686 to see the trace.

Code-level configuration

Everything routine is controlled by environment variables. A SpreeOpenTelemetry.configure block exists for the rest — adding instrumentation for libraries your app uses, removing a default, or advanced SDK tuning:

Instrumenting your own code

Spree’s spans are built on ActiveSupport::Notifications, and yours can be too — or use the OpenTelemetry API directly:
Custom workflows get traced automatically: every Spree::Workflow run, step, and hook dispatch is instrumented by the framework, including workflows your application or extensions define.