rails_error_dashboard 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +109 -48
- data/lib/rails_error_dashboard/commands/find_or_increment_error.rb +21 -0
- data/lib/rails_error_dashboard/version.rb +1 -1
- metadata +22 -27
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4aa6cdee526bf9210f3762861a373dbefbe99b9ed94ecdb5f6464fb781bdddb4
|
|
4
|
+
data.tar.gz: 3a7977ff26332c869b5bf6e4e5316d3470e978ff736184dcc4119f0982822c4c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ea46f47e2e96da83cf0c83d94596e63d63ab0dafeea5a3f696b2a1021b9eb57026485c9fec4d0827e8f8fcd4852fd587a69d28d3890ec14a5ec295d549826264
|
|
7
|
+
data.tar.gz: 4ea0ff21bbcb9177fd43297a5145e17a6316ec52f2f8a5370b30e36879a32810cd289b22e7c1d66abb2b9f9a66593bc2e013ab3ccfc19af1c0ffc46c42863537
|
data/README.md
CHANGED
|
@@ -7,27 +7,100 @@
|
|
|
7
7
|
[](https://github.com/sponsors/AnjanJ)
|
|
8
8
|
[](https://buymeacoffee.com/anjanj)
|
|
9
9
|
|
|
10
|
-
**Self-hosted
|
|
10
|
+
**Rails-native error tracking for failure investigation — see the Ruby state and Rails runtime health behind every exception. Self-hosted, inside your app, in your own database. The gem is MIT and free forever.**
|
|
11
11
|
|
|
12
12
|
```ruby
|
|
13
|
-
gem
|
|
13
|
+
gem "rails_error_dashboard"
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
```bash
|
|
17
|
+
bundle install
|
|
18
|
+
rails generate rails_error_dashboard:install
|
|
19
|
+
rails db:migrate
|
|
20
|
+
```
|
|
17
21
|
|
|
18
|
-
|
|
22
|
+
Open `/red` and raise a test exception. No monitoring account or ingestion service is required.
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
[Try the live demo](https://rails-error-dashboard.anjan.dev) (`gandalf` / `youshallnotpass`) · [Read the documentation](https://anjanj.github.io/rails_error_dashboard/) · [View on RubyGems](https://rubygems.org/gems/rails_error_dashboard)
|
|
25
|
+
|
|
26
|
+
> **Beta:** RED is functional and extensively tested, but configuration and APIs may change before 1.0. Supports Rails 7.0–8.1 and Ruby 3.2–4.0 (CI runs Ruby 3.2–3.4 against every supported Rails version; Ruby 4.0 is verified by the maintainer).
|
|
27
|
+
|
|
28
|
+
## See the Ruby state and Rails runtime health behind every exception
|
|
29
|
+
|
|
30
|
+
Rails Error Dashboard (RED) is an open-source, self-hosted Rails engine for investigating production failures. It helps you answer not only **what failed**, but **what was happening inside Ruby and Rails when it failed**.
|
|
31
|
+
|
|
32
|
+
- Inspect local variables and the raising object's instance variables before the stack unwinds.
|
|
33
|
+
- See error-time Active Record, Puma, job queue, GC, memory and process health.
|
|
34
|
+
- Follow the SQL, cache, controller, job, mailer and other Rails events leading to the exception.
|
|
35
|
+
- Stay safe during error floods with progressive, count-preserving storm protection.
|
|
36
|
+
- Keep exception data on infrastructure you control.
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
|
|
40
|
+
## The questions RED helps you answer
|
|
41
|
+
|
|
42
|
+
A stack trace tells you where execution stopped. RED helps you investigate the state behind it:
|
|
43
|
+
|
|
44
|
+
- What did `params`, local variables and objects such as `@order` contain?
|
|
45
|
+
- Was the Active Record pool exhausted?
|
|
46
|
+
- Was Puma out of thread capacity or building a backlog?
|
|
47
|
+
- Were jobs failing or queues growing?
|
|
48
|
+
- Was the process under GC, memory, descriptor or system pressure?
|
|
49
|
+
- Which SQL queries, cache operations or Rails events preceded the failure?
|
|
50
|
+
- Did a deploy introduce the error?
|
|
51
|
+
- Can the failing request become a cURL reproduction or RSpec regression-test scaffold?
|
|
52
|
+
|
|
53
|
+
## What makes RED different
|
|
54
|
+
|
|
55
|
+
### Failure-time Ruby state
|
|
56
|
+
|
|
57
|
+
Optionally capture local variables and — something no other error tracker does — the raising receiver's instance variables at `TracePoint(:raise)`, with bounded serialization and your Rails `filter_parameters` applied to sensitive values. Binding objects are never retained.
|
|
21
58
|
|
|
22
|
-
###
|
|
59
|
+
### Failure-time Rails health
|
|
23
60
|
|
|
24
|
-
|
|
61
|
+
Attach connection-pool, Puma, background-job, GC, memory, file-descriptor, TCP, RubyVM and YJIT state to the error record, refreshed on every captured occurrence — not merely to a separate periodic metrics chart. Every APM has these as time-series; none attaches them to the error. Opt-in; the procfs-backed fields are Linux-only.
|
|
25
62
|
|
|
26
|
-
|
|
63
|
+
### Monitoring that degrades safely
|
|
64
|
+
|
|
65
|
+
During an error flood, RED progressively reduces captured context and database work, keeps a fresh exemplar every minute, records the storm in a Storm History ledger and reconciles exact in-process occurrence counts onto the error records. On by default.
|
|
66
|
+
|
|
67
|
+
### Rails-specific investigation
|
|
68
|
+
|
|
69
|
+
Connect exceptions with SQL, caching, Active Job, Action Cable, Active Storage, Rack::Attack, deprecations and other Rails subsystems from one dashboard.
|
|
70
|
+
|
|
71
|
+
### Things no other tracker does
|
|
72
|
+
|
|
73
|
+
Verified against Sentry, Honeybadger, AppSignal, Rollbar, Bugsnag, Airbrake, Raygun, New Relic, Datadog, Scout, Skylight and every self-hosted Rails tracker in August 2026 ([the ledger](.shipkit/research/red-unique-features-verified.md)):
|
|
74
|
+
|
|
75
|
+
- **Copy as RSpec** — a runnable request spec generated from the captured request (Sentry offers curl only).
|
|
76
|
+
- **Swallowed-exception aggregate** — raise-vs-rescue ratio per location, no APM span needed (Datadog's paid APM detects rescued exceptions but keeps no aggregate).
|
|
77
|
+
- **Rack::Attack ledger** — throttle, blocklist and track events persisted with per-rule stats and an AI-crawler classifier; rack-attack ships no UI of its own.
|
|
78
|
+
- **Codeberg issue tracking**, alongside GitHub, GitLab and Linear with two-way sync.
|
|
79
|
+
- **The tracker instruments itself** — its capture pipeline exported as OpenTelemetry spans, so you can audit its overhead in your own APM.
|
|
80
|
+
|
|
81
|
+
## How RED compares
|
|
82
|
+
|
|
83
|
+
| Basic embedded tracker | General SaaS monitoring | RED |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| Stack trace and context | Cross-language telemetry and managed ingestion | Deep failure-time Ruby/Rails state inside the application boundary |
|
|
86
|
+
| Lightweight and local | Strong distributed and frontend observability | Rails-specific operational investigation and storm-safe local capture |
|
|
87
|
+
|
|
88
|
+
That makes RED a self-hosted Sentry alternative for teams that want Rails-specific depth and need error data to stay inside the application boundary — not a replacement for cross-language telemetry. RED has no mobile SDKs, no merge/split, no MCP server and no hosted operations.
|
|
89
|
+
|
|
90
|
+
## Choose how you run it
|
|
91
|
+
|
|
92
|
+
- Store data in the application's existing PostgreSQL, MySQL/Trilogy or SQLite database.
|
|
93
|
+
- Isolate monitoring writes in a separate error database.
|
|
94
|
+
- Use synchronous writes, or async logging through Sidekiq or Solid Queue (GoodJob is detected for job-health stats but is not an async adapter).
|
|
95
|
+
- Track several Rails applications through a shared database.
|
|
96
|
+
|
|
97
|
+
No RED licence or event-ingestion fee, and no plan limits — your database is the only cap, and storm protection deliberately sheds context during floods.
|
|
98
|
+
|
|
99
|
+
---
|
|
27
100
|
|
|
28
101
|
### Screenshots
|
|
29
102
|
|
|
30
|
-
**Dashboard Overview** —
|
|
103
|
+
**Dashboard Overview** — Live error stats, severity breakdown, and trend charts.
|
|
31
104
|
|
|
32
105
|

|
|
33
106
|
|
|
@@ -49,25 +122,12 @@ gem 'rails_error_dashboard'
|
|
|
49
122
|
|
|
50
123
|
---
|
|
51
124
|
|
|
52
|
-
##
|
|
53
|
-
|
|
54
|
-
- **Solo bootstrappers** who need professional error tracking without recurring costs
|
|
55
|
-
- **Indie SaaS founders** building profitable apps on tight budgets
|
|
56
|
-
- **Small dev teams** (2-5 people) who hate SaaS bloat
|
|
57
|
-
- **Privacy-conscious apps** that need to keep error data on their own servers
|
|
58
|
-
- **Side projects** that might become real businesses
|
|
59
|
-
|
|
60
|
-
## What It Replaces
|
|
125
|
+
## Safety, performance and compatibility
|
|
61
126
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
| SaaS pricing tiers and usage limits | Unlimited errors, unlimited projects |
|
|
67
|
-
| Vendor lock-in with proprietary APIs | 100% open source, fully portable |
|
|
68
|
-
| Complex SDK setup and external services | 5-minute Rails Engine installation |
|
|
69
|
-
| Pay extra for local variable capture (Sentry) | Local + instance variables included free |
|
|
70
|
-
| No tool detects silently rescued exceptions | Swallowed exception detection built in |
|
|
127
|
+
- **Host-app safety** — nothing in the capture path raises into your app; every subscriber and callback is rescue-wrapped, `Thread.current` is cleaned up in `ensure`, and the original exception is always re-raised. Variables, health and breadcrumbs are opt-in and off by default; storm protection is on by default and fails open.
|
|
128
|
+
- **Performance** — the storm-protection hot path is a digest plus an atomic increment with no I/O; the figures quoted below are a maintainer's single-machine measurements and no benchmark script ships with the gem yet.
|
|
129
|
+
- **Security** — HTTP Basic Auth or your own `authenticate_with` lambda (Devise, Warden, session); your Rails `filter_parameters` are applied to params, variables and breadcrumbs; prompts are never recorded by LLM observability. Vulnerability reports: [SECURITY.md](SECURITY.md).
|
|
130
|
+
- **Compatibility** — Rails 7.0–8.1, Ruby 3.2–4.0, PostgreSQL, MySQL/Trilogy or SQLite; `turbo-rails` plus ActionCable are needed for live updates (no polling fallback); the gem's own CSS/JS is inline but Bootstrap JS, Chart.js, highlight.js and Google Fonts load from CDNs, so it is not air-gap clean.
|
|
71
131
|
|
|
72
132
|
---
|
|
73
133
|
|
|
@@ -75,14 +135,14 @@ gem 'rails_error_dashboard'
|
|
|
75
135
|
|
|
76
136
|
### Core (Always Enabled)
|
|
77
137
|
|
|
78
|
-
Error capture from controllers, jobs, and middleware. Custom-designed dashboard with dark/light mode, search, filtering, and real-time updates. Analytics with trend charts, severity breakdown, and spike detection. Workflow management with assignment, priority, snooze, mute/unmute (notification suppression), comments, and batch operations. Security via HTTP Basic Auth or custom lambda (Devise, Warden, session-based). Exception cause chains, enriched HTTP context, custom fingerprinting, CurrentAttributes integration, auto-reopen on recurrence, and sensitive data filtering — all built in.
|
|
138
|
+
Error capture from controllers, jobs, and middleware. Custom-designed dashboard with dark/light mode, search, filtering, and real-time updates (the latter with `turbo-rails` + ActionCable in the host). Analytics with trend charts, severity breakdown, and spike detection. Workflow management with assignment, priority, snooze, mute/unmute (notification suppression), comments, and batch operations. Security via HTTP Basic Auth or custom lambda (Devise, Warden, session-based). Exception cause chains, enriched HTTP context, custom fingerprinting, CurrentAttributes integration, auto-reopen on recurrence, and sensitive data filtering — all built in.
|
|
79
139
|
|
|
80
140
|
### Optional Features
|
|
81
141
|
|
|
82
142
|
<details>
|
|
83
143
|
<summary><strong>Storm Protection — Circuit Breaker + Adaptive Sampling</strong></summary>
|
|
84
144
|
|
|
85
|
-
When the error rate spikes (a bad deploy throwing thousands of errors a minute), the nightmare scenario for any in-process tracker is amplifying the outage with its own database writes. Storm protection
|
|
145
|
+
When the error rate spikes (a bad deploy throwing thousands of errors a minute), the nightmare scenario for any in-process tracker is amplifying the outage with its own database writes. Storm protection is designed to **shed the gem's own expensive work first** — ON by default. The behaviour is measured (see Overhead below), though a bundled, reproducible benchmark is still to come.
|
|
86
146
|
|
|
87
147
|
- **Per-fingerprint caps:** past N occurrences/minute per error, context is shed, then rows are sampled deterministically (a fresh exemplar is always kept each minute)
|
|
88
148
|
- **Global circuit breaker:** sustained floods flip the gem to count-only mode — zero per-event I/O, exact in-memory counts reconciled onto error records every 30s. Async mode is gated too (a SolidQueue enqueue is itself a DB write)
|
|
@@ -98,7 +158,7 @@ config.storm_open_threshold_per_second = 50 # per process
|
|
|
98
158
|
|
|
99
159
|
All thresholds are per process and individually configurable. Disable with one flag.
|
|
100
160
|
|
|
101
|
-
**
|
|
161
|
+
**Overhead:** the check is a digest plus an atomic increment; there is no I/O on the hot path. The maintainer's single-machine measurement (Apple Silicon, Ruby 4.0) was 2.4µs/error with protection active and calm, 2.95µs in count-only mode and 0.2µs when disabled, against a 5µs budget — a reproducible benchmark script is not yet part of the gem.
|
|
102
162
|
</details>
|
|
103
163
|
|
|
104
164
|
<details>
|
|
@@ -108,7 +168,7 @@ See exactly what happened before the crash — SQL queries, controller actions,
|
|
|
108
168
|
|
|
109
169
|
- Automatic capture — zero config beyond the enable flag
|
|
110
170
|
- N+1 query detection with aggregate patterns page
|
|
111
|
-
- Deprecation warnings with aggregate view
|
|
171
|
+
- Deprecation warnings with aggregate view (needs the host's deprecation behaviour to include `:notify`; only requests that later raised are seen)
|
|
112
172
|
- Custom breadcrumbs via `RailsErrorDashboard.add_breadcrumb("checkout started", { cart_id: 123 })`
|
|
113
173
|
- Safe by design — fixed-size ring buffer, thread-local, every subscriber wrapped in rescue
|
|
114
174
|
|
|
@@ -146,7 +206,7 @@ Cross-error N+1 detection grouped by SQL fingerprint, and aggregate deprecation
|
|
|
146
206
|
|
|
147
207
|

|
|
148
208
|
|
|
149
|
-
Requires breadcrumbs to be enabled.
|
|
209
|
+
Requires breadcrumbs to be enabled. Deprecations are seen only when the host's `ActiveSupport::Deprecation` behaviour includes `:notify` (the production default does not) and only inside requests that later raised.
|
|
150
210
|
|
|
151
211
|
[Complete documentation →](docs/FEATURES.md#n1-query-detection)
|
|
152
212
|
</details>
|
|
@@ -154,7 +214,7 @@ Requires breadcrumbs to be enabled.
|
|
|
154
214
|
<details>
|
|
155
215
|
<summary><strong>Operational Health Panels — Jobs, Database, Cache, ActionCable</strong></summary>
|
|
156
216
|
|
|
157
|
-
**Job Health** —
|
|
217
|
+
**Job Health** — Aggregates the queue stats captured on each error (Sidekiq, SolidQueue or GoodJob auto-detected; needs `enable_system_health`). Not a live queue view — a per-error table with adapter badge, failed count (color-coded), sorted worst-first.
|
|
158
218
|
|
|
159
219
|

|
|
160
220
|
|
|
@@ -184,12 +244,12 @@ config.enable_activestorage_tracking = true # requires enable_breadcrumbs = tru
|
|
|
184
244
|
<details>
|
|
185
245
|
<summary><strong>LLM Observability — Calls, Tokens, Cost, Tool Use</strong></summary>
|
|
186
246
|
|
|
187
|
-
Capture
|
|
247
|
+
Capture your app's LLM calls — through a Faraday middleware, OpenTelemetry GenAI spans or a manual notification; nothing is auto-instrumented — as breadcrumbs on the error that follows, with model, latency, token counts, estimated USD cost and tool-use requests. When a request crashes, you see the chat completion that preceded it: which model was called, how long it took, what it cost, and which tools it asked to invoke.
|
|
188
248
|
|
|
189
249
|
- Three capture paths — pick whichever matches your stack
|
|
190
250
|
- Cost estimated from a built-in pricing table (Claude 4.x, GPT-4o/o1, Gemini 2.5) — override per-model via `config.llm_pricing_overrides`
|
|
191
251
|
- Tool-call requests summarized inline; tool *execution* spans captured separately via the OTel path
|
|
192
|
-
-
|
|
252
|
+
- Prompts and completions are **never recorded** — only token counts and metadata (the `llm_observability_content_capture` flag is reserved and currently a no-op)
|
|
193
253
|
- Same host-app safety guarantees as the rest of the gem — never raises, never blocks the request, every callback rescue-wrapped
|
|
194
254
|
|
|
195
255
|
```ruby
|
|
@@ -343,7 +403,7 @@ config.enable_git_blame = true
|
|
|
343
403
|
<details>
|
|
344
404
|
<summary><strong>Code Path Coverage (Diagnostic Mode)</strong></summary>
|
|
345
405
|
|
|
346
|
-
Enable coverage via a dashboard button to see which production code paths were executed. Source code viewer overlays green checkmarks on executed lines and gray dots on unexecuted lines. Uses Ruby's `Coverage.setup(oneshot_lines: true)` — near-zero overhead, each line fires once. Zero overhead when off.
|
|
406
|
+
Enable coverage via a dashboard button to see which production code paths were executed. Source code viewer overlays green checkmarks on executed lines and gray dots on unexecuted lines. Uses Ruby's `Coverage.setup(oneshot_lines: true)` — near-zero overhead, each line fires once. Zero overhead when off. Diagnostic mode only: coverage is process-global (a multi-threaded Puma blends requests), held in memory and not persisted. No error tracker integrates this; Coverband does it standalone with persistence.
|
|
347
407
|
|
|
348
408
|
```ruby
|
|
349
409
|
config.enable_coverage_tracking = true # shows Enable/Disable buttons on error detail page
|
|
@@ -405,9 +465,9 @@ Seven analysis engines built in:
|
|
|
405
465
|
1. **Baseline Anomaly Alerts** — Statistical spike detection (mean + std dev) with intelligent cooldown
|
|
406
466
|
2. **Fuzzy Error Matching** — Jaccard similarity + Levenshtein distance to find related errors
|
|
407
467
|
3. **Co-occurring Errors** — Detect errors that happen together within configurable time windows
|
|
408
|
-
4. **Error Cascade Detection** — Identify
|
|
468
|
+
4. **Error Cascade Detection** — Identify potential cascades (A is followed by B is followed by C) with probability and delays — temporal association, not proven causation
|
|
409
469
|
5. **Error Correlation Analysis** — Correlate errors with app versions, git commits, and users
|
|
410
|
-
6. **Platform Comparison** — iOS vs Android vs
|
|
470
|
+
6. **Platform Comparison** — iOS vs Android vs API health metrics side-by-side
|
|
411
471
|
7. **Occurrence Pattern Detection** — Cyclical patterns (business hours, weekends) and burst detection
|
|
412
472
|
|
|
413
473
|
[Complete documentation →](docs/FEATURES.md#advanced-analytics-features)
|
|
@@ -437,7 +497,7 @@ config.enable_instance_variables = true
|
|
|
437
497
|
<details>
|
|
438
498
|
<summary><strong>Swallowed Exception Detection</strong></summary>
|
|
439
499
|
|
|
440
|
-
Detect exceptions that are raised but silently rescued — the hardest bugs to find.
|
|
500
|
+
Detect exceptions that are raised but silently rescued — the hardest bugs to find. Only Datadog's paid APM detects rescued exceptions (Ruby 3.3+, and only inside a traced request); RED does it free, without an APM span, and aggregates the raise-vs-rescue ratio per location — no other tracker does that.
|
|
441
501
|
|
|
442
502
|
- Uses TracePoint(`:raise`) + TracePoint(`:rescue`) to track exception lifecycle
|
|
443
503
|
- Identifies code paths where exceptions are caught but never logged or re-raised
|
|
@@ -478,7 +538,8 @@ config.enable_diagnostic_dump = true
|
|
|
478
538
|
Track Rack Attack security events (throttles, blocklists, tracks) as breadcrumbs attached to errors, with a dedicated summary page.
|
|
479
539
|
|
|
480
540
|
- Captures throttle, blocklist, and track events automatically
|
|
481
|
-
- Dashboard page at `/errors/rack_attack_summary` with event breakdown
|
|
541
|
+
- Dashboard page at `/errors/rack_attack_summary` with event breakdown and per-rule stats — rack-attack ships no UI of its own
|
|
542
|
+
- Classifies AI-agent user agents (GPTBot, ClaudeBot, …) on `track` events
|
|
482
543
|
- Requires breadcrumbs to be enabled
|
|
483
544
|
|
|
484
545
|
```ruby
|
|
@@ -496,7 +557,7 @@ Capture unhandled exceptions that crash the Ruby process via an `at_exit` hook
|
|
|
496
557
|
- Disk-based fallback: writes crash data to disk because the database may be unavailable during shutdown
|
|
497
558
|
- Imported automatically on next boot
|
|
498
559
|
- Captures exception details, backtrace, uptime, GC stats, thread count, and cause chain
|
|
499
|
-
-
|
|
560
|
+
- Honeybadger, Bugsnag and AppSignal have `at_exit` reporters too; RED's writes to disk and imports at next boot because the database may already be gone during shutdown
|
|
500
561
|
|
|
501
562
|
```ruby
|
|
502
563
|
config.enable_crash_capture = true
|
|
@@ -617,7 +678,7 @@ end
|
|
|
617
678
|
|
|
618
679
|
## Languages
|
|
619
680
|
|
|
620
|
-
|
|
681
|
+
RED ships in English with machine-translated previews for ten additional languages, covering the dashboard, its emails and its notification payloads. Native-speaking Rails developers are invited to review and improve them; once a locale has been reviewed it will be marked individually as community-reviewed. Eleven locales ship:
|
|
621
682
|
|
|
622
683
|
| Locale | Language | Status |
|
|
623
684
|
|---|---|---|
|
|
@@ -661,13 +722,13 @@ SQLite, PostgreSQL, and MySQL/Trilogy — in either shared or separate-database
|
|
|
661
722
|
Yes. It runs entirely inside your own Rails process — no external services, no SDK calling out, no per-event pricing. Error data never leaves your infrastructure.
|
|
662
723
|
|
|
663
724
|
**Does it capture local variables like Sentry?**
|
|
664
|
-
Yes — local **and** instance variables at the moment the exception is raised, via `TracePoint(:raise)`, with sensitive-data filtering and configurable limits.
|
|
725
|
+
Yes — local **and** instance variables at the moment the exception is raised, via `TracePoint(:raise)`, with sensitive-data filtering and configurable limits. It is opt-in. (Sentry's SDK can also capture locals as an opt-in option; RED adds instance variables and applies your Rails `filter_parameters` automatically.)
|
|
665
726
|
|
|
666
727
|
**Will a flood of errors take down my app?**
|
|
667
|
-
No. Storm protection (a circuit breaker with adaptive sampling, **ON by default**) makes the gem degrade itself first during error floods — occurrence counts stay exact while it sheds the expensive work.
|
|
728
|
+
No. Storm protection (a circuit breaker with adaptive sampling, **ON by default**) makes the gem degrade itself first during error floods — occurrence counts stay exact while it sheds the expensive work, and a Storm History page shows exactly what was shed. There is no I/O on the hot path — the check is a digest and an atomic increment.
|
|
668
729
|
|
|
669
730
|
**Does it work with my background jobs?**
|
|
670
|
-
Yes — it
|
|
731
|
+
Yes — errors raised in jobs are captured, and it can log errors asynchronously through Sidekiq or SolidQueue (or the in-process `:async` adapter). Sidekiq, SolidQueue and GoodJob are all auto-detected for the job-queue stats stored on each error.
|
|
671
732
|
|
|
672
733
|
**Does it work with my authentication?**
|
|
673
734
|
Yes — HTTP Basic Auth out of the box, or a custom `authenticate_with` lambda that integrates with Devise, Warden, or session-based auth.
|
|
@@ -694,7 +755,7 @@ Rails 7.0–8.1 and Ruby 3.2–4.0.
|
|
|
694
755
|
- **[Batch Operations](docs/guides/BATCH_OPERATIONS.md)** — Bulk resolve/delete
|
|
695
756
|
- **[Real-Time Updates](docs/guides/REAL_TIME_UPDATES.md)** — Live dashboard
|
|
696
757
|
- **[Error Trends](docs/guides/ERROR_TREND_VISUALIZATIONS.md)** — Charts and analytics
|
|
697
|
-
- **[Translations](docs/guides/TRANSLATIONS.md)** —
|
|
758
|
+
- **[Translations](docs/guides/TRANSLATIONS.md)** — Eleven shipped locales, correcting a string, adding a language
|
|
698
759
|
|
|
699
760
|
### Advanced
|
|
700
761
|
- **[Multi-App Support](docs/MULTI_APP_PERFORMANCE.md)** — Track multiple applications
|
|
@@ -703,7 +764,7 @@ Rails 7.0–8.1 and Ruby 3.2–4.0.
|
|
|
703
764
|
- **[Customization](docs/CUSTOMIZATION.md)** — Customize everything
|
|
704
765
|
- **[Database Options](docs/guides/DATABASE_OPTIONS.md)** — Separate database setup
|
|
705
766
|
- **[Database Optimization](docs/guides/DATABASE_OPTIMIZATION.md)** — Performance tuning
|
|
706
|
-
- **[Mobile App Integration](docs/guides/MOBILE_APP_INTEGRATION.md)** —
|
|
767
|
+
- **[Mobile App Integration](docs/guides/MOBILE_APP_INTEGRATION.md)** — log mobile-originated errors through your own API endpoint, tagged by platform
|
|
707
768
|
- **[FAQ](docs/FAQ.md)** — Common questions answered
|
|
708
769
|
|
|
709
770
|
[View all documentation →](docs/README.md)
|
|
@@ -722,7 +783,7 @@ Built with **CQRS (Command/Query Responsibility Segregation)**:
|
|
|
722
783
|
|
|
723
784
|
## Testing
|
|
724
785
|
|
|
725
|
-
|
|
786
|
+
An RSpec suite of unit, request and browser-based system specs runs in CI on every supported Rails version (see the Tests badge above); the current count lives in the CI log rather than here, where it would go stale.
|
|
726
787
|
|
|
727
788
|
```bash
|
|
728
789
|
bundle exec rspec # Full suite
|
|
@@ -16,6 +16,17 @@ module RailsErrorDashboard
|
|
|
16
16
|
# stamped by the first occurrence that claims it, so history migrates
|
|
17
17
|
# itself without a backfill. An exact match always wins over a NULL one.
|
|
18
18
|
class FindOrIncrementError
|
|
19
|
+
# Context that describes THIS occurrence rather than the error as a
|
|
20
|
+
# group. It is refreshed on every recurrence so the row always shows the
|
|
21
|
+
# latest moment of failure, not the first one in the 24 h window. Keys
|
|
22
|
+
# absent from @attributes (feature disabled, column not migrated, or a
|
|
23
|
+
# storm :lite capture that shed context) leave the stored payload alone —
|
|
24
|
+
# a shed capture must never blank out a good snapshot.
|
|
25
|
+
REFRESHED_CONTEXT = %i[
|
|
26
|
+
breadcrumbs system_health local_variables instance_variables
|
|
27
|
+
http_method hostname content_type request_duration_ms
|
|
28
|
+
].freeze
|
|
29
|
+
|
|
19
30
|
def self.call(error_hash, attributes = {})
|
|
20
31
|
new(error_hash, attributes).call
|
|
21
32
|
end
|
|
@@ -69,6 +80,13 @@ module RailsErrorDashboard
|
|
|
69
80
|
.order(Arel.sql("CASE WHEN environment IS NULL THEN 1 ELSE 0 END"))
|
|
70
81
|
end
|
|
71
82
|
|
|
83
|
+
# The subset of REFRESHED_CONTEXT this occurrence actually captured.
|
|
84
|
+
def latest_context
|
|
85
|
+
REFRESHED_CONTEXT.each_with_object({}) do |key, refreshed|
|
|
86
|
+
refreshed[key] = @attributes[key] unless @attributes[key].nil?
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
72
90
|
# {} unless this is a legacy NULL-environment row being claimed.
|
|
73
91
|
def environment_adoption(error)
|
|
74
92
|
return {} unless ErrorLog.column_names.include?("environment")
|
|
@@ -86,6 +104,7 @@ module RailsErrorDashboard
|
|
|
86
104
|
request_params: @attributes[:request_params] || error.request_params,
|
|
87
105
|
user_agent: @attributes[:user_agent] || error.user_agent,
|
|
88
106
|
ip_address: @attributes[:ip_address] || error.ip_address,
|
|
107
|
+
**latest_context,
|
|
89
108
|
**environment_adoption(error)
|
|
90
109
|
)
|
|
91
110
|
error
|
|
@@ -103,6 +122,7 @@ module RailsErrorDashboard
|
|
|
103
122
|
request_params: @attributes[:request_params] || error.request_params,
|
|
104
123
|
user_agent: @attributes[:user_agent] || error.user_agent,
|
|
105
124
|
ip_address: @attributes[:ip_address] || error.ip_address,
|
|
125
|
+
**latest_context,
|
|
106
126
|
**environment_adoption(error)
|
|
107
127
|
}
|
|
108
128
|
attrs[:reopened_at] = Time.current if ErrorLog.column_names.include?("reopened_at")
|
|
@@ -126,6 +146,7 @@ module RailsErrorDashboard
|
|
|
126
146
|
retry_existing.update!(
|
|
127
147
|
occurrence_count: retry_existing.occurrence_count + 1,
|
|
128
148
|
last_seen_at: Time.current,
|
|
149
|
+
**latest_context,
|
|
129
150
|
**environment_adoption(retry_existing)
|
|
130
151
|
)
|
|
131
152
|
retry_existing
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_error_dashboard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.11.
|
|
4
|
+
version: 0.11.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anjan Jagirdar
|
|
@@ -219,29 +219,24 @@ dependencies:
|
|
|
219
219
|
- - "~>"
|
|
220
220
|
- !ruby/object:Gem::Version
|
|
221
221
|
version: '0.15'
|
|
222
|
-
description: '
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
mutates your app''s I18n; a missing translation falls back to English. Backtraces,
|
|
241
|
-
exception names and webhook payload keys stay English by design. The ten non-English
|
|
242
|
-
locales are machine-translated and not yet reviewed by native speakers. 5-minute
|
|
243
|
-
setup, works out-of-the-box. Rails 7.0-8.1, Ruby 3.2-4.0. BETA: API may change before
|
|
244
|
-
v1.0.0. Live demo: https://rails-error-dashboard.anjan.dev (gandalf/youshallnotpass)'
|
|
222
|
+
description: 'Rails Error Dashboard (RED) is an open-source, self-hosted Rails engine
|
|
223
|
+
for investigating production exceptions without sending error data to a monitoring
|
|
224
|
+
vendor. It groups errors and records request context and cause chains and, when
|
|
225
|
+
enabled, breadcrumbs plus local and instance variables captured before Ruby unwinds
|
|
226
|
+
the stack. RED attaches Rails and Ruby runtime health to the error record on every
|
|
227
|
+
captured occurrence, including Active Record pool, Puma, background jobs, GC, memory,
|
|
228
|
+
threads, file descriptors and system pressure. Built-in storm protection progressively
|
|
229
|
+
sheds expensive context and I/O during error floods while retaining useful exemplars
|
|
230
|
+
and exact occurrence counts. Run RED with your application''s database or an isolated
|
|
231
|
+
error database. It supports PostgreSQL, MySQL/Trilogy and SQLite, and includes workflow,
|
|
232
|
+
notifications (Slack, Email, Discord, PagerDuty, webhooks), two-way issue sync with
|
|
233
|
+
GitHub, GitLab, Codeberg and Linear, Copy as RSpec/curl/LLM, swallowed-exception
|
|
234
|
+
detection, LLM observability without prompt capture, OpenTelemetry span export and
|
|
235
|
+
Rails-specific operational views. The dashboard is translated into 11 languages
|
|
236
|
+
(machine-translated outside English, awaiting native review). A self-hosted Sentry
|
|
237
|
+
alternative that keeps error data in your own database. The gem is MIT and free
|
|
238
|
+
forever. Supports Rails 7.0-8.1 and Ruby 3.2-4.0. Beta: APIs may change before 1.0.
|
|
239
|
+
Live demo: https://rails-error-dashboard.anjan.dev'
|
|
245
240
|
email:
|
|
246
241
|
- anjan.jagirdar@gmail.com
|
|
247
242
|
executables: []
|
|
@@ -561,7 +556,7 @@ metadata:
|
|
|
561
556
|
funding_uri: https://github.com/sponsors/AnjanJ
|
|
562
557
|
post_install_message: |
|
|
563
558
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
564
|
-
RED (Rails Error Dashboard) v0.11.
|
|
559
|
+
RED (Rails Error Dashboard) v0.11.1
|
|
565
560
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
566
561
|
|
|
567
562
|
First install:
|
|
@@ -599,6 +594,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
599
594
|
requirements: []
|
|
600
595
|
rubygems_version: 3.6.9
|
|
601
596
|
specification_version: 4
|
|
602
|
-
summary:
|
|
603
|
-
|
|
597
|
+
summary: Rails-native, self-hosted error monitoring with exception-time Ruby state,
|
|
598
|
+
runtime health, and storm-safe capture.
|
|
604
599
|
test_files: []
|