rails_error_dashboard 0.1.28 → 0.1.30

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +50 -6
  3. data/app/controllers/rails_error_dashboard/errors_controller.rb +22 -0
  4. data/app/helpers/rails_error_dashboard/application_helper.rb +79 -7
  5. data/app/helpers/rails_error_dashboard/backtrace_helper.rb +149 -0
  6. data/app/models/rails_error_dashboard/application.rb +1 -1
  7. data/app/models/rails_error_dashboard/error_log.rb +44 -16
  8. data/app/views/layouts/rails_error_dashboard.html.erb +71 -1237
  9. data/app/views/rails_error_dashboard/errors/_error_row.html.erb +10 -2
  10. data/app/views/rails_error_dashboard/errors/_source_code.html.erb +76 -0
  11. data/app/views/rails_error_dashboard/errors/_timeline.html.erb +18 -82
  12. data/app/views/rails_error_dashboard/errors/_user_errors_table.html.erb +70 -0
  13. data/app/views/rails_error_dashboard/errors/analytics.html.erb +9 -37
  14. data/app/views/rails_error_dashboard/errors/correlation.html.erb +11 -37
  15. data/app/views/rails_error_dashboard/errors/index.html.erb +64 -31
  16. data/app/views/rails_error_dashboard/errors/overview.html.erb +181 -3
  17. data/app/views/rails_error_dashboard/errors/platform_comparison.html.erb +2 -1
  18. data/app/views/rails_error_dashboard/errors/settings/_value_badge.html.erb +286 -0
  19. data/app/views/rails_error_dashboard/errors/settings.html.erb +146 -480
  20. data/app/views/rails_error_dashboard/errors/show.html.erb +102 -76
  21. data/db/migrate/20251223000000_create_rails_error_dashboard_complete_schema.rb +188 -0
  22. data/db/migrate/20251224000001_create_rails_error_dashboard_error_logs.rb +5 -0
  23. data/db/migrate/20251224081522_add_better_tracking_to_error_logs.rb +3 -0
  24. data/db/migrate/20251224101217_add_controller_action_to_error_logs.rb +3 -0
  25. data/db/migrate/20251225071314_add_optimized_indexes_to_error_logs.rb +4 -0
  26. data/db/migrate/20251225074653_remove_environment_from_error_logs.rb +3 -0
  27. data/db/migrate/20251225085859_add_enhanced_metrics_to_error_logs.rb +3 -0
  28. data/db/migrate/20251225093603_add_similarity_tracking_to_error_logs.rb +3 -0
  29. data/db/migrate/20251225100236_create_error_occurrences.rb +3 -0
  30. data/db/migrate/20251225101920_create_cascade_patterns.rb +3 -0
  31. data/db/migrate/20251225102500_create_error_baselines.rb +3 -0
  32. data/db/migrate/20251226020000_add_workflow_fields_to_error_logs.rb +3 -0
  33. data/db/migrate/20251226020100_create_error_comments.rb +3 -0
  34. data/db/migrate/20251229111223_add_additional_performance_indexes.rb +4 -0
  35. data/db/migrate/20260106094220_create_rails_error_dashboard_applications.rb +3 -0
  36. data/db/migrate/20260106094233_add_application_to_error_logs.rb +3 -0
  37. data/db/migrate/20260106094318_finalize_application_foreign_key.rb +5 -0
  38. data/lib/generators/rails_error_dashboard/install/install_generator.rb +32 -0
  39. data/lib/generators/rails_error_dashboard/install/templates/initializer.rb +37 -4
  40. data/lib/rails_error_dashboard/configuration.rb +160 -3
  41. data/lib/rails_error_dashboard/configuration_error.rb +24 -0
  42. data/lib/rails_error_dashboard/engine.rb +17 -0
  43. data/lib/rails_error_dashboard/helpers/user_model_detector.rb +138 -0
  44. data/lib/rails_error_dashboard/queries/analytics_stats.rb +1 -2
  45. data/lib/rails_error_dashboard/queries/dashboard_stats.rb +19 -4
  46. data/lib/rails_error_dashboard/queries/errors_list.rb +27 -8
  47. data/lib/rails_error_dashboard/services/error_normalizer.rb +143 -0
  48. data/lib/rails_error_dashboard/services/git_blame_reader.rb +195 -0
  49. data/lib/rails_error_dashboard/services/github_link_generator.rb +159 -0
  50. data/lib/rails_error_dashboard/services/source_code_reader.rb +214 -0
  51. data/lib/rails_error_dashboard/version.rb +1 -1
  52. data/lib/rails_error_dashboard.rb +6 -0
  53. metadata +14 -10
  54. data/app/assets/stylesheets/rails_error_dashboard/_catppuccin_mocha.scss +0 -107
  55. data/app/assets/stylesheets/rails_error_dashboard/_components.scss +0 -625
  56. data/app/assets/stylesheets/rails_error_dashboard/_layout.scss +0 -257
  57. data/app/assets/stylesheets/rails_error_dashboard/_theme_variables.scss +0 -203
  58. data/app/assets/stylesheets/rails_error_dashboard/application.css +0 -15
  59. data/app/assets/stylesheets/rails_error_dashboard/application.css.map +0 -7
  60. data/app/assets/stylesheets/rails_error_dashboard/application.scss +0 -61
  61. data/app/views/layouts/rails_error_dashboard/application.html.erb +0 -55
@@ -1,625 +0,0 @@
1
- // =============================================================================
2
- // Component Styles - Catppuccin Mocha Theme
3
- // =============================================================================
4
- // Component-specific styling using Catppuccin color palette
5
- // Ensures proper contrast and visibility in dark theme
6
- // =============================================================================
7
-
8
- @import 'catppuccin_mocha';
9
- @import 'theme_variables';
10
-
11
- // =============================================================================
12
- // BADGE COMPONENTS
13
- // =============================================================================
14
- // Platform and status badges with proper contrast
15
-
16
- .badge {
17
- // iOS Badge - Light text on dark background (dark theme)
18
- &.badge-ios {
19
- [data-theme="dark"] & {
20
- background-color: var(--ctp-overlay0);
21
- color: var(--ctp-text);
22
- border: 1px solid var(--ctp-surface2);
23
- }
24
- }
25
-
26
- // Android Badge - Green theme
27
- &.badge-android {
28
- [data-theme="dark"] & {
29
- background-color: #{ctp-opacity($ctp-green, 0.2)};
30
- color: var(--ctp-green);
31
- border: 1px solid var(--ctp-green);
32
- }
33
- }
34
-
35
- // Web Badge - Blue theme
36
- &.badge-web {
37
- [data-theme="dark"] & {
38
- background-color: #{ctp-opacity($ctp-blue, 0.2)};
39
- color: var(--ctp-blue);
40
- border: 1px solid var(--ctp-blue);
41
- }
42
- }
43
-
44
- // API Badge - Sapphire theme
45
- &.badge-api {
46
- [data-theme="dark"] & {
47
- background-color: #{ctp-opacity($ctp-sapphire, 0.2)};
48
- color: var(--ctp-sapphire);
49
- border: 1px solid var(--ctp-sapphire);
50
- }
51
- }
52
-
53
- // Severity Badges
54
- &.bg-danger {
55
- [data-theme="dark"] & {
56
- background-color: var(--ctp-red) !important;
57
- color: var(--ctp-base) !important;
58
- }
59
- }
60
-
61
- &.bg-warning {
62
- [data-theme="dark"] & {
63
- background-color: var(--ctp-peach) !important;
64
- color: var(--ctp-base) !important;
65
- }
66
- }
67
-
68
- &.bg-success {
69
- [data-theme="dark"] & {
70
- background-color: var(--ctp-green) !important;
71
- color: var(--ctp-base) !important;
72
- }
73
- }
74
-
75
- &.bg-info {
76
- [data-theme="dark"] & {
77
- background-color: var(--ctp-blue) !important;
78
- color: var(--ctp-base) !important;
79
- }
80
- }
81
-
82
- &.bg-secondary {
83
- [data-theme="dark"] & {
84
- background-color: var(--ctp-overlay1) !important;
85
- color: var(--ctp-text) !important;
86
- }
87
- }
88
- }
89
-
90
- // =============================================================================
91
- // CARD COMPONENTS
92
- // =============================================================================
93
-
94
- .card {
95
- [data-theme="dark"] & {
96
- background-color: var(--card-bg);
97
- border-color: var(--border-color);
98
- color: var(--text-color);
99
-
100
- .card-header {
101
- background-color: var(--card-bg);
102
- border-bottom-color: var(--border-color);
103
- color: var(--text-color);
104
-
105
- // Override all bg-white instances
106
- &.bg-white {
107
- background-color: var(--card-bg) !important;
108
- color: var(--text-color) !important;
109
- }
110
-
111
- &.bg-danger {
112
- background-color: var(--ctp-red) !important;
113
- color: var(--ctp-base) !important;
114
- }
115
-
116
- &.bg-warning {
117
- background-color: var(--ctp-peach) !important;
118
- color: var(--ctp-base) !important;
119
- }
120
-
121
- &.bg-success {
122
- background-color: var(--ctp-green) !important;
123
- color: var(--ctp-base) !important;
124
- }
125
-
126
- &.bg-info {
127
- background-color: var(--ctp-blue) !important;
128
- color: var(--ctp-base) !important;
129
- }
130
- }
131
-
132
- .card-body {
133
- color: var(--text-color);
134
- }
135
-
136
- .card-footer {
137
- background-color: var(--card-bg);
138
- border-top-color: var(--border-color);
139
- color: var(--text-secondary);
140
- }
141
- }
142
- }
143
-
144
- // =============================================================================
145
- // CODE BLOCKS & SYNTAX HIGHLIGHTING
146
- // =============================================================================
147
-
148
- code, pre {
149
- [data-theme="dark"] & {
150
- background-color: var(--code-bg) !important;
151
- color: var(--text-color) !important;
152
- border-color: var(--border-color);
153
- }
154
- }
155
-
156
- .code-block {
157
- [data-theme="dark"] & {
158
- background-color: var(--code-bg);
159
- color: var(--text-color);
160
- border: 1px solid var(--border-color);
161
- }
162
- }
163
-
164
- // Override Bootstrap's bg-dark for code blocks
165
- .bg-dark.code-block {
166
- [data-theme="dark"] & {
167
- background-color: var(--code-bg) !important;
168
- color: var(--text-color) !important;
169
- }
170
- }
171
-
172
- code.bg-dark,
173
- pre.bg-dark {
174
- [data-theme="dark"] & {
175
- background-color: var(--code-bg) !important;
176
- color: var(--text-color) !important;
177
- }
178
- }
179
-
180
- // =============================================================================
181
- // BACKTRACE FRAMES
182
- // =============================================================================
183
- // Syntax highlighting for stack traces
184
-
185
- .backtrace-frame {
186
- [data-theme="dark"] & {
187
- padding: $spacing-sm $spacing-md;
188
- margin-bottom: 2px;
189
- border-radius: $radius-sm;
190
- font-family: 'Courier New', monospace;
191
- font-size: 0.875rem;
192
-
193
- // App code - Most important, use green
194
- &.frame-app {
195
- background-color: #{ctp-opacity($ctp-green, 0.1)} !important;
196
- color: var(--ctp-green) !important;
197
- border-left: 3px solid var(--ctp-green);
198
- font-weight: 600;
199
- }
200
-
201
- // Gem code - Library code, use blue
202
- &.frame-gem {
203
- background-color: #{ctp-opacity($ctp-blue, 0.1)} !important;
204
- color: var(--ctp-blue) !important;
205
- border-left: 3px solid var(--ctp-blue);
206
- }
207
-
208
- // Framework code - Rails/framework, use yellow
209
- &.frame-framework {
210
- background-color: #{ctp-opacity($ctp-yellow, 0.1)} !important;
211
- color: var(--ctp-yellow) !important;
212
- border-left: 3px solid var(--ctp-yellow);
213
- }
214
-
215
- // Ruby core - System code, muted
216
- &.frame-ruby-core {
217
- background-color: #{ctp-opacity($ctp-overlay0, 0.1)} !important;
218
- color: var(--ctp-subtext0) !important;
219
- border-left: 3px solid var(--ctp-overlay0);
220
- }
221
- }
222
- }
223
-
224
- // =============================================================================
225
- // HEATMAP VISUALIZATION
226
- // =============================================================================
227
-
228
- .heatmap-cell {
229
- [data-theme="dark"] & {
230
- background-color: var(--ctp-red);
231
- color: var(--text-color);
232
- border: 1px solid var(--border-subtle);
233
- transition: all $transition-fast;
234
-
235
- &:hover {
236
- border-color: var(--border-color);
237
- transform: scale(1.05);
238
- }
239
-
240
- // Intensity-based opacity set via inline style
241
- // Example: style="--heatmap-intensity: 0.5; opacity: 0.5"
242
- }
243
- }
244
-
245
- // =============================================================================
246
- // TABLE COMPONENTS
247
- // =============================================================================
248
-
249
- .table {
250
- [data-theme="dark"] & {
251
- color: var(--text-color);
252
- border-color: var(--border-color);
253
-
254
- thead {
255
- th {
256
- background-color: var(--card-bg);
257
- border-bottom-color: var(--border-color);
258
- color: var(--text-color);
259
- }
260
- }
261
-
262
- tbody {
263
- tr {
264
- background-color: transparent;
265
- border-bottom-color: var(--border-subtle);
266
-
267
- &:hover {
268
- background-color: var(--table-hover);
269
- }
270
-
271
- td {
272
- border-color: var(--border-subtle);
273
- color: var(--text-color);
274
- }
275
- }
276
- }
277
-
278
- // Striped tables
279
- &.table-striped {
280
- tbody tr:nth-of-type(odd) {
281
- background-color: #{ctp-opacity($ctp-surface0, 0.5)};
282
- }
283
- }
284
-
285
- // Bordered tables
286
- &.table-bordered {
287
- border-color: var(--border-color);
288
-
289
- th, td {
290
- border-color: var(--border-color);
291
- }
292
- }
293
- }
294
- }
295
-
296
- // =============================================================================
297
- // FORM CONTROLS
298
- // =============================================================================
299
-
300
- .form-control,
301
- .form-select {
302
- [data-theme="dark"] & {
303
- background-color: var(--card-bg);
304
- color: var(--text-color);
305
- border-color: var(--border-color);
306
-
307
- &:focus {
308
- background-color: var(--card-bg);
309
- border-color: var(--primary-color);
310
- color: var(--text-color);
311
- box-shadow: 0 0 0 0.2rem #{ctp-opacity($ctp-mauve, 0.25)};
312
- }
313
-
314
- &::placeholder {
315
- color: var(--text-muted);
316
- }
317
-
318
- &:disabled {
319
- background-color: var(--ctp-surface1);
320
- color: var(--text-muted);
321
- }
322
- }
323
- }
324
-
325
- .form-check-input {
326
- [data-theme="dark"] & {
327
- background-color: var(--card-bg);
328
- border-color: var(--border-color);
329
-
330
- &:checked {
331
- background-color: var(--primary-color);
332
- border-color: var(--primary-color);
333
- }
334
-
335
- &:focus {
336
- border-color: var(--primary-color);
337
- box-shadow: 0 0 0 0.2rem #{ctp-opacity($ctp-mauve, 0.25)};
338
- }
339
- }
340
- }
341
-
342
- // =============================================================================
343
- // BUTTON COMPONENTS
344
- // =============================================================================
345
-
346
- .btn {
347
- [data-theme="dark"] & {
348
- // Primary button
349
- &.btn-primary {
350
- background-color: var(--ctp-mauve);
351
- border-color: var(--ctp-mauve);
352
- color: var(--ctp-base);
353
-
354
- &:hover {
355
- background-color: #{ctp-lighten($ctp-mauve, 5%)};
356
- border-color: #{ctp-lighten($ctp-mauve, 5%)};
357
- }
358
-
359
- &:active {
360
- background-color: #{ctp-darken($ctp-mauve, 5%)};
361
- border-color: #{ctp-darken($ctp-mauve, 5%)};
362
- }
363
- }
364
-
365
- // Danger button
366
- &.btn-danger {
367
- background-color: var(--ctp-red);
368
- border-color: var(--ctp-red);
369
- color: var(--ctp-base);
370
-
371
- &:hover {
372
- background-color: #{ctp-lighten($ctp-red, 5%)};
373
- border-color: #{ctp-lighten($ctp-red, 5%)};
374
- }
375
- }
376
-
377
- // Success button
378
- &.btn-success {
379
- background-color: var(--ctp-green);
380
- border-color: var(--ctp-green);
381
- color: var(--ctp-base);
382
-
383
- &:hover {
384
- background-color: #{ctp-lighten($ctp-green, 5%)};
385
- border-color: #{ctp-lighten($ctp-green, 5%)};
386
- }
387
- }
388
-
389
- // Warning button
390
- &.btn-warning {
391
- background-color: var(--ctp-peach);
392
- border-color: var(--ctp-peach);
393
- color: var(--ctp-base);
394
-
395
- &:hover {
396
- background-color: #{ctp-lighten($ctp-peach, 5%)};
397
- border-color: #{ctp-lighten($ctp-peach, 5%)};
398
- }
399
- }
400
-
401
- // Info button
402
- &.btn-info {
403
- background-color: var(--ctp-blue);
404
- border-color: var(--ctp-blue);
405
- color: var(--ctp-base);
406
-
407
- &:hover {
408
- background-color: #{ctp-lighten($ctp-blue, 5%)};
409
- border-color: #{ctp-lighten($ctp-blue, 5%)};
410
- }
411
- }
412
-
413
- // Secondary button
414
- &.btn-secondary {
415
- background-color: var(--ctp-overlay1);
416
- border-color: var(--ctp-overlay1);
417
- color: var(--ctp-text);
418
-
419
- &:hover {
420
- background-color: var(--ctp-overlay2);
421
- border-color: var(--ctp-overlay2);
422
- }
423
- }
424
-
425
- // Outline variants
426
- &.btn-outline-primary {
427
- color: var(--ctp-mauve);
428
- border-color: var(--ctp-mauve);
429
-
430
- &:hover {
431
- background-color: var(--ctp-mauve);
432
- color: var(--ctp-base);
433
- }
434
- }
435
- }
436
- }
437
-
438
- // =============================================================================
439
- // MODAL COMPONENTS
440
- // =============================================================================
441
-
442
- .modal {
443
- [data-theme="dark"] & {
444
- .modal-content {
445
- background-color: var(--card-bg);
446
- color: var(--text-color);
447
- border-color: var(--border-color);
448
-
449
- .modal-header {
450
- background-color: var(--card-bg);
451
- border-bottom-color: var(--border-color);
452
- color: var(--text-color);
453
-
454
- .btn-close {
455
- filter: invert(1) grayscale(100%) brightness(200%);
456
- }
457
- }
458
-
459
- .modal-body {
460
- color: var(--text-color);
461
- }
462
-
463
- .modal-footer {
464
- background-color: var(--card-bg);
465
- border-top-color: var(--border-color);
466
- }
467
- }
468
- }
469
- }
470
-
471
- // =============================================================================
472
- // DROPDOWN COMPONENTS
473
- // =============================================================================
474
-
475
- .dropdown-menu {
476
- [data-theme="dark"] & {
477
- background-color: var(--card-bg);
478
- border-color: var(--border-color);
479
-
480
- .dropdown-item {
481
- color: var(--text-color);
482
-
483
- &:hover,
484
- &:focus {
485
- background-color: var(--table-hover);
486
- color: var(--text-color);
487
- }
488
-
489
- &.active {
490
- background-color: var(--primary-color);
491
- color: var(--ctp-base);
492
- }
493
- }
494
-
495
- .dropdown-divider {
496
- border-top-color: var(--border-color);
497
- }
498
- }
499
- }
500
-
501
- // =============================================================================
502
- // PROGRESS BARS
503
- // =============================================================================
504
-
505
- .progress {
506
- [data-theme="dark"] & {
507
- background-color: var(--ctp-surface1);
508
-
509
- .progress-bar {
510
- &.bg-success {
511
- background-color: var(--ctp-green) !important;
512
- }
513
-
514
- &.bg-danger {
515
- background-color: var(--ctp-red) !important;
516
- }
517
-
518
- &.bg-warning {
519
- background-color: var(--ctp-peach) !important;
520
- }
521
-
522
- &.bg-info {
523
- background-color: var(--ctp-blue) !important;
524
- }
525
- }
526
- }
527
- }
528
-
529
- // =============================================================================
530
- // ALERTS
531
- // =============================================================================
532
-
533
- .alert {
534
- [data-theme="dark"] & {
535
- &.alert-danger {
536
- background-color: #{ctp-opacity($ctp-red, 0.2)};
537
- border-color: var(--ctp-red);
538
- color: var(--ctp-red);
539
- }
540
-
541
- &.alert-warning {
542
- background-color: #{ctp-opacity($ctp-peach, 0.2)};
543
- border-color: var(--ctp-peach);
544
- color: var(--ctp-peach);
545
- }
546
-
547
- &.alert-success {
548
- background-color: #{ctp-opacity($ctp-green, 0.2)};
549
- border-color: var(--ctp-green);
550
- color: var(--ctp-green);
551
- }
552
-
553
- &.alert-info {
554
- background-color: #{ctp-opacity($ctp-blue, 0.2)};
555
- border-color: var(--ctp-blue);
556
- color: var(--ctp-blue);
557
- }
558
- }
559
- }
560
-
561
- // =============================================================================
562
- // LIST GROUP
563
- // =============================================================================
564
-
565
- .list-group {
566
- [data-theme="dark"] & {
567
- .list-group-item {
568
- background-color: var(--card-bg);
569
- border-color: var(--border-color);
570
- color: var(--text-color);
571
-
572
- &:hover {
573
- background-color: var(--table-hover);
574
- }
575
-
576
- &.active {
577
- background-color: var(--primary-color);
578
- border-color: var(--primary-color);
579
- color: var(--ctp-base);
580
- }
581
- }
582
- }
583
- }
584
-
585
- // =============================================================================
586
- // TEXT COLOR UTILITIES
587
- // =============================================================================
588
-
589
- [data-theme="dark"] {
590
- .text-muted {
591
- color: var(--text-muted) !important;
592
- }
593
-
594
- .text-primary {
595
- color: var(--primary-color) !important;
596
- }
597
-
598
- .text-success {
599
- color: var(--success-color) !important;
600
- }
601
-
602
- .text-danger {
603
- color: var(--danger-color) !important;
604
- }
605
-
606
- .text-warning {
607
- color: var(--warning-color) !important;
608
- }
609
-
610
- .text-info {
611
- color: var(--info-color) !important;
612
- }
613
-
614
- .text-secondary {
615
- color: var(--secondary-color) !important;
616
- }
617
-
618
- .text-light {
619
- color: var(--text-color) !important;
620
- }
621
-
622
- .text-dark {
623
- color: var(--text-muted) !important;
624
- }
625
- }