rails_error_dashboard 0.4.0 → 0.4.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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af7cf1b00931ba21cc10e507128ce90183cd2c0c707e47b16c2833ada7108fa7
|
|
4
|
+
data.tar.gz: e59567ed413e58003c45336006239562eeffdfd11330515a1faef711b7143f46
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7446d9a051e2fa804b5090294217c0a678123fd8b1eb8720fff4b5ef8bf0bde48f87245333119b9b1c4101e036f3665b85b33b867ba8b2666182d6e2f7768cd7
|
|
7
|
+
data.tar.gz: 9b7d7140f5acebbc5c15c218716a81e03309e7590880b9648e5ac9b35276ecccd210fbfbc4837ae8bd88a75f936b12873f81f170b9c85b9da8997d5641602126
|
data/README.md
CHANGED
|
@@ -22,7 +22,7 @@ gem 'rails_error_dashboard'
|
|
|
22
22
|
|
|
23
23
|
**[rails-error-dashboard.anjan.dev](https://rails-error-dashboard.anjan.dev)** — Username: `gandalf` · Password: `youshallnotpass`
|
|
24
24
|
|
|
25
|
-
> **Beta Software** — Functional and tested (2,
|
|
25
|
+
> **Beta Software** — Functional and tested (2,600+ tests passing), but the API may change before v1.0. Supports Rails 7.0-8.1 and Ruby 3.2-4.0.
|
|
26
26
|
|
|
27
27
|
### Screenshots
|
|
28
28
|
|
|
@@ -53,6 +53,8 @@ gem 'rails_error_dashboard'
|
|
|
53
53
|
| SaaS pricing tiers and usage limits | Unlimited errors, unlimited projects |
|
|
54
54
|
| Vendor lock-in with proprietary APIs | 100% open source, fully portable |
|
|
55
55
|
| Complex SDK setup and external services | 5-minute Rails Engine installation |
|
|
56
|
+
| Pay extra for local variable capture (Sentry) | Local + instance variables included free |
|
|
57
|
+
| No tool detects silently rescued exceptions | Swallowed exception detection built in |
|
|
56
58
|
|
|
57
59
|
---
|
|
58
60
|
|
|
@@ -85,10 +87,12 @@ config.enable_breadcrumbs = true
|
|
|
85
87
|
<details>
|
|
86
88
|
<summary><strong>System Health Snapshot</strong></summary>
|
|
87
89
|
|
|
88
|
-
Know your app's runtime state at the moment of failure — GC stats, process memory, thread count, connection pool utilization,
|
|
90
|
+
Know your app's runtime state at the moment of failure — GC stats, process memory, thread count, connection pool utilization, Puma thread stats, RubyVM cache health, and YJIT compilation stats captured automatically.
|
|
89
91
|
|
|
90
92
|
- Sub-millisecond total snapshot, every metric individually rescue-wrapped
|
|
91
93
|
- No ObjectSpace scanning, no Thread backtraces, no subprocess calls
|
|
94
|
+
- RubyVM.stat: constant cache invalidations, shape cache stats
|
|
95
|
+
- YJIT runtime stats: compiled iseqs, invalidation count, code region sizes
|
|
92
96
|
|
|
93
97
|
```ruby
|
|
94
98
|
config.enable_system_health = true
|
|
@@ -181,6 +185,98 @@ Seven analysis engines built in:
|
|
|
181
185
|
[Complete documentation →](docs/FEATURES.md#advanced-analytics-features)
|
|
182
186
|
</details>
|
|
183
187
|
|
|
188
|
+
<details>
|
|
189
|
+
<summary><strong>Local Variable + Instance Variable Capture</strong></summary>
|
|
190
|
+
|
|
191
|
+
See the exact values of local variables and instance variables at the moment an exception was raised — the most valuable debugging context possible.
|
|
192
|
+
|
|
193
|
+
- TracePoint(`:raise`) captures locals and ivars before the stack unwinds
|
|
194
|
+
- Configurable limits: max variable count, nesting depth, string truncation length
|
|
195
|
+
- Sensitive data auto-filtered via Rails `filter_parameters` — passwords, tokens, and PII never stored
|
|
196
|
+
- Never stores Binding objects — values extracted immediately, Binding is GC'd
|
|
197
|
+
- Independent config flags: enable one or both
|
|
198
|
+
|
|
199
|
+

|
|
200
|
+
|
|
201
|
+
```ruby
|
|
202
|
+
config.enable_local_variables = true
|
|
203
|
+
config.enable_instance_variables = true
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
[Complete documentation →](docs/FEATURES.md)
|
|
207
|
+
</details>
|
|
208
|
+
|
|
209
|
+
<details>
|
|
210
|
+
<summary><strong>Swallowed Exception Detection</strong></summary>
|
|
211
|
+
|
|
212
|
+
Detect exceptions that are raised but silently rescued — the hardest bugs to find. No other error tracker does this.
|
|
213
|
+
|
|
214
|
+
- Uses TracePoint(`:raise`) + TracePoint(`:rescue`) to track exception lifecycle
|
|
215
|
+
- Identifies code paths where exceptions are caught but never logged or re-raised
|
|
216
|
+
- Dashboard page at `/errors/swallowed_exceptions` shows detection counts, locations, and patterns
|
|
217
|
+
- Memory-bounded aggregation with background flush
|
|
218
|
+
- Requires Ruby 3.3+
|
|
219
|
+
|
|
220
|
+

|
|
221
|
+
|
|
222
|
+
```ruby
|
|
223
|
+
config.detect_swallowed_exceptions = true
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
[Complete documentation →](docs/FEATURES.md)
|
|
227
|
+
</details>
|
|
228
|
+
|
|
229
|
+
<details>
|
|
230
|
+
<summary><strong>On-Demand Diagnostic Dump</strong></summary>
|
|
231
|
+
|
|
232
|
+
Snapshot your app's entire system state on demand — environment, GC stats, threads, connection pool, memory, job queue health, and more.
|
|
233
|
+
|
|
234
|
+
- Trigger via dashboard button or `rake rails_error_dashboard:diagnostic_dump`
|
|
235
|
+
- Dashboard page at `/errors/diagnostic_dumps` with full history
|
|
236
|
+
- Useful for debugging intermittent production issues without reproducing them
|
|
237
|
+
|
|
238
|
+

|
|
239
|
+
|
|
240
|
+
```ruby
|
|
241
|
+
config.enable_diagnostic_dump = true
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
[Complete documentation →](docs/FEATURES.md)
|
|
245
|
+
</details>
|
|
246
|
+
|
|
247
|
+
<details>
|
|
248
|
+
<summary><strong>Rack Attack Event Tracking</strong></summary>
|
|
249
|
+
|
|
250
|
+
Track Rack Attack security events (throttles, blocklists, tracks) as breadcrumbs attached to errors, with a dedicated summary page.
|
|
251
|
+
|
|
252
|
+
- Captures throttle, blocklist, and track events automatically
|
|
253
|
+
- Dashboard page at `/errors/rack_attack_summary` with event breakdown
|
|
254
|
+
- Requires breadcrumbs to be enabled
|
|
255
|
+
|
|
256
|
+
```ruby
|
|
257
|
+
config.enable_rack_attack_tracking = true
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
[Complete documentation →](docs/FEATURES.md)
|
|
261
|
+
</details>
|
|
262
|
+
|
|
263
|
+
<details>
|
|
264
|
+
<summary><strong>Process Crash Capture</strong></summary>
|
|
265
|
+
|
|
266
|
+
Capture unhandled exceptions that crash the Ruby process via an `at_exit` hook — the last line of defense.
|
|
267
|
+
|
|
268
|
+
- Disk-based fallback: writes crash data to disk because the database may be unavailable during shutdown
|
|
269
|
+
- Imported automatically on next boot
|
|
270
|
+
- Captures exception details, backtrace, uptime, GC stats, thread count, and cause chain
|
|
271
|
+
- A self-hosted only feature — impossible for SaaS tools
|
|
272
|
+
|
|
273
|
+
```ruby
|
|
274
|
+
config.enable_crash_capture = true
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
[Complete documentation →](docs/FEATURES.md)
|
|
278
|
+
</details>
|
|
279
|
+
|
|
184
280
|
<details>
|
|
185
281
|
<summary><strong>Plugin System</strong></summary>
|
|
186
282
|
|
|
@@ -304,7 +400,7 @@ Built with **CQRS (Command/Query Responsibility Segregation)**:
|
|
|
304
400
|
|
|
305
401
|
## Testing
|
|
306
402
|
|
|
307
|
-
2,
|
|
403
|
+
2,600+ tests covering unit, integration, and browser-based system tests.
|
|
308
404
|
|
|
309
405
|
```bash
|
|
310
406
|
bundle exec rspec # Full suite
|
|
@@ -344,7 +440,7 @@ Built with [Rails](https://rubyonrails.org/) · UI by [Bootstrap 5](https://getb
|
|
|
344
440
|
|
|
345
441
|
[](https://github.com/AnjanJ/rails_error_dashboard/graphs/contributors)
|
|
346
442
|
|
|
347
|
-
Special thanks to [@bonniesimon](https://github.com/bonniesimon), [@gundestrup](https://github.com/gundestrup),
|
|
443
|
+
Special thanks to [@bonniesimon](https://github.com/bonniesimon), [@gundestrup](https://github.com/gundestrup), [@midwire](https://github.com/midwire), and [@RafaelTurtle](https://github.com/RafaelTurtle). See [CONTRIBUTORS.md](CONTRIBUTORS.md) for the full list.
|
|
348
444
|
|
|
349
445
|
---
|
|
350
446
|
|
|
@@ -334,6 +334,54 @@
|
|
|
334
334
|
</code>
|
|
335
335
|
</div>
|
|
336
336
|
<% end %>
|
|
337
|
+
|
|
338
|
+
<% if health[:ruby_vm] %>
|
|
339
|
+
<% vm = health[:ruby_vm] %>
|
|
340
|
+
<div class="mb-1">
|
|
341
|
+
<small class="text-muted">VM Cache Invalidations:</small>
|
|
342
|
+
<% invals = vm[:constant_cache_invalidations].to_i %>
|
|
343
|
+
<code class="ms-1 <%= 'text-danger' if invals > 10_000 %>"><%= begin; number_with_delimiter(invals); rescue; invals; end %></code>
|
|
344
|
+
</div>
|
|
345
|
+
<div class="mb-1">
|
|
346
|
+
<small class="text-muted">VM Cache Misses:</small>
|
|
347
|
+
<code class="ms-1"><%= begin; number_with_delimiter(vm[:constant_cache_misses]); rescue; vm[:constant_cache_misses]; end %></code>
|
|
348
|
+
</div>
|
|
349
|
+
<% if vm[:shape_cache_size] %>
|
|
350
|
+
<div class="mb-1">
|
|
351
|
+
<small class="text-muted">Shape Cache Size:</small>
|
|
352
|
+
<code class="ms-1"><%= begin; number_with_delimiter(vm[:shape_cache_size]); rescue; vm[:shape_cache_size]; end %></code>
|
|
353
|
+
</div>
|
|
354
|
+
<% end %>
|
|
355
|
+
<% end %>
|
|
356
|
+
|
|
357
|
+
<% if health[:yjit] %>
|
|
358
|
+
<% yj = health[:yjit] %>
|
|
359
|
+
<% if yj[:compiled_iseq_count] || yj[:compiled_block_count] %>
|
|
360
|
+
<div class="mb-1">
|
|
361
|
+
<small class="text-muted">YJIT Compiled:</small>
|
|
362
|
+
<code class="ms-1"><%= yj[:compiled_iseq_count] %> iseqs / <%= yj[:compiled_block_count] %> blocks</code>
|
|
363
|
+
</div>
|
|
364
|
+
<% end %>
|
|
365
|
+
<% if yj[:invalidation_count] %>
|
|
366
|
+
<div class="mb-1">
|
|
367
|
+
<small class="text-muted">YJIT Invalidations:</small>
|
|
368
|
+
<% yj_invals = yj[:invalidation_count].to_i %>
|
|
369
|
+
<code class="ms-1 <%= 'text-danger' if yj_invals > 100 %>"><%= yj_invals %></code>
|
|
370
|
+
</div>
|
|
371
|
+
<% end %>
|
|
372
|
+
<% if yj[:code_region_size] %>
|
|
373
|
+
<div class="mb-1">
|
|
374
|
+
<small class="text-muted">YJIT Code Size:</small>
|
|
375
|
+
<code class="ms-1"><%= (yj[:code_region_size].to_f / 1024).round(1) %> KB</code>
|
|
376
|
+
</div>
|
|
377
|
+
<% end %>
|
|
378
|
+
<% if yj[:compile_time_ns] %>
|
|
379
|
+
<div class="mb-1">
|
|
380
|
+
<small class="text-muted">YJIT Compile Time:</small>
|
|
381
|
+
<code class="ms-1"><%= (yj[:compile_time_ns].to_f / 1_000_000).round(2) %> ms</code>
|
|
382
|
+
</div>
|
|
383
|
+
<% end %>
|
|
384
|
+
<% end %>
|
|
337
385
|
</div>
|
|
338
386
|
</div>
|
|
339
387
|
<% end %>
|
|
@@ -34,6 +34,8 @@ module RailsErrorDashboard
|
|
|
34
34
|
connection_pool: connection_pool_stats,
|
|
35
35
|
puma: puma_stats,
|
|
36
36
|
job_queue: job_queue_stats,
|
|
37
|
+
ruby_vm: ruby_vm_stats,
|
|
38
|
+
yjit: yjit_stats,
|
|
37
39
|
captured_at: Time.current.iso8601
|
|
38
40
|
}
|
|
39
41
|
end
|
|
@@ -140,6 +142,37 @@ module RailsErrorDashboard
|
|
|
140
142
|
rescue => e
|
|
141
143
|
nil
|
|
142
144
|
end
|
|
145
|
+
|
|
146
|
+
# RubyVM.stat — constant/method cache invalidation rates
|
|
147
|
+
# Keys vary by Ruby version; pass through full hash for forward-compat
|
|
148
|
+
# Ruby 3.2+: constant_cache_invalidations, constant_cache_misses,
|
|
149
|
+
# global_cvar_state, next_shape_id, shape_cache_size
|
|
150
|
+
def ruby_vm_stats
|
|
151
|
+
return nil unless defined?(RubyVM) && RubyVM.respond_to?(:stat)
|
|
152
|
+
RubyVM.stat
|
|
153
|
+
rescue => e
|
|
154
|
+
nil
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# RubyVM::YJIT.runtime_stats — JIT compilation health
|
|
158
|
+
# Cherry-picks diagnostic keys (full hash has 30+ entries)
|
|
159
|
+
def yjit_stats
|
|
160
|
+
return nil unless defined?(RubyVM::YJIT) && RubyVM::YJIT.respond_to?(:enabled?) && RubyVM::YJIT.enabled?
|
|
161
|
+
raw = RubyVM::YJIT.runtime_stats
|
|
162
|
+
{
|
|
163
|
+
inline_code_size: raw[:inline_code_size],
|
|
164
|
+
code_region_size: raw[:code_region_size],
|
|
165
|
+
compiled_iseq_count: raw[:compiled_iseq_count],
|
|
166
|
+
compiled_block_count: raw[:compiled_block_count],
|
|
167
|
+
compile_time_ns: raw[:compile_time_ns],
|
|
168
|
+
invalidation_count: raw[:invalidation_count],
|
|
169
|
+
invalidate_method_lookup: raw[:invalidate_method_lookup],
|
|
170
|
+
invalidate_constant_state_bump: raw[:invalidate_constant_state_bump],
|
|
171
|
+
object_shape_count: raw[:object_shape_count]
|
|
172
|
+
}
|
|
173
|
+
rescue => e
|
|
174
|
+
nil
|
|
175
|
+
end
|
|
143
176
|
end
|
|
144
177
|
end
|
|
145
178
|
end
|
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.4.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anjan Jagirdar
|
|
@@ -457,7 +457,7 @@ metadata:
|
|
|
457
457
|
bug_tracker_uri: https://github.com/AnjanJ/rails_error_dashboard/issues
|
|
458
458
|
funding_uri: https://buymeacoffee.com/anjanj
|
|
459
459
|
post_install_message: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n
|
|
460
|
-
\ Rails Error Dashboard v0.4.
|
|
460
|
+
\ Rails Error Dashboard v0.4.1\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
|
|
461
461
|
First time? Quick start:\n rails generate rails_error_dashboard:install\n rails
|
|
462
462
|
db:migrate\n # Add to config/routes.rb:\n mount RailsErrorDashboard::Engine
|
|
463
463
|
=> '/error_dashboard'\n\n\U0001F504 Upgrading from v0.1.x?\n rails db:migrate\n
|