rails_error_dashboard 0.1.0

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +858 -0
  4. data/Rakefile +3 -0
  5. data/app/assets/stylesheets/rails_error_dashboard/application.css +15 -0
  6. data/app/controllers/rails_error_dashboard/application_controller.rb +12 -0
  7. data/app/controllers/rails_error_dashboard/errors_controller.rb +123 -0
  8. data/app/helpers/rails_error_dashboard/application_helper.rb +4 -0
  9. data/app/jobs/rails_error_dashboard/application_job.rb +4 -0
  10. data/app/jobs/rails_error_dashboard/discord_error_notification_job.rb +116 -0
  11. data/app/jobs/rails_error_dashboard/email_error_notification_job.rb +19 -0
  12. data/app/jobs/rails_error_dashboard/pagerduty_error_notification_job.rb +105 -0
  13. data/app/jobs/rails_error_dashboard/slack_error_notification_job.rb +166 -0
  14. data/app/jobs/rails_error_dashboard/webhook_error_notification_job.rb +108 -0
  15. data/app/mailers/rails_error_dashboard/application_mailer.rb +8 -0
  16. data/app/mailers/rails_error_dashboard/error_notification_mailer.rb +27 -0
  17. data/app/models/rails_error_dashboard/application_record.rb +5 -0
  18. data/app/models/rails_error_dashboard/error_log.rb +185 -0
  19. data/app/models/rails_error_dashboard/error_logs_record.rb +34 -0
  20. data/app/views/layouts/rails_error_dashboard/application.html.erb +17 -0
  21. data/app/views/layouts/rails_error_dashboard.html.erb +351 -0
  22. data/app/views/rails_error_dashboard/error_notification_mailer/error_alert.html.erb +200 -0
  23. data/app/views/rails_error_dashboard/error_notification_mailer/error_alert.text.erb +32 -0
  24. data/app/views/rails_error_dashboard/errors/analytics.html.erb +237 -0
  25. data/app/views/rails_error_dashboard/errors/index.html.erb +334 -0
  26. data/app/views/rails_error_dashboard/errors/show.html.erb +294 -0
  27. data/config/routes.rb +13 -0
  28. data/db/migrate/20251224000001_create_rails_error_dashboard_error_logs.rb +40 -0
  29. data/db/migrate/20251224081522_add_better_tracking_to_error_logs.rb +13 -0
  30. data/db/migrate/20251224101217_add_controller_action_to_error_logs.rb +10 -0
  31. data/lib/generators/rails_error_dashboard/install/install_generator.rb +27 -0
  32. data/lib/generators/rails_error_dashboard/install/templates/README +33 -0
  33. data/lib/generators/rails_error_dashboard/install/templates/initializer.rb +64 -0
  34. data/lib/rails_error_dashboard/commands/batch_delete_errors.rb +40 -0
  35. data/lib/rails_error_dashboard/commands/batch_resolve_errors.rb +60 -0
  36. data/lib/rails_error_dashboard/commands/log_error.rb +134 -0
  37. data/lib/rails_error_dashboard/commands/resolve_error.rb +35 -0
  38. data/lib/rails_error_dashboard/configuration.rb +83 -0
  39. data/lib/rails_error_dashboard/engine.rb +20 -0
  40. data/lib/rails_error_dashboard/error_reporter.rb +35 -0
  41. data/lib/rails_error_dashboard/middleware/error_catcher.rb +41 -0
  42. data/lib/rails_error_dashboard/plugin.rb +98 -0
  43. data/lib/rails_error_dashboard/plugin_registry.rb +88 -0
  44. data/lib/rails_error_dashboard/plugins/audit_log_plugin.rb +96 -0
  45. data/lib/rails_error_dashboard/plugins/jira_integration_plugin.rb +122 -0
  46. data/lib/rails_error_dashboard/plugins/metrics_plugin.rb +78 -0
  47. data/lib/rails_error_dashboard/queries/analytics_stats.rb +108 -0
  48. data/lib/rails_error_dashboard/queries/dashboard_stats.rb +37 -0
  49. data/lib/rails_error_dashboard/queries/developer_insights.rb +277 -0
  50. data/lib/rails_error_dashboard/queries/errors_list.rb +66 -0
  51. data/lib/rails_error_dashboard/queries/errors_list_v2.rb +149 -0
  52. data/lib/rails_error_dashboard/queries/filter_options.rb +21 -0
  53. data/lib/rails_error_dashboard/services/platform_detector.rb +41 -0
  54. data/lib/rails_error_dashboard/value_objects/error_context.rb +148 -0
  55. data/lib/rails_error_dashboard/version.rb +3 -0
  56. data/lib/rails_error_dashboard.rb +60 -0
  57. data/lib/tasks/rails_error_dashboard_tasks.rake +4 -0
  58. metadata +318 -0
@@ -0,0 +1,200 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
5
+ <style>
6
+ body {
7
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
8
+ line-height: 1.6;
9
+ color: #333;
10
+ max-width: 600px;
11
+ margin: 0 auto;
12
+ padding: 20px;
13
+ }
14
+ .header {
15
+ background: linear-gradient(135deg, #8B5CF6, #6D28D9);
16
+ color: white;
17
+ padding: 20px;
18
+ border-radius: 8px 8px 0 0;
19
+ text-align: center;
20
+ }
21
+ .header h1 {
22
+ margin: 0;
23
+ font-size: 24px;
24
+ }
25
+ .content {
26
+ background: #ffffff;
27
+ border: 1px solid #e5e7eb;
28
+ border-top: none;
29
+ padding: 20px;
30
+ border-radius: 0 0 8px 8px;
31
+ }
32
+ .info-grid {
33
+ display: grid;
34
+ grid-template-columns: 150px 1fr;
35
+ gap: 10px;
36
+ margin: 20px 0;
37
+ }
38
+ .label {
39
+ font-weight: 600;
40
+ color: #6B7280;
41
+ }
42
+ .value {
43
+ color: #1F2937;
44
+ }
45
+ .error-message {
46
+ background: #FEF2F2;
47
+ border-left: 4px solid #EF4444;
48
+ padding: 15px;
49
+ margin: 20px 0;
50
+ border-radius: 4px;
51
+ }
52
+ .error-message code {
53
+ background: #FEE2E2;
54
+ padding: 2px 6px;
55
+ border-radius: 3px;
56
+ font-size: 14px;
57
+ color: #991B1B;
58
+ }
59
+ .backtrace {
60
+ background: #F9FAFB;
61
+ border: 1px solid #E5E7EB;
62
+ padding: 15px;
63
+ border-radius: 4px;
64
+ overflow-x: auto;
65
+ margin: 20px 0;
66
+ }
67
+ .backtrace pre {
68
+ margin: 0;
69
+ font-size: 12px;
70
+ color: #4B5563;
71
+ white-space: pre-wrap;
72
+ word-wrap: break-word;
73
+ }
74
+ .badge {
75
+ display: inline-block;
76
+ padding: 4px 12px;
77
+ border-radius: 12px;
78
+ font-size: 12px;
79
+ font-weight: 600;
80
+ text-transform: uppercase;
81
+ }
82
+ .badge-production {
83
+ background: #FEE2E2;
84
+ color: #991B1B;
85
+ }
86
+ .badge-staging {
87
+ background: #FEF3C7;
88
+ color: #92400E;
89
+ }
90
+ .badge-development {
91
+ background: #D1FAE5;
92
+ color: #065F46;
93
+ }
94
+ .badge-ios {
95
+ background: #000000;
96
+ color: #FFFFFF;
97
+ }
98
+ .badge-android {
99
+ background: #3DDC84;
100
+ color: #000000;
101
+ }
102
+ .badge-api {
103
+ background: #DBEAFE;
104
+ color: #1E40AF;
105
+ }
106
+ .button {
107
+ display: inline-block;
108
+ background: #8B5CF6;
109
+ color: white;
110
+ padding: 12px 24px;
111
+ text-decoration: none;
112
+ border-radius: 6px;
113
+ font-weight: 600;
114
+ margin: 20px 0;
115
+ }
116
+ .button:hover {
117
+ background: #7C3AED;
118
+ }
119
+ .footer {
120
+ margin-top: 30px;
121
+ padding-top: 20px;
122
+ border-top: 1px solid #E5E7EB;
123
+ color: #6B7280;
124
+ font-size: 12px;
125
+ text-align: center;
126
+ }
127
+ </style>
128
+ </head>
129
+ <body>
130
+ <div class="header">
131
+ <h1>🚨 Error Alert</h1>
132
+ </div>
133
+
134
+ <div class="content">
135
+ <div class="info-grid">
136
+ <div class="label">Error Type:</div>
137
+ <div class="value"><code><%= @error_log.error_type %></code></div>
138
+
139
+ <div class="label">Environment:</div>
140
+ <div class="value">
141
+ <span class="badge badge-<%= @error_log.environment %>">
142
+ <%= @error_log.environment.upcase %>
143
+ </span>
144
+ </div>
145
+
146
+ <% if @error_log.platform.present? %>
147
+ <div class="label">Platform:</div>
148
+ <div class="value">
149
+ <span class="badge badge-<%= @error_log.platform.downcase %>">
150
+ <%= @error_log.platform %>
151
+ </span>
152
+ </div>
153
+ <% end %>
154
+
155
+ <div class="label">Occurred At:</div>
156
+ <div class="value"><%= @error_log.occurred_at.strftime('%B %d, %Y at %I:%M %p %Z') %></div>
157
+
158
+ <% if @error_log.user.present? %>
159
+ <div class="label">User:</div>
160
+ <div class="value"><%= @error_log.user.email %></div>
161
+ <% end %>
162
+
163
+ <% if @error_log.ip_address.present? %>
164
+ <div class="label">IP Address:</div>
165
+ <div class="value"><%= @error_log.ip_address %></div>
166
+ <% end %>
167
+
168
+ <% if @error_log.request_url.present? %>
169
+ <div class="label">Request URL:</div>
170
+ <div class="value"><%= @error_log.request_url %></div>
171
+ <% end %>
172
+ </div>
173
+
174
+ <div class="error-message">
175
+ <strong>Message:</strong><br/>
176
+ <code><%= @error_log.message %></code>
177
+ </div>
178
+
179
+ <% if @error_log.backtrace.present? %>
180
+ <div class="backtrace">
181
+ <strong>Stack Trace (first 10 lines):</strong>
182
+ <pre><%= @error_log.backtrace.split("\n").first(10).join("\n") %></pre>
183
+ </div>
184
+ <% end %>
185
+
186
+ <div style="text-align: center;">
187
+ <a href="<%= @dashboard_url %>" class="button">
188
+ View Full Details in Dashboard
189
+ </a>
190
+ </div>
191
+
192
+ <div class="footer">
193
+ <p>
194
+ This is an automated error notification from Rails Error Dashboard.<br/>
195
+ Error ID: <%= @error_log.id %>
196
+ </p>
197
+ </div>
198
+ </div>
199
+ </body>
200
+ </html>
@@ -0,0 +1,32 @@
1
+ ==========================================
2
+ 🚨 ERROR ALERT
3
+ ==========================================
4
+
5
+ Error Type: <%= @error_log.error_type %>
6
+ Environment: <%= @error_log.environment.upcase %>
7
+ <% if @error_log.platform.present? %>Platform: <%= @error_log.platform %><% end %>
8
+ Occurred At: <%= @error_log.occurred_at.strftime('%B %d, %Y at %I:%M %p %Z') %>
9
+ <% if @error_log.user.present? %>User: <%= @error_log.user.email %><% end %>
10
+ <% if @error_log.ip_address.present? %>IP Address: <%= @error_log.ip_address %><% end %>
11
+ <% if @error_log.request_url.present? %>Request URL: <%= @error_log.request_url %><% end %>
12
+
13
+ ------------------------------------------
14
+ MESSAGE
15
+ ------------------------------------------
16
+ <%= @error_log.message %>
17
+
18
+ <% if @error_log.backtrace.present? %>
19
+ ------------------------------------------
20
+ STACK TRACE (first 10 lines)
21
+ ------------------------------------------
22
+ <%= @error_log.backtrace.split("\n").first(10).join("\n") %>
23
+ <% end %>
24
+
25
+ ------------------------------------------
26
+
27
+ View full details in the dashboard:
28
+ <%= @dashboard_url %>
29
+
30
+ Error ID: <%= @error_log.id %>
31
+
32
+ This is an automated error notification from Rails Error Dashboard.
@@ -0,0 +1,237 @@
1
+ <div class="py-4">
2
+ <div class="d-flex justify-content-between align-items-center mb-4">
3
+ <h2 class="mb-0"><i class="bi bi-graph-up text-primary"></i> Error Analytics</h2>
4
+ <div>
5
+ <%= form_with url: analytics_errors_path, method: :get, class: "d-flex gap-2" do %>
6
+ <%= select_tag :days, options_for_select([
7
+ ['Last 7 Days', 7],
8
+ ['Last 14 Days', 14],
9
+ ['Last 30 Days', 30],
10
+ ['Last 60 Days', 60],
11
+ ['Last 90 Days', 90]
12
+ ], @days), class: "form-select", onchange: "this.form.submit()" %>
13
+ <% end %>
14
+ </div>
15
+ </div>
16
+
17
+ <!-- Summary Stats -->
18
+ <div class="row g-4 mb-4">
19
+ <div class="col-md-3">
20
+ <div class="card stat-card border-primary">
21
+ <div class="card-body">
22
+ <div class="stat-label mb-2 text-primary">Total Errors</div>
23
+ <div class="stat-value text-primary"><%= @error_stats[:total] %></div>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ <div class="col-md-3">
28
+ <div class="card stat-card border-danger">
29
+ <div class="card-body">
30
+ <div class="stat-label mb-2 text-danger">Unresolved</div>
31
+ <div class="stat-value text-danger"><%= @error_stats[:unresolved] %></div>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <div class="col-md-3">
36
+ <div class="card stat-card border-success">
37
+ <div class="card-body">
38
+ <div class="stat-label mb-2 text-success">Resolution Rate</div>
39
+ <div class="stat-value text-success"><%= @resolution_rate %>%</div>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ <div class="col-md-3">
44
+ <div class="card stat-card border-info">
45
+ <div class="card-body">
46
+ <div class="stat-label mb-2 text-info">Mobile Errors</div>
47
+ <div class="stat-value text-info"><%= @mobile_errors %></div>
48
+ <small class="text-muted">vs <%= @api_errors %> API</small>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </div>
53
+
54
+ <!-- Error Trend Chart -->
55
+ <div class="card mb-4">
56
+ <div class="card-header bg-white">
57
+ <h5 class="mb-0"><i class="bi bi-graph-up"></i> Error Trend (Last <%= @days %> Days)</h5>
58
+ </div>
59
+ <div class="card-body">
60
+ <%= line_chart @errors_over_time,
61
+ color: "#8B5CF6",
62
+ curve: false,
63
+ points: true,
64
+ height: "300px",
65
+ xtitle: "Date",
66
+ ytitle: "Number of Errors" %>
67
+ </div>
68
+ </div>
69
+
70
+ <!-- Charts Row 1 -->
71
+ <div class="row g-4 mb-4">
72
+ <div class="col-md-6">
73
+ <div class="card">
74
+ <div class="card-header bg-white">
75
+ <h5 class="mb-0"><i class="bi bi-phone"></i> Errors by Platform</h5>
76
+ </div>
77
+ <div class="card-body">
78
+ <%= pie_chart @errors_by_platform,
79
+ colors: ["#000000", "#3DDC84", "#3B82F6"],
80
+ height: "300px",
81
+ legend: "bottom",
82
+ donut: true %>
83
+ </div>
84
+ </div>
85
+ </div>
86
+
87
+ <div class="col-md-6">
88
+ <div class="card">
89
+ <div class="card-header bg-white">
90
+ <h5 class="mb-0"><i class="bi bi-server"></i> Errors by Environment</h5>
91
+ </div>
92
+ <div class="card-body">
93
+ <%= pie_chart @errors_by_environment,
94
+ colors: ["#10B981", "#EF4444", "#F59E0B"],
95
+ height: "300px",
96
+ legend: "bottom",
97
+ donut: true %>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ </div>
102
+
103
+ <!-- Charts Row 2 -->
104
+ <div class="row g-4 mb-4">
105
+ <div class="col-md-12">
106
+ <div class="card">
107
+ <div class="card-header bg-white">
108
+ <h5 class="mb-0"><i class="bi bi-bug"></i> Top 10 Error Types</h5>
109
+ </div>
110
+ <div class="card-body">
111
+ <%= bar_chart @errors_by_type,
112
+ color: "#EF4444",
113
+ height: "400px",
114
+ xtitle: "Error Type",
115
+ ytitle: "Count" %>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ </div>
120
+
121
+ <!-- Charts Row 3 -->
122
+ <div class="row g-4 mb-4">
123
+ <div class="col-md-12">
124
+ <div class="card">
125
+ <div class="card-header bg-white">
126
+ <h5 class="mb-0"><i class="bi bi-clock"></i> Errors by Hour of Day</h5>
127
+ </div>
128
+ <div class="card-body">
129
+ <%= column_chart @errors_by_hour,
130
+ color: "#8B5CF6",
131
+ height: "300px",
132
+ xtitle: "Hour",
133
+ ytitle: "Number of Errors" %>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ </div>
138
+
139
+ <!-- Top Users Table -->
140
+ <% if @top_users.any? %>
141
+ <div class="row g-4 mb-4">
142
+ <div class="col-md-12">
143
+ <div class="card">
144
+ <div class="card-header bg-white">
145
+ <h5 class="mb-0"><i class="bi bi-people"></i> Top 10 Affected Users</h5>
146
+ </div>
147
+ <div class="card-body p-0">
148
+ <div class="table-responsive">
149
+ <table class="table table-hover mb-0">
150
+ <thead class="table-light">
151
+ <tr>
152
+ <th>Rank</th>
153
+ <th>User</th>
154
+ <th>Error Count</th>
155
+ <th>Percentage</th>
156
+ </tr>
157
+ </thead>
158
+ <tbody>
159
+ <% @top_users.each_with_index do |(email, count), index| %>
160
+ <tr>
161
+ <td><strong>#<%= index + 1 %></strong></td>
162
+ <td><%= email %></td>
163
+ <td><span class="badge bg-danger"><%= count %></span></td>
164
+ <td>
165
+ <div class="progress" style="height: 20px;">
166
+ <div class="progress-bar bg-danger"
167
+ role="progressbar"
168
+ style="width: <%= (count.to_f / @error_stats[:total] * 100).round(1) %>%"
169
+ aria-valuenow="<%= count %>"
170
+ aria-valuemin="0"
171
+ aria-valuemax="<%= @error_stats[:total] %>">
172
+ <%= (count.to_f / @error_stats[:total] * 100).round(1) %>%
173
+ </div>
174
+ </div>
175
+ </td>
176
+ </tr>
177
+ <% end %>
178
+ </tbody>
179
+ </table>
180
+ </div>
181
+ </div>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ <% end %>
186
+
187
+ <!-- Error Type Breakdown Table -->
188
+ <div class="row g-4">
189
+ <div class="col-md-12">
190
+ <div class="card">
191
+ <div class="card-header bg-white d-flex justify-content-between align-items-center">
192
+ <h5 class="mb-0"><i class="bi bi-list-check"></i> Error Type Breakdown</h5>
193
+ <small class="text-muted">Last <%= @days %> days</small>
194
+ </div>
195
+ <div class="card-body p-0">
196
+ <div class="table-responsive">
197
+ <table class="table table-hover mb-0">
198
+ <thead class="table-light">
199
+ <tr>
200
+ <th>Rank</th>
201
+ <th>Error Type</th>
202
+ <th>Count</th>
203
+ <th>Percentage</th>
204
+ <th>Actions</th>
205
+ </tr>
206
+ </thead>
207
+ <tbody>
208
+ <% @error_stats[:by_type].each_with_index do |(error_type, count), index| %>
209
+ <tr>
210
+ <td><strong>#<%= index + 1 %></strong></td>
211
+ <td><code class="text-danger"><%= error_type %></code></td>
212
+ <td><span class="badge bg-secondary"><%= count %></span></td>
213
+ <td>
214
+ <div class="progress" style="height: 20px; min-width: 200px;">
215
+ <div class="progress-bar"
216
+ role="progressbar"
217
+ style="width: <%= (count.to_f / @error_stats[:total] * 100).round(1) %>%"
218
+ aria-valuenow="<%= count %>"
219
+ aria-valuemin="0"
220
+ aria-valuemax="<%= @error_stats[:total] %>">
221
+ <%= (count.to_f / @error_stats[:total] * 100).round(1) %>%
222
+ </div>
223
+ </div>
224
+ </td>
225
+ <td>
226
+ <%= link_to "View Errors", errors_path(error_type: error_type), class: "btn btn-sm btn-outline-primary" %>
227
+ </td>
228
+ </tr>
229
+ <% end %>
230
+ </tbody>
231
+ </table>
232
+ </div>
233
+ </div>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ </div>