rails_error_dashboard 0.3.1 → 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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +236 -841
  3. data/app/controllers/rails_error_dashboard/errors_controller.rb +89 -0
  4. data/app/jobs/rails_error_dashboard/swallowed_exception_flush_job.rb +32 -0
  5. data/app/models/rails_error_dashboard/diagnostic_dump.rb +14 -0
  6. data/app/models/rails_error_dashboard/swallowed_exception.rb +38 -0
  7. data/app/views/layouts/rails_error_dashboard.html.erb +21 -0
  8. data/app/views/rails_error_dashboard/errors/_instance_variables.html.erb +55 -0
  9. data/app/views/rails_error_dashboard/errors/_local_variables.html.erb +46 -0
  10. data/app/views/rails_error_dashboard/errors/_sidebar_metadata.html.erb +48 -0
  11. data/app/views/rails_error_dashboard/errors/diagnostic_dumps.html.erb +182 -0
  12. data/app/views/rails_error_dashboard/errors/rack_attack_summary.html.erb +133 -0
  13. data/app/views/rails_error_dashboard/errors/show.html.erb +4 -0
  14. data/app/views/rails_error_dashboard/errors/swallowed_exceptions.html.erb +126 -0
  15. data/config/routes.rb +4 -0
  16. data/db/migrate/20251223000000_create_rails_error_dashboard_complete_schema.rb +33 -0
  17. data/db/migrate/20260306000001_add_local_variables_to_error_logs.rb +13 -0
  18. data/db/migrate/20260306000002_add_instance_variables_to_error_logs.rb +7 -0
  19. data/db/migrate/20260306000003_create_rails_error_dashboard_swallowed_exceptions.rb +34 -0
  20. data/db/migrate/20260307000001_create_rails_error_dashboard_diagnostic_dumps.rb +17 -0
  21. data/lib/generators/rails_error_dashboard/install/install_generator.rb +32 -0
  22. data/lib/generators/rails_error_dashboard/install/templates/initializer.rb +47 -0
  23. data/lib/rails_error_dashboard/commands/flush_swallowed_exceptions.rb +103 -0
  24. data/lib/rails_error_dashboard/commands/log_error.rb +68 -0
  25. data/lib/rails_error_dashboard/configuration.rb +122 -0
  26. data/lib/rails_error_dashboard/engine.rb +24 -0
  27. data/lib/rails_error_dashboard/queries/dashboard_stats.rb +32 -11
  28. data/lib/rails_error_dashboard/queries/rack_attack_summary.rb +90 -0
  29. data/lib/rails_error_dashboard/queries/swallowed_exception_summary.rb +97 -0
  30. data/lib/rails_error_dashboard/services/breadcrumb_collector.rb +12 -0
  31. data/lib/rails_error_dashboard/services/crash_capture.rb +234 -0
  32. data/lib/rails_error_dashboard/services/diagnostic_dump_generator.rb +98 -0
  33. data/lib/rails_error_dashboard/services/local_variable_capturer.rb +207 -0
  34. data/lib/rails_error_dashboard/services/swallowed_exception_tracker.rb +277 -0
  35. data/lib/rails_error_dashboard/services/system_health_snapshot.rb +33 -0
  36. data/lib/rails_error_dashboard/services/variable_serializer.rb +326 -0
  37. data/lib/rails_error_dashboard/subscribers/rack_attack_subscriber.rb +94 -0
  38. data/lib/rails_error_dashboard/version.rb +1 -1
  39. data/lib/rails_error_dashboard.rb +9 -0
  40. data/lib/tasks/error_dashboard.rake +34 -0
  41. metadata +23 -2
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsErrorDashboard
4
+ module Subscribers
5
+ # Registers ActiveSupport::Notifications subscribers for Rack::Attack events.
6
+ #
7
+ # Rack Attack (v5.0+) emits:
8
+ # - throttle.rack_attack — rate-limited requests
9
+ # - blocklist.rack_attack — blocked requests
10
+ # - track.rack_attack — tracked (observed) requests
11
+ #
12
+ # Each event is captured as a breadcrumb with category "rack_attack",
13
+ # allowing correlation between rate-limit events and error spikes.
14
+ #
15
+ # SAFETY RULES (HOST_APP_SAFETY.md):
16
+ # - Every subscriber wrapped in rescue => e; nil
17
+ # - Never raise from subscriber callbacks
18
+ # - Skip if buffer is nil (not in a request context)
19
+ class RackAttackSubscriber
20
+ EVENTS = %w[
21
+ throttle.rack_attack
22
+ blocklist.rack_attack
23
+ track.rack_attack
24
+ ].freeze
25
+
26
+ # Event subscriptions managed by this class
27
+ @subscriptions = []
28
+
29
+ class << self
30
+ attr_reader :subscriptions
31
+
32
+ # Register all Rack Attack event subscribers
33
+ # @return [Array] Array of subscription objects
34
+ def subscribe!
35
+ @subscriptions = []
36
+
37
+ EVENTS.each do |event_name|
38
+ @subscriptions << subscribe_event(event_name)
39
+ end
40
+
41
+ @subscriptions
42
+ end
43
+
44
+ # Remove all Rack Attack subscribers
45
+ def unsubscribe!
46
+ @subscriptions.each do |sub|
47
+ ActiveSupport::Notifications.unsubscribe(sub) if sub
48
+ rescue => e
49
+ nil
50
+ end
51
+ @subscriptions = []
52
+ end
53
+
54
+ private
55
+
56
+ def subscribe_event(event_name)
57
+ ActiveSupport::Notifications.subscribe(event_name) do |*args|
58
+ event = ActiveSupport::Notifications::Event.new(*args)
59
+ handle_rack_attack(event, event_name)
60
+ rescue => e
61
+ nil
62
+ end
63
+ end
64
+
65
+ def handle_rack_attack(event, event_name)
66
+ return unless Services::BreadcrumbCollector.current_buffer
67
+
68
+ request = event.payload[:request]
69
+ return unless request
70
+
71
+ env = request.respond_to?(:env) ? request.env : {}
72
+
73
+ match_type = event_name.split(".").first # "throttle", "blocklist", "track"
74
+ rule = env["rack.attack.matched"].to_s
75
+ discriminator = env["rack.attack.match_discriminator"].to_s
76
+ path = request.respond_to?(:path) ? request.path.to_s : ""
77
+ method = request.respond_to?(:request_method) ? request.request_method.to_s : ""
78
+
79
+ message = "#{match_type}: #{rule} (#{discriminator}) #{method} #{path}"
80
+
81
+ metadata = {
82
+ rule: rule,
83
+ type: match_type,
84
+ discriminator: discriminator,
85
+ path: path,
86
+ method: method
87
+ }
88
+
89
+ Services::BreadcrumbCollector.add("rack_attack", message, metadata: metadata)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -1,3 +1,3 @@
1
1
  module RailsErrorDashboard
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -57,7 +57,13 @@ require "rails_error_dashboard/services/curl_generator"
57
57
  require "rails_error_dashboard/services/rspec_generator"
58
58
  require "rails_error_dashboard/services/database_health_inspector"
59
59
  require "rails_error_dashboard/services/cache_analyzer"
60
+ require "rails_error_dashboard/services/variable_serializer"
61
+ require "rails_error_dashboard/services/local_variable_capturer"
62
+ require "rails_error_dashboard/services/swallowed_exception_tracker"
63
+ require "rails_error_dashboard/services/crash_capture"
64
+ require "rails_error_dashboard/services/diagnostic_dump_generator"
60
65
  require "rails_error_dashboard/subscribers/breadcrumb_subscriber"
66
+ require "rails_error_dashboard/subscribers/rack_attack_subscriber"
61
67
  require "rails_error_dashboard/queries/co_occurring_errors"
62
68
  require "rails_error_dashboard/queries/error_cascades"
63
69
  require "rails_error_dashboard/queries/baseline_stats"
@@ -80,6 +86,7 @@ require "rails_error_dashboard/commands/find_or_increment_error"
80
86
  require "rails_error_dashboard/commands/find_or_create_application"
81
87
  require "rails_error_dashboard/commands/upsert_cascade_pattern"
82
88
  require "rails_error_dashboard/commands/upsert_baseline"
89
+ require "rails_error_dashboard/commands/flush_swallowed_exceptions"
83
90
  require "rails_error_dashboard/queries/errors_list"
84
91
  require "rails_error_dashboard/queries/dashboard_stats"
85
92
  require "rails_error_dashboard/queries/analytics_stats"
@@ -93,6 +100,8 @@ require "rails_error_dashboard/queries/n_plus_one_summary"
93
100
  require "rails_error_dashboard/queries/cache_health_summary"
94
101
  require "rails_error_dashboard/queries/job_health_summary"
95
102
  require "rails_error_dashboard/queries/database_health_summary"
103
+ require "rails_error_dashboard/queries/swallowed_exception_summary"
104
+ require "rails_error_dashboard/queries/rack_attack_summary"
96
105
  require "rails_error_dashboard/error_reporter"
97
106
  require "rails_error_dashboard/middleware/error_catcher"
98
107
  require "rails_error_dashboard/middleware/rate_limiter"
@@ -444,6 +444,40 @@ namespace :error_dashboard do
444
444
  puts "\n" + "=" * 80 + "\n"
445
445
  end
446
446
 
447
+ desc "Capture diagnostic dump of current system state"
448
+ task diagnostic_dump: :environment do
449
+ unless RailsErrorDashboard.configuration.enable_diagnostic_dump
450
+ puts "\n Diagnostic dumps are not enabled."
451
+ puts " Set config.enable_diagnostic_dump = true in your initializer."
452
+ next
453
+ end
454
+
455
+ puts "\n" + "=" * 70
456
+ puts " RAILS ERROR DASHBOARD - DIAGNOSTIC DUMP"
457
+ puts "=" * 70
458
+
459
+ dump = RailsErrorDashboard::Services::DiagnosticDumpGenerator.call
460
+
461
+ app_name = RailsErrorDashboard.configuration.application_name ||
462
+ ENV["APPLICATION_NAME"] ||
463
+ (defined?(Rails) && Rails.application.class.module_parent_name) ||
464
+ "Unknown"
465
+ app = RailsErrorDashboard::Commands::FindOrCreateApplication.call(app_name)
466
+
467
+ RailsErrorDashboard::DiagnosticDump.create!(
468
+ application_id: app.id,
469
+ dump_data: dump.to_json,
470
+ captured_at: Time.current,
471
+ note: ENV["NOTE"]
472
+ )
473
+
474
+ puts "\n" + JSON.pretty_generate(dump)
475
+ puts "\n Diagnostic dump saved to database."
476
+ puts " Application: #{app_name}"
477
+ puts " Note: #{ENV['NOTE'] || '(none)'}"
478
+ puts "\n" + "=" * 70 + "\n"
479
+ end
480
+
447
481
  desc "Run retention cleanup (delete errors older than retention_days)"
448
482
  task retention_cleanup: :environment do
449
483
  config = RailsErrorDashboard.configuration
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.3.1
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anjan Jagirdar
@@ -256,16 +256,19 @@ files:
256
256
  - app/jobs/rails_error_dashboard/pagerduty_error_notification_job.rb
257
257
  - app/jobs/rails_error_dashboard/retention_cleanup_job.rb
258
258
  - app/jobs/rails_error_dashboard/slack_error_notification_job.rb
259
+ - app/jobs/rails_error_dashboard/swallowed_exception_flush_job.rb
259
260
  - app/jobs/rails_error_dashboard/webhook_error_notification_job.rb
260
261
  - app/mailers/rails_error_dashboard/application_mailer.rb
261
262
  - app/mailers/rails_error_dashboard/error_notification_mailer.rb
262
263
  - app/models/rails_error_dashboard/application.rb
263
264
  - app/models/rails_error_dashboard/cascade_pattern.rb
265
+ - app/models/rails_error_dashboard/diagnostic_dump.rb
264
266
  - app/models/rails_error_dashboard/error_baseline.rb
265
267
  - app/models/rails_error_dashboard/error_comment.rb
266
268
  - app/models/rails_error_dashboard/error_log.rb
267
269
  - app/models/rails_error_dashboard/error_logs_record.rb
268
270
  - app/models/rails_error_dashboard/error_occurrence.rb
271
+ - app/models/rails_error_dashboard/swallowed_exception.rb
269
272
  - app/views/layouts/rails_error_dashboard.html.erb
270
273
  - app/views/rails_error_dashboard/error_notification_mailer/error_alert.html.erb
271
274
  - app/views/rails_error_dashboard/error_notification_mailer/error_alert.text.erb
@@ -275,6 +278,8 @@ files:
275
278
  - app/views/rails_error_dashboard/errors/_error_cascades.html.erb
276
279
  - app/views/rails_error_dashboard/errors/_error_info.html.erb
277
280
  - app/views/rails_error_dashboard/errors/_error_row.html.erb
281
+ - app/views/rails_error_dashboard/errors/_instance_variables.html.erb
282
+ - app/views/rails_error_dashboard/errors/_local_variables.html.erb
278
283
  - app/views/rails_error_dashboard/errors/_modals.html.erb
279
284
  - app/views/rails_error_dashboard/errors/_pattern_insights.html.erb
280
285
  - app/views/rails_error_dashboard/errors/_request_context.html.erb
@@ -290,14 +295,17 @@ files:
290
295
  - app/views/rails_error_dashboard/errors/correlation.html.erb
291
296
  - app/views/rails_error_dashboard/errors/database_health_summary.html.erb
292
297
  - app/views/rails_error_dashboard/errors/deprecations.html.erb
298
+ - app/views/rails_error_dashboard/errors/diagnostic_dumps.html.erb
293
299
  - app/views/rails_error_dashboard/errors/index.html.erb
294
300
  - app/views/rails_error_dashboard/errors/job_health_summary.html.erb
295
301
  - app/views/rails_error_dashboard/errors/n_plus_one_summary.html.erb
296
302
  - app/views/rails_error_dashboard/errors/overview.html.erb
297
303
  - app/views/rails_error_dashboard/errors/platform_comparison.html.erb
304
+ - app/views/rails_error_dashboard/errors/rack_attack_summary.html.erb
298
305
  - app/views/rails_error_dashboard/errors/settings.html.erb
299
306
  - app/views/rails_error_dashboard/errors/settings/_value_badge.html.erb
300
307
  - app/views/rails_error_dashboard/errors/show.html.erb
308
+ - app/views/rails_error_dashboard/errors/swallowed_exceptions.html.erb
301
309
  - config/routes.rb
302
310
  - db/development.sqlite3
303
311
  - db/migrate/20251223000000_create_rails_error_dashboard_complete_schema.rb
@@ -326,6 +334,10 @@ files:
326
334
  - db/migrate/20260221000002_add_reopened_at_to_error_logs.rb
327
335
  - db/migrate/20260303000001_add_breadcrumbs_to_error_logs.rb
328
336
  - db/migrate/20260304000001_add_system_health_to_error_logs.rb
337
+ - db/migrate/20260306000001_add_local_variables_to_error_logs.rb
338
+ - db/migrate/20260306000002_add_instance_variables_to_error_logs.rb
339
+ - db/migrate/20260306000003_create_rails_error_dashboard_swallowed_exceptions.rb
340
+ - db/migrate/20260307000001_create_rails_error_dashboard_diagnostic_dumps.rb
329
341
  - lib/generators/rails_error_dashboard/install/install_generator.rb
330
342
  - lib/generators/rails_error_dashboard/install/templates/README
331
343
  - lib/generators/rails_error_dashboard/install/templates/initializer.rb
@@ -340,6 +352,7 @@ files:
340
352
  - lib/rails_error_dashboard/commands/calculate_cascade_probability.rb
341
353
  - lib/rails_error_dashboard/commands/find_or_create_application.rb
342
354
  - lib/rails_error_dashboard/commands/find_or_increment_error.rb
355
+ - lib/rails_error_dashboard/commands/flush_swallowed_exceptions.rb
343
356
  - lib/rails_error_dashboard/commands/increment_cascade_detection.rb
344
357
  - lib/rails_error_dashboard/commands/log_error.rb
345
358
  - lib/rails_error_dashboard/commands/resolve_error.rb
@@ -380,8 +393,10 @@ files:
380
393
  - lib/rails_error_dashboard/queries/mttr_stats.rb
381
394
  - lib/rails_error_dashboard/queries/n_plus_one_summary.rb
382
395
  - lib/rails_error_dashboard/queries/platform_comparison.rb
396
+ - lib/rails_error_dashboard/queries/rack_attack_summary.rb
383
397
  - lib/rails_error_dashboard/queries/recurring_issues.rb
384
398
  - lib/rails_error_dashboard/queries/similar_errors.rb
399
+ - lib/rails_error_dashboard/queries/swallowed_exception_summary.rb
385
400
  - lib/rails_error_dashboard/services/analytics_cache_manager.rb
386
401
  - lib/rails_error_dashboard/services/backtrace_parser.rb
387
402
  - lib/rails_error_dashboard/services/backtrace_processor.rb
@@ -392,8 +407,10 @@ files:
392
407
  - lib/rails_error_dashboard/services/cache_analyzer.rb
393
408
  - lib/rails_error_dashboard/services/cascade_detector.rb
394
409
  - lib/rails_error_dashboard/services/cause_chain_extractor.rb
410
+ - lib/rails_error_dashboard/services/crash_capture.rb
395
411
  - lib/rails_error_dashboard/services/curl_generator.rb
396
412
  - lib/rails_error_dashboard/services/database_health_inspector.rb
413
+ - lib/rails_error_dashboard/services/diagnostic_dump_generator.rb
397
414
  - lib/rails_error_dashboard/services/discord_payload_builder.rb
398
415
  - lib/rails_error_dashboard/services/environment_snapshot.rb
399
416
  - lib/rails_error_dashboard/services/error_broadcaster.rb
@@ -403,6 +420,7 @@ files:
403
420
  - lib/rails_error_dashboard/services/exception_filter.rb
404
421
  - lib/rails_error_dashboard/services/git_blame_reader.rb
405
422
  - lib/rails_error_dashboard/services/github_link_generator.rb
423
+ - lib/rails_error_dashboard/services/local_variable_capturer.rb
406
424
  - lib/rails_error_dashboard/services/n_plus_one_detector.rb
407
425
  - lib/rails_error_dashboard/services/notification_helpers.rb
408
426
  - lib/rails_error_dashboard/services/notification_throttler.rb
@@ -418,9 +436,12 @@ files:
418
436
  - lib/rails_error_dashboard/services/slack_payload_builder.rb
419
437
  - lib/rails_error_dashboard/services/source_code_reader.rb
420
438
  - lib/rails_error_dashboard/services/statistical_classifier.rb
439
+ - lib/rails_error_dashboard/services/swallowed_exception_tracker.rb
421
440
  - lib/rails_error_dashboard/services/system_health_snapshot.rb
441
+ - lib/rails_error_dashboard/services/variable_serializer.rb
422
442
  - lib/rails_error_dashboard/services/webhook_payload_builder.rb
423
443
  - lib/rails_error_dashboard/subscribers/breadcrumb_subscriber.rb
444
+ - lib/rails_error_dashboard/subscribers/rack_attack_subscriber.rb
424
445
  - lib/rails_error_dashboard/value_objects/error_context.rb
425
446
  - lib/rails_error_dashboard/version.rb
426
447
  - lib/tasks/error_dashboard.rake
@@ -436,7 +457,7 @@ metadata:
436
457
  bug_tracker_uri: https://github.com/AnjanJ/rails_error_dashboard/issues
437
458
  funding_uri: https://buymeacoffee.com/anjanj
438
459
  post_install_message: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n
439
- \ Rails Error Dashboard v0.3.1\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
460
+ \ Rails Error Dashboard v0.4.1\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
440
461
  First time? Quick start:\n rails generate rails_error_dashboard:install\n rails
441
462
  db:migrate\n # Add to config/routes.rb:\n mount RailsErrorDashboard::Engine
442
463
  => '/error_dashboard'\n\n\U0001F504 Upgrading from v0.1.x?\n rails db:migrate\n