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: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:
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:Code-level configuration
Everything routine is controlled by environment variables. ASpreeOpenTelemetry.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 onActiveSupport::Notifications, and yours can be
too — or use the OpenTelemetry API directly:
Spree::Workflow run, step,
and hook dispatch is instrumented by the framework, including workflows your
application or extensions define.
