rails_error_dashboard 0.5.15 → 0.6.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/rails_error_dashboard/application_controller.rb +37 -12
  3. data/app/controllers/rails_error_dashboard/errors_controller.rb +48 -26
  4. data/app/helpers/rails_error_dashboard/application_helper.rb +12 -5
  5. data/app/views/layouts/rails_error_dashboard.html.erb +1219 -1927
  6. data/app/views/rails_error_dashboard/errors/_breadcrumbs_group.html.erb +4 -4
  7. data/app/views/rails_error_dashboard/errors/_co_occurring_errors.html.erb +1 -1
  8. data/app/views/rails_error_dashboard/errors/_discussion.html.erb +3 -3
  9. data/app/views/rails_error_dashboard/errors/_error_cascades.html.erb +1 -1
  10. data/app/views/rails_error_dashboard/errors/_error_row.html.erb +69 -79
  11. data/app/views/rails_error_dashboard/errors/_instance_variables.html.erb +1 -1
  12. data/app/views/rails_error_dashboard/errors/_issue_section.html.erb +1 -1
  13. data/app/views/rails_error_dashboard/errors/_local_variables.html.erb +1 -1
  14. data/app/views/rails_error_dashboard/errors/_pattern_insights.html.erb +2 -2
  15. data/app/views/rails_error_dashboard/errors/_request_context.html.erb +1 -1
  16. data/app/views/rails_error_dashboard/errors/_sidebar_metadata.html.erb +1 -1
  17. data/app/views/rails_error_dashboard/errors/_similar_errors.html.erb +1 -1
  18. data/app/views/rails_error_dashboard/errors/_timeline.html.erb +4 -4
  19. data/app/views/rails_error_dashboard/errors/actioncable_health_summary.html.erb +6 -6
  20. data/app/views/rails_error_dashboard/errors/activestorage_health_summary.html.erb +6 -6
  21. data/app/views/rails_error_dashboard/errors/analytics.html.erb +34 -50
  22. data/app/views/rails_error_dashboard/errors/cache_health_summary.html.erb +7 -7
  23. data/app/views/rails_error_dashboard/errors/correlation.html.erb +11 -11
  24. data/app/views/rails_error_dashboard/errors/database_health_summary.html.erb +114 -172
  25. data/app/views/rails_error_dashboard/errors/deprecations.html.erb +7 -7
  26. data/app/views/rails_error_dashboard/errors/diagnostic_dumps.html.erb +6 -6
  27. data/app/views/rails_error_dashboard/errors/index.html.erb +311 -613
  28. data/app/views/rails_error_dashboard/errors/job_health_summary.html.erb +7 -7
  29. data/app/views/rails_error_dashboard/errors/n_plus_one_summary.html.erb +7 -7
  30. data/app/views/rails_error_dashboard/errors/overview.html.erb +192 -363
  31. data/app/views/rails_error_dashboard/errors/platform_comparison.html.erb +11 -11
  32. data/app/views/rails_error_dashboard/errors/rack_attack_summary.html.erb +6 -6
  33. data/app/views/rails_error_dashboard/errors/releases.html.erb +6 -6
  34. data/app/views/rails_error_dashboard/errors/settings.html.erb +53 -51
  35. data/app/views/rails_error_dashboard/errors/show.html.erb +200 -203
  36. data/app/views/rails_error_dashboard/errors/swallowed_exceptions.html.erb +19 -19
  37. data/app/views/rails_error_dashboard/errors/user_impact.html.erb +6 -6
  38. data/config/routes.rb +1 -0
  39. data/lib/rails_error_dashboard/configuration.rb +6 -0
  40. data/lib/rails_error_dashboard/services/error_broadcaster.rb +1 -1
  41. data/lib/rails_error_dashboard/services/system_health_snapshot.rb +1 -1
  42. data/lib/rails_error_dashboard/test_error.rb +7 -0
  43. data/lib/rails_error_dashboard/version.rb +1 -1
  44. data/lib/rails_error_dashboard.rb +1 -0
  45. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3569ff68dcb977b53c8565d17e3f95de2b28b9c3abc462c77c6877277f79d101
4
- data.tar.gz: b27615768c8fc87bca5f55f0deee1d4f1ec5c9c7466956480180808779708fc9
3
+ metadata.gz: 8730984999d2ab508eeefe889bfd320e54cb9395c6baacbe87fef1a3aa20de7a
4
+ data.tar.gz: 6a301193d907d990418f6a74b83ee36a54caeac1b05dc57a75ea24213e9b7f7c
5
5
  SHA512:
6
- metadata.gz: 85b4d1f4017fafc58181547f3fca6c87b19d72b4b19092462dd89cdfd35cc7d84cd2203244b5273db2e7901e09c54530a8ee53baf904eccbb016f7df64b3cfbe
7
- data.tar.gz: f77c96cdd3d5e322025086c889417af20668bdd8cbf582fb93b512eecaed4971596db330a81fe7912536e6bace26dab34f9d88b31f88123a887f0b0468d0a1db
6
+ metadata.gz: af05b90ebe19d1b90adb82b7e8d3a4cd57faf695327c3a51c2d36ced221d1951265e4d88d77e4ddb843c465582fe14d6911141e3f081b2de76ca3037a4e637f0
7
+ data.tar.gz: add93453ac6ebee6a3f320fc336fe30c81a952f58fc30b3b8554c410071586da7d9c25da1d886c5976b4ade28cc6504c5b355509a29dcf5025aa8b502d1fff65
@@ -23,23 +23,27 @@ module RailsErrorDashboard
23
23
  Rails.logger.error("Params: #{params.inspect}")
24
24
  Rails.logger.error(exception.backtrace&.first(10)&.join("\n")) if exception.backtrace
25
25
 
26
- # Render user-friendly error page
27
- render plain: "The Error Dashboard encountered an issue displaying this page.\n\n" \
28
- "Your application is unaffected - this is only a dashboard display error.\n\n" \
29
- "Error: #{exception.message}\n\n" \
30
- "Check Rails logs for details: [RailsErrorDashboard]",
31
- status: :internal_server_error,
32
- layout: false
26
+ render_dashboard_error(
27
+ icon: "bi-exclamation-triangle",
28
+ icon_style: "background: var(--status-warning-bg); color: var(--status-warning);",
29
+ title: "Something went wrong",
30
+ message: "The Error Dashboard encountered an issue displaying this page. Your application is unaffected.",
31
+ detail: exception.message,
32
+ status: :internal_server_error
33
+ )
33
34
  end
34
35
 
35
36
  # Handle record not found — return 404 instead of 500
36
37
  rescue_from ActiveRecord::RecordNotFound do |exception|
37
38
  Rails.logger.warn("[RailsErrorDashboard] Record not found: #{exception.message}")
38
- render plain: "The requested error was not found.\n\n" \
39
- "It may have been deleted or the ID is invalid.\n\n" \
40
- "Error: #{exception.message}",
41
- status: :not_found,
42
- layout: false
39
+
40
+ render_dashboard_error(
41
+ icon: "bi-search",
42
+ title: "The requested error was not found",
43
+ message: "It may have been deleted or the ID is invalid.",
44
+ detail: exception.message,
45
+ status: :not_found
46
+ )
43
47
  end
44
48
 
45
49
  # Handle Pagy pagination errors — redirect to page 1
@@ -47,5 +51,26 @@ module RailsErrorDashboard
47
51
  Rails.logger.warn("[RailsErrorDashboard] Pagination error: #{exception.message}")
48
52
  redirect_to request.path, status: :moved_permanently
49
53
  end
54
+
55
+ private
56
+
57
+ def render_dashboard_error(icon:, title:, message:, detail: nil, icon_style: nil, status: :internal_server_error)
58
+ set_common_view_variables
59
+ error_html = <<~ERB
60
+ <div class="red-empty-state" style="margin-top: var(--space-6);">
61
+ <div class="red-empty-state-icon"#{icon_style ? " style=\"#{icon_style}\"" : ""}><i class="bi #{icon}"></i></div>
62
+ <div class="red-empty-state-title">#{ERB::Util.html_escape(title)}</div>
63
+ <div class="red-empty-state-message">#{ERB::Util.html_escape(message)}</div>
64
+ #{"<div style=\"font-size: 12px; color: var(--text-tertiary); margin-top: var(--space-2); font-family: var(--font-mono);\">" + ERB::Util.html_escape(detail) + "</div>" if detail}
65
+ <a href="#{errors_path}" class="red-empty-state-cta" style="margin-top: var(--space-4);"><i class="bi bi-arrow-left"></i> Back to errors</a>
66
+ </div>
67
+ ERB
68
+ render html: error_html.html_safe, status: status, layout: "rails_error_dashboard"
69
+ end
70
+
71
+ def set_common_view_variables
72
+ @applications = Application.ordered_by_name.pluck(:name, :id) rescue []
73
+ @default_credentials_warning = RailsErrorDashboard.configuration.default_credentials? rescue false
74
+ end
50
75
  end
51
76
  end
@@ -98,49 +98,49 @@ module RailsErrorDashboard
98
98
  resolution_reference: params[:resolution_reference]
99
99
  )
100
100
 
101
- redirect_to error_path(@error)
101
+ redirect_to error_path(@error, **app_context_params)
102
102
  end
103
103
 
104
104
  # Phase 3: Workflow Integration Actions (via Commands)
105
105
 
106
106
  def assign
107
107
  @error = Commands::AssignError.call(params[:id], assigned_to: params[:assigned_to])
108
- redirect_to error_path(@error)
108
+ redirect_to error_path(@error, **app_context_params)
109
109
  end
110
110
 
111
111
  def unassign
112
112
  @error = Commands::UnassignError.call(params[:id])
113
- redirect_to error_path(@error)
113
+ redirect_to error_path(@error, **app_context_params)
114
114
  end
115
115
 
116
116
  def update_priority
117
117
  @error = Commands::UpdateErrorPriority.call(params[:id], priority_level: params[:priority_level])
118
- redirect_to error_path(@error)
118
+ redirect_to error_path(@error, **app_context_params)
119
119
  end
120
120
 
121
121
  def snooze
122
122
  @error = Commands::SnoozeError.call(params[:id], hours: params[:hours].to_i, reason: params[:reason])
123
- redirect_to error_path(@error)
123
+ redirect_to error_path(@error, **app_context_params)
124
124
  end
125
125
 
126
126
  def unsnooze
127
127
  @error = Commands::UnsnoozeError.call(params[:id])
128
- redirect_to error_path(@error)
128
+ redirect_to error_path(@error, **app_context_params)
129
129
  end
130
130
 
131
131
  def mute
132
132
  @error = Commands::MuteError.call(params[:id], muted_by: params[:muted_by], reason: params[:reason])
133
- redirect_to error_path(@error)
133
+ redirect_to error_path(@error, **app_context_params)
134
134
  end
135
135
 
136
136
  def unmute
137
137
  @error = Commands::UnmuteError.call(params[:id])
138
- redirect_to error_path(@error)
138
+ redirect_to error_path(@error, **app_context_params)
139
139
  end
140
140
 
141
141
  def update_status
142
142
  result = Commands::UpdateErrorStatus.call(params[:id], status: params[:status], comment: params[:comment])
143
- redirect_to error_path(result[:error])
143
+ redirect_to error_path(result[:error], **app_context_params)
144
144
  end
145
145
 
146
146
  def create_issue
@@ -153,7 +153,7 @@ module RailsErrorDashboard
153
153
  else
154
154
  flash[:alert] = "Failed to create issue: #{result[:error]}"
155
155
  end
156
- redirect_to error_path(params[:id], anchor: "issue-tracking")
156
+ redirect_to error_path(params[:id], anchor: "issue-tracking", **app_context_params)
157
157
  end
158
158
 
159
159
  def link_issue
@@ -164,7 +164,7 @@ module RailsErrorDashboard
164
164
  else
165
165
  flash[:alert] = "Failed to link issue: #{result[:error]}"
166
166
  end
167
- redirect_to error_path(params[:id], anchor: "issue-tracking")
167
+ redirect_to error_path(params[:id], anchor: "issue-tracking", **app_context_params)
168
168
  end
169
169
 
170
170
  def analytics
@@ -205,7 +205,7 @@ module RailsErrorDashboard
205
205
  # Check if feature is enabled
206
206
  unless RailsErrorDashboard.configuration.enable_platform_comparison
207
207
  flash[:alert] = "Platform Comparison is not enabled. Enable it in config/initializers/rails_error_dashboard.rb"
208
- redirect_to errors_path
208
+ redirect_to errors_path(**app_context_params)
209
209
  return
210
210
  end
211
211
 
@@ -252,14 +252,14 @@ module RailsErrorDashboard
252
252
  flash[:alert] = "Batch operation failed: #{result[:errors].join(', ')}"
253
253
  end
254
254
 
255
- redirect_to errors_path
255
+ redirect_to errors_path(**app_context_params)
256
256
  end
257
257
 
258
258
  def correlation
259
259
  # Check if feature is enabled
260
260
  unless RailsErrorDashboard.configuration.enable_error_correlation
261
261
  flash[:alert] = "Error Correlation is not enabled. Enable it in config/initializers/rails_error_dashboard.rb"
262
- redirect_to errors_path
262
+ redirect_to errors_path(**app_context_params)
263
263
  return
264
264
  end
265
265
 
@@ -299,7 +299,7 @@ module RailsErrorDashboard
299
299
  def deprecations
300
300
  unless RailsErrorDashboard.configuration.enable_breadcrumbs
301
301
  flash[:alert] = "Breadcrumbs are not enabled. Enable them in config/initializers/rails_error_dashboard.rb"
302
- redirect_to errors_path
302
+ redirect_to errors_path(**app_context_params)
303
303
  return
304
304
  end
305
305
 
@@ -319,7 +319,7 @@ module RailsErrorDashboard
319
319
  def n_plus_one_summary
320
320
  unless RailsErrorDashboard.configuration.enable_breadcrumbs
321
321
  flash[:alert] = "Breadcrumbs are not enabled. Enable them in config/initializers/rails_error_dashboard.rb"
322
- redirect_to errors_path
322
+ redirect_to errors_path(**app_context_params)
323
323
  return
324
324
  end
325
325
 
@@ -339,7 +339,7 @@ module RailsErrorDashboard
339
339
  def cache_health_summary
340
340
  unless RailsErrorDashboard.configuration.enable_breadcrumbs
341
341
  flash[:alert] = "Breadcrumbs are not enabled. Enable them in config/initializers/rails_error_dashboard.rb"
342
- redirect_to errors_path
342
+ redirect_to errors_path(**app_context_params)
343
343
  return
344
344
  end
345
345
 
@@ -360,7 +360,7 @@ module RailsErrorDashboard
360
360
  def job_health_summary
361
361
  unless RailsErrorDashboard.configuration.enable_system_health
362
362
  flash[:alert] = "System health is not enabled. Enable it in config/initializers/rails_error_dashboard.rb"
363
- redirect_to errors_path
363
+ redirect_to errors_path(**app_context_params)
364
364
  return
365
365
  end
366
366
 
@@ -380,7 +380,7 @@ module RailsErrorDashboard
380
380
  def database_health_summary
381
381
  unless RailsErrorDashboard.configuration.enable_system_health
382
382
  flash[:alert] = "System health is not enabled. Enable it in config/initializers/rails_error_dashboard.rb"
383
- redirect_to errors_path
383
+ redirect_to errors_path(**app_context_params)
384
384
  return
385
385
  end
386
386
 
@@ -416,7 +416,7 @@ module RailsErrorDashboard
416
416
  else
417
417
  flash[:alert] = "Swallowed exception detection is not enabled. Enable it in config/initializers/rails_error_dashboard.rb"
418
418
  end
419
- redirect_to errors_path
419
+ redirect_to errors_path(**app_context_params)
420
420
  return
421
421
  end
422
422
 
@@ -437,7 +437,7 @@ module RailsErrorDashboard
437
437
  unless RailsErrorDashboard.configuration.enable_rack_attack_tracking &&
438
438
  RailsErrorDashboard.configuration.enable_breadcrumbs
439
439
  flash[:alert] = "Rack Attack tracking is not enabled. Enable enable_rack_attack_tracking and enable_breadcrumbs in config/initializers/rails_error_dashboard.rb"
440
- redirect_to errors_path
440
+ redirect_to errors_path(**app_context_params)
441
441
  return
442
442
  end
443
443
 
@@ -458,7 +458,7 @@ module RailsErrorDashboard
458
458
  unless RailsErrorDashboard.configuration.enable_actioncable_tracking &&
459
459
  RailsErrorDashboard.configuration.enable_breadcrumbs
460
460
  flash[:alert] = "ActionCable tracking is not enabled. Enable enable_actioncable_tracking and enable_breadcrumbs in config/initializers/rails_error_dashboard.rb"
461
- redirect_to errors_path
461
+ redirect_to errors_path(**app_context_params)
462
462
  return
463
463
  end
464
464
 
@@ -479,7 +479,7 @@ module RailsErrorDashboard
479
479
  unless RailsErrorDashboard.configuration.enable_activestorage_tracking &&
480
480
  RailsErrorDashboard.configuration.enable_breadcrumbs
481
481
  flash[:alert] = "ActiveStorage tracking is not enabled. Enable enable_activestorage_tracking and enable_breadcrumbs in config/initializers/rails_error_dashboard.rb"
482
- redirect_to errors_path
482
+ redirect_to errors_path(**app_context_params)
483
483
  return
484
484
  end
485
485
 
@@ -499,7 +499,7 @@ module RailsErrorDashboard
499
499
  def diagnostic_dumps
500
500
  unless RailsErrorDashboard.configuration.enable_diagnostic_dump
501
501
  flash[:alert] = "Diagnostic dumps are not enabled. Enable them in config/initializers/rails_error_dashboard.rb"
502
- redirect_to errors_path
502
+ redirect_to errors_path(**app_context_params)
503
503
  return
504
504
  end
505
505
 
@@ -513,7 +513,7 @@ module RailsErrorDashboard
513
513
  def create_diagnostic_dump
514
514
  unless RailsErrorDashboard.configuration.enable_diagnostic_dump
515
515
  flash[:alert] = "Diagnostic dumps are not enabled."
516
- redirect_to errors_path
516
+ redirect_to errors_path(**app_context_params)
517
517
  return
518
518
  end
519
519
 
@@ -542,7 +542,7 @@ module RailsErrorDashboard
542
542
  def enable_coverage
543
543
  unless RailsErrorDashboard.configuration.enable_coverage_tracking
544
544
  flash[:alert] = "Coverage tracking is not enabled in configuration."
545
- redirect_to errors_path
545
+ redirect_to errors_path(**app_context_params)
546
546
  return
547
547
  end
548
548
 
@@ -560,6 +560,23 @@ module RailsErrorDashboard
560
560
  redirect_back fallback_location: errors_path
561
561
  end
562
562
 
563
+ def test_error
564
+ exception = RailsErrorDashboard::TestError.new(
565
+ "[RED Test] This is a test error sent from the dashboard to verify " \
566
+ "that error capture and notification delivery are working correctly. " \
567
+ "It is safe to resolve or delete this error."
568
+ )
569
+ exception.set_backtrace(caller)
570
+
571
+ Commands::LogError.call(exception, { request: request, source: "dashboard.test_error" })
572
+
573
+ flash[:notice] = "Test error logged successfully. Check your notification channels (Slack, Discord, email, etc.) to confirm delivery."
574
+ redirect_to errors_path(**app_context_params)
575
+ rescue => e
576
+ flash[:alert] = "Failed to log test error: #{e.message}"
577
+ redirect_to settings_path(**app_context_params)
578
+ end
579
+
563
580
  def settings
564
581
  @config = RailsErrorDashboard.configuration
565
582
  end
@@ -595,6 +612,11 @@ module RailsErrorDashboard
595
612
  @applications = Application.ordered_by_name.pluck(:name, :id)
596
613
  end
597
614
 
615
+ # Preserves the application_id param across redirects
616
+ def app_context_params
617
+ @current_application_id.present? ? { application_id: @current_application_id } : {}
618
+ end
619
+
598
620
  def fetch_platform_issue(error)
599
621
  return nil unless error.external_issue_url.present? && error.external_issue_number.present?
600
622
  return nil unless RailsErrorDashboard.configuration.enable_issue_tracking
@@ -26,15 +26,15 @@ module RailsErrorDashboard
26
26
  def severity_color_var(severity)
27
27
  case severity&.to_sym
28
28
  when :critical
29
- "var(--ctp-red)"
29
+ "var(--status-critical)"
30
30
  when :high
31
- "var(--ctp-peach)"
31
+ "var(--status-warning)"
32
32
  when :medium
33
- "var(--ctp-blue)"
33
+ "var(--status-info)"
34
34
  when :low
35
- "var(--ctp-overlay1)"
35
+ "var(--text-tertiary)"
36
36
  else
37
- "var(--ctp-overlay1)"
37
+ "var(--text-tertiary)"
38
38
  end
39
39
  end
40
40
 
@@ -74,6 +74,13 @@ module RailsErrorDashboard
74
74
  end
75
75
  end
76
76
 
77
+ # Returns the current application context param for preserving app selection across navigation.
78
+ # Use this in link helpers: errors_path(app_context) or error_path(error, **app_context)
79
+ # @return [Hash] { application_id: X } if an app is selected, empty hash otherwise
80
+ def app_context
81
+ params[:application_id].present? ? { application_id: params[:application_id] } : {}
82
+ end
83
+
77
84
  # Returns a sanitized hash of filter params safe for query links
78
85
  # @param extra_keys [Array<Symbol>] Additional permitted keys for specific contexts
79
86
  # @return [Hash] Whitelisted params for building URLs