RightSignals is a standards-first error tracking and trace-debugging product. The reporting side is intentionally open; the product value sits in grouping, correlation, workflow, and the operator UI.
RightSignals is OpenTelemetry-native. No proprietary SDK is required or published — not for Ruby, not Crystal, not any language. The "SDK" is the official OpenTelemetry library for your language. Add the OTel gems, point the OTLP exporter at this host with a bearer token, and you are reporting in minutes — not days. Agents: see /llms.txt.
Three core nouns, each mapped to OpenTelemetry. The supporting nouns hang off them.
| Noun | What it is | OpenTelemetry |
|---|---|---|
| Trace | One request's journey — a tree of spans (HTTP handler, DB query, outbound call) with timing and status. Every request produces one, error or not. Powers performance / APM. | Trace / Span |
| Occurrence | One time something broke — a single error instance captured from a trace's exception span event (error-log capture is planned). Carries the specific stack trace, plus both a trace_id and a fingerprint. | exception event (our projection) |
| Issue | The defect itself — all occurrences sharing a fingerprint, with status (open / resolved), first & last seen, count, and regression markers. This is what you triage and resolve. | grouping over exceptions |
Two keys, two questions.
A
trace_id
is which request (shared by every span in one request); a
fingerprint
is which bug — a hash of exception type + normalized stack frames, shared across requests. A trace has no fingerprint; an occurrence has both. Example: six real occurrences of one RuntimeError share one
fingerprint
so they collapse into a single Issue — but each has a different
trace_id
(six separate requests). The same fingerprint groups them; the differing trace_ids do not.
Hierarchy: Trace → Spans → (a span's exception) → Occurrence → grouped by fingerprint → Issue.
One analogy: the Trace is the flight recorder of one journey; an Occurrence is one alarm that went off; an Issue is "this alarm keeps going off."
Today the reporting path into RightSignals is open, not proprietary.
Telemetry submission and private account automation have different blast radii. RightSignals treats those as separate keys on purpose.
| Approach | Upside | Downside | Verdict |
|---|---|---|---|
| One hidden key reused for telemetry and future account APIs | Smallest implementation surface and fewer things to explain. | Too restrictive for browser reporters and too much privilege to expose widely. | Rejected. |
| One always-visible key reused for everything | Simplest copy-paste onboarding. | Any client-side leak would also expose privileged account operations later. | Rejected. |
| Public reporter key plus private API key | Submission setup stays easy, browser use is possible, and privileged operations stay on a separately rotatable key. | One extra concept for operators to manage. | Chosen. |
RightSignals does not currently ship a proprietary reporting SDK, a proprietary wire protocol, or a proprietary collector agent. The proprietary layer is the product behavior above telemetry transport.
| Layer | Open Option | Proprietary Option | RightSignals Today |
|---|---|---|---|
| Reporting protocol | OTLP over HTTP or gRPC | Custom vendor ingestion format | OTLP only. No custom wire format is shipped. |
| Runtime instrumentation | Official OpenTelemetry SDKs and auto-instrumentation where available | Vendor-specific reporting gems or agents | Use OpenTelemetry libraries. RightSignals does not ship its own Rails reporting gem. |
| Edge collection | OpenTelemetry Collector | Vendor-owned sidecar or daemon | Collector profile is provided. No proprietary agent is shipped. |
| Product behavior | Raw telemetry plus portable context | Grouping logic, UI, workflow rules, issue lifecycle | This is where RightSignals is product-specific today. |
| API surface | OpenAPI / MCP / A2A style interfaces | UI-only or private APIs | Planned direction. Today the open integration surface is OTLP ingest; broader public product APIs are not shipped yet. |
RightSignals uses standard OpenTelemetry gems instead of a proprietary reporting gem. This means slightly more setup up front, but your instrumentation stays portable across vendors.
Use the Ruby metapackage for the fastest first pass, or swap in the narrower
opentelemetry-instrumentation-rails
gem if you want tighter control.
gem "opentelemetry-sdk" gem "opentelemetry-exporter-otlp" gem "opentelemetry-instrumentation-all"
Put this in
config/initializers/opentelemetry.rb
so Rails configures tracing on boot.
# config/initializers/opentelemetry.rb
require "opentelemetry/sdk"
require "opentelemetry/instrumentation/all"
require "opentelemetry-exporter-otlp"
OpenTelemetry::SDK.configure do |c|
c.service_name = ENV.fetch("OTEL_SERVICE_NAME", "your-app")
c.resource = OpenTelemetry::SDK::Resources::Resource.create(
"service.version" => ENV.fetch("HEROKU_SLUG_COMMIT", "unknown"),
"deployment.environment.name" => ENV.fetch("RAILS_ENV", "production")
)
c.use_all
end
service.version
is set in code from the runtime build variable (e.g.
HEROKU_SLUG_COMMIT
on Heroku). Do NOT use
OTEL_RESOURCE_ATTRIBUTES
for this — that env var does not expand
$VARS
, so the literal string would be sent instead of the actual commit SHA.
These tell the OTLP exporter where to send data and authenticate with the project's reporter key.
Get your reporter key from the project settings page
after signing in.
Use a literal space after
Bearer
— do not URL-encode it as
%20.
OTEL_EXPORTER_OTLP_ENDPOINT=https://app.rightsignals.com OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer YOUR_REPORTER_KEY OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf OTEL_SERVICE_NAME=your-app
The reporter key (
rsp_…
) is per-project and publishable — safe to set in CI config or a collector. If it leaks, the risk is spammy telemetry only.
service.version
and
deployment.environment.name
are set from
HEROKU_SLUG_COMMIT
and
RAILS_ENV
in the initializer above, so they don't need separate env vars.
After deploy, load a few Rails pages, run a background job, or trigger an exception path. Your service should appear in the RightSignals dashboard within seconds.
| Area | Typical Proprietary Rails Tooling | RightSignals Today |
|---|---|---|
| Installation | Add the vendor gem and run its installer. | Add OpenTelemetry gems and a Rails initializer. |
| Error capture | Vendor SDK emits proprietary error events. | Exceptions captured from OTel span events, grouped into issues. |
| Tracing | Some tools add traces, some stay exception-centric. | Trace and span linkage is part of the model from the start. |
| Migration cost | Higher — app code and payload shape are vendor-specific. | Lower — OTLP and OTel stay portable. Change the exporter, keep everything else. |
| Feature breadth | Often broader on day one: alerting, replay, cron monitors. | Focused: issues, occurrences, releases, traces, and guided setup. |
Unhandled exceptions in instrumented code paths (controller actions, background jobs) are captured automatically. But when you rescue an error and want RightSignals to still track it as an issue, you need to tell OpenTelemetry about it explicitly.
tracer = OpenTelemetry.tracer_provider.tracer("myapp.external")
tracer.in_span("model.unavailable", attributes: {
"model.name" => "gemini-3.1-flash",
"model.status" => "429",
"model.detail" => "Quota exceeded for free tier"
}) do |span|
# Mark the span as errored — shows red in trace views
span.status = OpenTelemetry::Trace::Status.error("Model unavailable: gemini-3.1-flash (429)")
# Record an exception event — this is what creates a RightSignals issue
span.record_exception(RuntimeError.new("Model unavailable: gemini-3.1-flash (429)"))
end
Why both calls?
| Call | What It Does | Without It |
|---|---|---|
span.status = error
|
Marks the span red in trace views. | Span looks green even though something failed. |
span.record_exception
|
Adds an
exception
event with
exception.type
,
exception.message
, and
exception.stacktrace
attributes. This is the
OTel exception semantic convention
that RightSignals keys on to group and count occurrences as issues.
|
The span shows as errored in traces but no trackable issue is created. |
Sampling is not implemented in the shipped RightSignals Rails app or the current collector profile. The provided collector config batches traffic, but it does not currently include a sampling processor.
| Topic | Current State | What To Do Today |
|---|---|---|
| App-side ingest sampling | Not implemented in RightSignals. | Sample before data reaches RightSignals if you have high request volume. |
| Collector gateway sampling | Not in the shipped profile. The profile currently does batching only. | Add upstream collector sampling in your own deployment if needed. |
| Ingest protection | Bearer-token auth exists; rate limiting and sampling controls do not yet. | Treat the current MVP as best for controlled early workloads, not unlimited firehose traffic. |
In practice, the safe current posture is: batch everywhere, sample upstream for noisy success traffic, and keep failure paths highly visible.
The RightSignals CLI lets you query issues, traces, occurrences, and events from your terminal.
brew install aluminumio/tap/rightsignals export RIGHTSIGNALS_TOKEN=rsg_... # from Setup page
| Command | Purpose |
|---|---|
rightsignals issues --status=open
|
List open issues |
rightsignals issues <id>
|
Stack trace and recent occurrences |
rightsignals occurrences <id>
|
Full occurrence detail |
rightsignals traces <id>
|
Request trace waterfall |
rightsignals issues:resolve <id>
|
Mark resolved |
rightsignals issues:reopen <id>
|
Reopen |
Add
-j
for JSON output,
-e ENV
to filter by environment,
--service=NAME
to filter by service.
Add this skill to your Claude Code setup so it can find and fix production exceptions automatically.
Create the file
~/.claude/skills/rightsignals-debug/SKILL.md
with the contents below.
--- name: rightsignals-debug description: Use when debugging production exceptions, finding errors in an application, or when the user wants to see what's broken in production. user-invocable: true argument-hint: [--status=open] [issue-id] allowed-tools: Bash, Read, Edit, Glob, Grep --- Find and fix production exceptions using the RightSignals CLI. ## Setup ```bash brew install aluminumio/tap/rightsignals export RIGHTSIGNALS_TOKEN=rsg_... ``` ## Workflow ### 1. Find open issues ```bash rightsignals issues --status=open ``` Prioritize high-count or recently-seen issues. ### 2. Get the stack trace ```bash rightsignals issues <id> ``` The top application frame (not gems/libraries) is usually the fix site. ### 3. Find the source code Use the stack trace file and line number to locate the code in the codebase. ### 4. Check the request trace (optional) ```bash rightsignals traces <trace-id> ``` ### 5. Fix and verify Apply the fix and run specs. ### 6. Resolve ```bash rightsignals issues:resolve <id> ``` RightSignals auto-reopens if the issue regresses.
Once installed, use
/rightsignals-debug
or ask Claude "what's broken in production?" and it will use the CLI to find and fix issues.