flare 0.1.1 → 1.0.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.

Potentially problematic release.


This version of flare might be problematic. Click here for more details.

Files changed (56) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +18 -0
  5. data/Rakefile +55 -0
  6. data/VERSION +1 -0
  7. data/flare.gemspec +66 -0
  8. data/lib/flare/active_record.rb +102 -0
  9. data/lib/flare/collection.rb +47 -0
  10. data/lib/flare/configuration.rb +64 -109
  11. data/lib/flare/index_builder.rb +24 -0
  12. data/lib/flare/session.rb +142 -0
  13. data/lib/flare/tasks.rb +18 -0
  14. data/lib/flare.rb +19 -408
  15. data/test/helper.rb +10 -0
  16. data/test/test_flare.rb +7 -0
  17. metadata +89 -228
  18. checksums.yaml +0 -7
  19. data/CHANGELOG.md +0 -5
  20. data/LICENSE.txt +0 -21
  21. data/README.md +0 -148
  22. data/app/controllers/flare/application_controller.rb +0 -22
  23. data/app/controllers/flare/jobs_controller.rb +0 -55
  24. data/app/controllers/flare/requests_controller.rb +0 -73
  25. data/app/controllers/flare/spans_controller.rb +0 -101
  26. data/app/helpers/flare/application_helper.rb +0 -168
  27. data/app/views/flare/jobs/index.html.erb +0 -69
  28. data/app/views/flare/jobs/show.html.erb +0 -323
  29. data/app/views/flare/requests/index.html.erb +0 -120
  30. data/app/views/flare/requests/show.html.erb +0 -498
  31. data/app/views/flare/spans/index.html.erb +0 -112
  32. data/app/views/flare/spans/show.html.erb +0 -184
  33. data/app/views/layouts/flare/application.html.erb +0 -126
  34. data/config/routes.rb +0 -20
  35. data/exe/flare +0 -9
  36. data/lib/flare/backoff_policy.rb +0 -73
  37. data/lib/flare/cli/doctor_command.rb +0 -129
  38. data/lib/flare/cli/output.rb +0 -45
  39. data/lib/flare/cli/setup_command.rb +0 -404
  40. data/lib/flare/cli/status_command.rb +0 -47
  41. data/lib/flare/cli.rb +0 -50
  42. data/lib/flare/engine.rb +0 -43
  43. data/lib/flare/http_metrics_config.rb +0 -101
  44. data/lib/flare/metric_counter.rb +0 -45
  45. data/lib/flare/metric_flusher.rb +0 -124
  46. data/lib/flare/metric_key.rb +0 -42
  47. data/lib/flare/metric_span_processor.rb +0 -470
  48. data/lib/flare/metric_storage.rb +0 -42
  49. data/lib/flare/metric_submitter.rb +0 -221
  50. data/lib/flare/source_location.rb +0 -113
  51. data/lib/flare/sqlite_exporter.rb +0 -279
  52. data/lib/flare/storage/sqlite.rb +0 -789
  53. data/lib/flare/storage.rb +0 -54
  54. data/lib/flare/version.rb +0 -5
  55. data/public/flare-assets/flare.css +0 -1245
  56. data/public/flare-assets/images/flipper.png +0 -0
@@ -1,1245 +0,0 @@
1
- /* ==========================================================================
2
- Flare Design System
3
- Clean monochrome analytics dashboard for the Flare Rails engine.
4
- System fonts, Bootstrap Icons, border-based design.
5
- ========================================================================== */
6
-
7
- /* --- CSS Variables --- */
8
- :root {
9
- --cb-bg: #ffffff;
10
- --cb-bg-subtle: #fafafa;
11
- --cb-bg-muted: #f0f0f0;
12
- --cb-border: #e5e5e5;
13
- --cb-border-hover: #ccc;
14
- --cb-text-faint: #bbb;
15
- --cb-text-muted: #999;
16
- --cb-text-secondary: #666;
17
- --cb-text: #1a1a1a;
18
- --cb-text-strong: #000;
19
- --cb-success: #2b7a3e;
20
- --cb-info: #6B8A9A;
21
- --cb-warning: #C4A35A;
22
- --cb-danger: #c53030;
23
- --cb-radius: 0.5rem;
24
- --cb-radius-sm: 0.375rem;
25
- --cb-radius-lg: 0.5rem;
26
- --cb-shadow: none;
27
- --cb-shadow-sm: none;
28
- --cb-shadow-lg: 0 4px 24px rgba(0, 0, 0, 0.08);
29
- --cb-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
30
- --cb-font-mono: ui-monospace, 'SF Mono', Monaco, monospace;
31
- --cb-sidebar-width: 220px;
32
- --cb-sidebar-collapsed: 64px;
33
- }
34
-
35
- /* --- Reset & Base --- */
36
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
37
-
38
- body {
39
- font-family: var(--cb-font);
40
- font-size: 0.875rem;
41
- color: var(--cb-text);
42
- background: var(--cb-bg);
43
- line-height: 1.5;
44
- min-height: 100vh;
45
- -webkit-font-smoothing: antialiased;
46
- -moz-osx-font-smoothing: grayscale;
47
- }
48
-
49
- a {
50
- color: var(--cb-text-secondary);
51
- text-decoration: none;
52
- transition: color 0.15s ease;
53
- }
54
- a:hover { color: var(--cb-text); }
55
-
56
- code, pre {
57
- font-family: var(--cb-font-mono);
58
- }
59
-
60
- /* --- App Layout --- */
61
- .app-layout {
62
- display: flex;
63
- min-height: 100vh;
64
- }
65
-
66
- /* --- Sidebar --- */
67
- .sidebar {
68
- width: var(--cb-sidebar-width);
69
- background: var(--cb-bg);
70
- border-right: 1px solid var(--cb-border);
71
- display: flex;
72
- flex-direction: column;
73
- position: fixed;
74
- top: 0;
75
- left: 0;
76
- bottom: 0;
77
- z-index: 100;
78
- }
79
-
80
- .sidebar-header {
81
- padding: 1.25rem 1rem;
82
- border-bottom: 1px solid var(--cb-border);
83
- min-height: 60px;
84
- display: flex;
85
- align-items: center;
86
- }
87
-
88
- .logo {
89
- display: flex;
90
- align-items: center;
91
- gap: 0.625rem;
92
- text-decoration: none;
93
- color: var(--cb-text);
94
- }
95
-
96
- .logo-icon {
97
- width: 28px;
98
- height: 28px;
99
- background: var(--cb-text);
100
- border-radius: var(--cb-radius-sm);
101
- display: flex;
102
- align-items: center;
103
- justify-content: center;
104
- flex-shrink: 0;
105
- }
106
-
107
- .logo-icon svg {
108
- width: 16px;
109
- height: 16px;
110
- color: white;
111
- }
112
-
113
- .logo-icon i {
114
- font-size: 14px;
115
- color: white;
116
- }
117
-
118
- .logo-text {
119
- font-size: 1rem;
120
- font-weight: 700;
121
- letter-spacing: -0.02em;
122
- color: var(--cb-text);
123
- }
124
-
125
- /* Sidebar Nav */
126
- .sidebar-nav {
127
- flex: 1;
128
- padding: 0.75rem 0.625rem;
129
- overflow-y: auto;
130
- }
131
-
132
- .nav-section {
133
- margin-bottom: 1.25rem;
134
- }
135
-
136
- .nav-section-title {
137
- font-size: 0.6875rem;
138
- font-weight: 600;
139
- text-transform: uppercase;
140
- letter-spacing: 0.06em;
141
- color: var(--cb-text-muted);
142
- padding: 0 0.625rem;
143
- margin-bottom: 0.375rem;
144
- }
145
-
146
- .nav-item {
147
- display: flex;
148
- align-items: center;
149
- gap: 0.625rem;
150
- padding: 0.5rem 0.625rem;
151
- border-radius: var(--cb-radius-sm);
152
- color: var(--cb-text-secondary);
153
- text-decoration: none;
154
- font-size: 0.8125rem;
155
- font-weight: 500;
156
- transition: all 0.15s ease;
157
- }
158
-
159
- .nav-item:hover {
160
- background: var(--cb-bg-subtle);
161
- color: var(--cb-text);
162
- text-decoration: none;
163
- }
164
-
165
- .nav-item.active {
166
- background: var(--cb-bg-subtle);
167
- color: var(--cb-text);
168
- font-weight: 600;
169
- }
170
-
171
- .nav-item i {
172
- font-size: 1rem;
173
- width: 1.25rem;
174
- text-align: center;
175
- opacity: 0.6;
176
- flex-shrink: 0;
177
- }
178
-
179
- .nav-item svg {
180
- width: 1rem;
181
- height: 1rem;
182
- opacity: 0.6;
183
- flex-shrink: 0;
184
- }
185
-
186
- .nav-item:hover i,
187
- .nav-item:hover svg,
188
- .nav-item.active i,
189
- .nav-item.active svg {
190
- opacity: 1;
191
- }
192
-
193
- .nav-item-count {
194
- margin-left: auto;
195
- font-size: 0.6875rem;
196
- font-weight: 500;
197
- color: var(--cb-text-muted);
198
- background: var(--cb-bg-muted);
199
- padding: 0.125rem 0.5rem;
200
- border-radius: 10px;
201
- }
202
-
203
- .nav-item.active .nav-item-count {
204
- background: var(--cb-text);
205
- color: white;
206
- }
207
-
208
- /* Sidebar Footer */
209
- .sidebar-footer {
210
- padding: 0.75rem 0.625rem;
211
- border-top: 1px solid var(--cb-border);
212
- margin-top: auto;
213
- }
214
-
215
- .sidebar-ad {
216
- display: block;
217
- padding: 0.625rem;
218
- margin-bottom: 0.5rem;
219
- border-radius: var(--cb-radius-sm);
220
- background: var(--cb-bg-subtle);
221
- text-decoration: none;
222
- transition: all 0.15s ease;
223
- }
224
-
225
- .sidebar-ad:hover {
226
- background: var(--cb-bg-muted);
227
- }
228
-
229
- .sidebar-ad-inner {
230
- display: flex;
231
- align-items: center;
232
- gap: 0.5rem;
233
- }
234
-
235
- .sidebar-ad-logo {
236
- width: 36px;
237
- height: 36px;
238
- flex-shrink: 0;
239
- }
240
-
241
- .sidebar-ad-logo img {
242
- width: 100%;
243
- height: 100%;
244
- object-fit: contain;
245
- }
246
-
247
- .sidebar-ad-text {
248
- font-size: 0.6875rem;
249
- line-height: 1.4;
250
- color: var(--cb-text-secondary);
251
- }
252
-
253
- .sidebar-ad-title {
254
- font-weight: 600;
255
- color: var(--cb-text);
256
- }
257
-
258
- /* Clear button */
259
- .btn-clear {
260
- display: flex;
261
- align-items: center;
262
- gap: 0.625rem;
263
- width: 100%;
264
- padding: 0.5rem 0.625rem;
265
- border-radius: var(--cb-radius-sm);
266
- background: transparent;
267
- border: none;
268
- color: var(--cb-text-muted);
269
- font-size: 0.8125rem;
270
- font-weight: 500;
271
- font-family: inherit;
272
- cursor: pointer;
273
- transition: all 0.15s ease;
274
- }
275
-
276
- .btn-clear:hover {
277
- background: rgba(197,48,48,0.08);
278
- color: var(--cb-danger);
279
- }
280
-
281
- .btn-clear svg,
282
- .btn-clear i {
283
- width: 1rem;
284
- height: 1rem;
285
- font-size: 1rem;
286
- opacity: 0.6;
287
- flex-shrink: 0;
288
- }
289
-
290
- .btn-clear:hover svg,
291
- .btn-clear:hover i {
292
- opacity: 1;
293
- }
294
-
295
- /* --- Main Content --- */
296
- .main-content {
297
- flex: 1;
298
- margin-left: var(--cb-sidebar-width);
299
- min-height: 100vh;
300
- }
301
-
302
- /* Page Header */
303
- .page-header {
304
- background: var(--cb-bg);
305
- border-bottom: 1px solid var(--cb-border);
306
- padding: 1rem 1.5rem;
307
- min-height: 60px;
308
- display: flex;
309
- align-items: center;
310
- justify-content: space-between;
311
- gap: 1rem;
312
- }
313
-
314
- .page-title {
315
- font-size: 1rem;
316
- font-weight: 600;
317
- color: var(--cb-text);
318
- margin: 0;
319
- }
320
-
321
- /* Page Body */
322
- .page-body {
323
- padding: 1.25rem 1.5rem;
324
- }
325
-
326
- /* --- Cards --- */
327
- .card {
328
- background: var(--cb-bg);
329
- border-radius: var(--cb-radius-lg);
330
- border: 1px solid var(--cb-border);
331
- overflow: hidden;
332
- box-shadow: none;
333
- }
334
-
335
- .card-header {
336
- padding: 0.75rem 1rem;
337
- border-bottom: 1px solid var(--cb-border);
338
- display: flex;
339
- align-items: center;
340
- justify-content: space-between;
341
- background: transparent;
342
- }
343
-
344
- .card-title {
345
- font-size: 0.8125rem;
346
- font-weight: 600;
347
- color: var(--cb-text);
348
- }
349
-
350
- .card-body {
351
- padding: 0;
352
- }
353
-
354
- /* --- Data Table --- */
355
- .data-table {
356
- width: 100%;
357
- border-collapse: collapse;
358
- }
359
-
360
- .data-table th {
361
- text-align: left;
362
- padding: 0.5rem 0.75rem;
363
- font-size: 0.6875rem;
364
- font-weight: 600;
365
- text-transform: uppercase;
366
- letter-spacing: 0.04em;
367
- color: var(--cb-text-muted);
368
- background: transparent;
369
- border-bottom: 1px solid var(--cb-border);
370
- }
371
-
372
- .data-table td {
373
- padding: 0.5rem 0.75rem;
374
- border-bottom: 1px solid var(--cb-bg-muted);
375
- vertical-align: middle;
376
- font-size: 0.8125rem;
377
- }
378
-
379
- .data-table tbody tr {
380
- transition: background 0.1s ease;
381
- }
382
-
383
- .data-table tbody tr:hover {
384
- background: var(--cb-bg-subtle);
385
- }
386
-
387
- .data-table tbody tr:last-child td {
388
- border-bottom: none;
389
- }
390
-
391
- /* --- Badges --- */
392
- .badge {
393
- display: inline-flex;
394
- align-items: center;
395
- padding: 0.2em 0.5em;
396
- border-radius: 0.25rem;
397
- font-size: 0.6875rem;
398
- font-weight: 600;
399
- font-family: var(--cb-font-mono);
400
- letter-spacing: 0.02em;
401
- }
402
-
403
- .badge-verb {
404
- background: var(--cb-bg-muted);
405
- color: var(--cb-text-secondary);
406
- }
407
-
408
- .badge-get { background: rgba(107,138,154,0.15); color: #4a7a8a; }
409
- .badge-post { background: rgba(43,122,62,0.15); color: #1d6b2f; }
410
- .badge-put, .badge-patch { background: rgba(196,163,90,0.15); color: #9a7d2e; }
411
- .badge-delete { background: rgba(197,48,48,0.15); color: #a53030; }
412
-
413
- .badge-status {
414
- min-width: 36px;
415
- justify-content: center;
416
- }
417
-
418
- .badge-success { background: rgba(43,122,62,0.15); color: #1d6b2f; }
419
- .badge-error { background: rgba(197,48,48,0.15); color: #a53030; }
420
- .badge-warning { background: rgba(196,163,90,0.15); color: #9a7d2e; }
421
-
422
- .badge-type {
423
- font-family: var(--cb-font);
424
- font-weight: 500;
425
- }
426
-
427
- .badge-request { background: rgba(107,138,154,0.15); color: #4a7a8a; }
428
- .badge-job { background: rgba(138,154,107,0.15); color: #5a7a3d; }
429
-
430
- .badge-clue { font-family: var(--cb-font-mono); font-size: 0.6875rem; }
431
- .badge-sql { background: rgba(107,138,154,0.15); color: #4a7a8a; }
432
- .badge-cache { background: rgba(43,122,62,0.15); color: #1d6b2f; }
433
- .badge-view { background: rgba(196,163,90,0.15); color: #9a7d2e; }
434
- .badge-mail { background: rgba(154,107,138,0.15); color: #8a4a7a; }
435
- .badge-http { background: rgba(138,107,154,0.15); color: #7a4a8a; }
436
- .badge-exception { background: rgba(197,48,48,0.15); color: #a53030; }
437
- .badge-other { background: var(--cb-bg-muted); color: var(--cb-text-secondary); }
438
- .badge-redis { background: rgba(197,48,48,0.12); color: #a53030; }
439
- .badge-query { background: rgba(107,138,154,0.15); color: #4a7a8a; }
440
-
441
- /* --- Search / Filters --- */
442
- .filters {
443
- display: flex;
444
- gap: 0.5rem;
445
- align-items: center;
446
- flex-wrap: wrap;
447
- }
448
-
449
- .filter-select {
450
- padding: 0.375rem 0.625rem;
451
- border: 1px solid var(--cb-border);
452
- border-radius: var(--cb-radius);
453
- background: var(--cb-bg);
454
- font-size: 0.8125rem;
455
- font-family: var(--cb-font);
456
- color: var(--cb-text);
457
- cursor: pointer;
458
- min-width: 100px;
459
- transition: border-color 0.15s ease;
460
- }
461
-
462
- .filter-select:focus {
463
- outline: none;
464
- border-color: var(--cb-text);
465
- box-shadow: 0 0 0 3px rgba(26,26,26,0.1);
466
- }
467
-
468
- .filter-select::placeholder {
469
- color: var(--cb-text-muted);
470
- }
471
-
472
- /* --- Path / Name Cells --- */
473
- .path-cell {
474
- max-width: 400px;
475
- }
476
-
477
- .path-text {
478
- display: block;
479
- overflow: hidden;
480
- text-overflow: ellipsis;
481
- white-space: nowrap;
482
- }
483
-
484
- .path-subtext {
485
- display: block;
486
- overflow: hidden;
487
- text-overflow: ellipsis;
488
- white-space: nowrap;
489
- color: var(--cb-text-muted);
490
- font-size: 0.75rem;
491
- margin-top: 1px;
492
- }
493
-
494
- .action-name,
495
- .job-name,
496
- .span-name {
497
- font-weight: 600;
498
- color: var(--cb-text);
499
- }
500
-
501
- /* --- Duration / Timestamp --- */
502
- .duration {
503
- font-variant-numeric: tabular-nums;
504
- font-family: var(--cb-font-mono);
505
- font-size: 0.8125rem;
506
- font-weight: 500;
507
- color: var(--cb-text-secondary);
508
- text-align: right;
509
- white-space: nowrap;
510
- }
511
-
512
- .timestamp {
513
- color: var(--cb-text-muted);
514
- font-size: 0.75rem;
515
- text-align: right;
516
- white-space: nowrap;
517
- }
518
-
519
- /* --- Pagination --- */
520
- .pagination {
521
- display: flex;
522
- justify-content: space-between;
523
- align-items: center;
524
- padding: 0.75rem 1rem;
525
- border-top: 1px solid var(--cb-border);
526
- }
527
-
528
- .pagination-link {
529
- padding: 0.375rem 0.75rem;
530
- border: 1px solid var(--cb-border);
531
- border-radius: var(--cb-radius);
532
- color: var(--cb-text-secondary);
533
- text-decoration: none;
534
- font-size: 0.8125rem;
535
- font-weight: 500;
536
- transition: all 0.15s ease;
537
- }
538
-
539
- .pagination-link:hover {
540
- background: var(--cb-bg-subtle);
541
- border-color: var(--cb-border-hover);
542
- color: var(--cb-text);
543
- }
544
-
545
- .pagination-info {
546
- font-size: 0.75rem;
547
- color: var(--cb-text-muted);
548
- }
549
-
550
- .pagination-side {
551
- min-width: 80px;
552
- }
553
-
554
- /* --- Empty State --- */
555
- .empty-state {
556
- text-align: center;
557
- padding: 3rem 1.5rem;
558
- color: var(--cb-text-secondary);
559
- }
560
-
561
- .empty-state-icon {
562
- width: 3rem;
563
- height: 3rem;
564
- margin: 0 auto 1rem;
565
- color: var(--cb-text-muted);
566
- }
567
-
568
- .empty-state h3 {
569
- font-size: 0.9375rem;
570
- font-weight: 600;
571
- color: var(--cb-text);
572
- margin-bottom: 0.375rem;
573
- }
574
-
575
- .empty-state p {
576
- font-size: 0.8125rem;
577
- color: var(--cb-text-secondary);
578
- }
579
-
580
- /* --- Detail Header --- */
581
- .detail-header {
582
- display: flex;
583
- align-items: flex-start;
584
- justify-content: space-between;
585
- gap: 1.5rem;
586
- }
587
-
588
- .detail-header-left {
589
- flex: 1;
590
- min-width: 0;
591
- }
592
-
593
- .detail-title {
594
- display: flex;
595
- align-items: center;
596
- gap: 0.625rem;
597
- flex-wrap: wrap;
598
- }
599
-
600
- .detail-title h1 {
601
- font-size: 1rem;
602
- font-weight: 600;
603
- word-break: break-all;
604
- color: var(--cb-text);
605
- margin: 0;
606
- }
607
-
608
- .detail-meta {
609
- display: flex;
610
- gap: 1.5rem;
611
- margin-top: 0.75rem;
612
- flex-wrap: wrap;
613
- }
614
-
615
- .meta-item {
616
- display: flex;
617
- flex-direction: column;
618
- gap: 2px;
619
- }
620
-
621
- .meta-label {
622
- font-size: 0.6875rem;
623
- font-weight: 600;
624
- text-transform: uppercase;
625
- letter-spacing: 0.04em;
626
- color: var(--cb-text-muted);
627
- }
628
-
629
- .meta-value {
630
- font-size: 0.8125rem;
631
- color: var(--cb-text);
632
- font-weight: 500;
633
- }
634
-
635
- .meta-value.mono {
636
- font-family: var(--cb-font-mono);
637
- font-size: 0.8125rem;
638
- }
639
-
640
- .meta-value a {
641
- color: var(--cb-text-secondary);
642
- text-decoration: none;
643
- }
644
-
645
- .meta-value a:hover {
646
- color: var(--cb-text);
647
- text-decoration: underline;
648
- }
649
-
650
- /* --- Tabs --- */
651
- .tabs {
652
- display: flex;
653
- gap: 0;
654
- border-bottom: 1px solid var(--cb-border);
655
- margin-bottom: 0;
656
- }
657
-
658
- .tab {
659
- padding: 0.625rem 1rem;
660
- font-size: 0.8125rem;
661
- font-weight: 500;
662
- color: var(--cb-text-secondary);
663
- text-decoration: none;
664
- border-bottom: 2px solid transparent;
665
- margin-bottom: -1px;
666
- transition: all 0.15s ease;
667
- cursor: pointer;
668
- }
669
-
670
- .tab:hover {
671
- color: var(--cb-text);
672
- text-decoration: none;
673
- }
674
-
675
- .tab.active {
676
- color: var(--cb-text);
677
- border-bottom-color: var(--cb-text);
678
- font-weight: 600;
679
- }
680
-
681
- .tab-content {
682
- display: none;
683
- padding: 1rem;
684
- }
685
-
686
- .tab-content.active {
687
- display: block;
688
- }
689
-
690
- /* --- Details Sections --- */
691
- .details-sections {
692
- display: flex;
693
- flex-direction: column;
694
- gap: 0;
695
- }
696
-
697
- .details-section {
698
- padding: 1rem 1.25rem;
699
- border-bottom: 1px solid var(--cb-border);
700
- }
701
-
702
- .details-section:last-child {
703
- border-bottom: none;
704
- }
705
-
706
- .section-header {
707
- display: flex;
708
- align-items: center;
709
- gap: 0.5rem;
710
- margin-bottom: 0.75rem;
711
- }
712
-
713
- .section-icon {
714
- width: 1.75rem;
715
- height: 1.75rem;
716
- border-radius: var(--cb-radius-sm);
717
- display: flex;
718
- align-items: center;
719
- justify-content: center;
720
- flex-shrink: 0;
721
- }
722
-
723
- .section-icon svg {
724
- width: 0.875rem;
725
- height: 0.875rem;
726
- }
727
-
728
- .section-icon.request { background: rgba(107,138,154,0.15); color: #4a7a8a; }
729
- .section-icon.route { background: rgba(138,107,154,0.15); color: #7a4a8a; }
730
- .section-icon.client { background: rgba(196,163,90,0.15); color: #9a7d2e; }
731
- .section-icon.other { background: var(--cb-bg-muted); color: var(--cb-text-secondary); }
732
- .section-icon.job { background: rgba(138,154,107,0.15); color: #5a7a3d; }
733
- .section-icon.queue { background: rgba(138,107,154,0.15); color: #7a4a8a; }
734
- .section-icon.properties { background: rgba(107,138,154,0.15); color: #4a7a8a; }
735
- .section-icon.statement { background: rgba(196,163,90,0.15); color: #9a7d2e; }
736
- .section-icon.trace { background: rgba(138,107,154,0.15); color: #7a4a8a; }
737
- .section-icon.events { background: rgba(197,48,48,0.15); color: #a53030; }
738
-
739
- .section-title {
740
- font-size: 0.6875rem;
741
- font-weight: 700;
742
- text-transform: uppercase;
743
- letter-spacing: 0.06em;
744
- color: var(--cb-text-muted);
745
- }
746
-
747
- .section-grid {
748
- display: grid;
749
- grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
750
- gap: 0.75rem 1.5rem;
751
- }
752
-
753
- .detail-item {
754
- display: flex;
755
- flex-direction: column;
756
- gap: 2px;
757
- }
758
-
759
- .detail-item.full-width {
760
- grid-column: 1 / -1;
761
- }
762
-
763
- .detail-label {
764
- font-size: 0.6875rem;
765
- font-weight: 500;
766
- color: var(--cb-text-muted);
767
- letter-spacing: 0.02em;
768
- }
769
-
770
- .detail-value {
771
- font-size: 0.8125rem;
772
- color: var(--cb-text);
773
- word-break: break-word;
774
- line-height: 1.4;
775
- }
776
-
777
- .detail-value.mono {
778
- font-family: var(--cb-font-mono);
779
- font-size: 0.8125rem;
780
- }
781
-
782
- .detail-value.prominent {
783
- font-size: 1.125rem;
784
- font-weight: 700;
785
- color: var(--cb-text);
786
- font-family: var(--cb-font-mono);
787
- letter-spacing: -0.01em;
788
- }
789
-
790
- .detail-value.truncate {
791
- white-space: nowrap;
792
- overflow: hidden;
793
- text-overflow: ellipsis;
794
- }
795
-
796
- .detail-value.secondary {
797
- color: var(--cb-text-secondary);
798
- font-size: 0.8125rem;
799
- }
800
-
801
- /* Status dot */
802
- .status-dot {
803
- display: inline-block;
804
- width: 6px;
805
- height: 6px;
806
- border-radius: 50%;
807
- margin-right: 0.375rem;
808
- }
809
-
810
- .status-dot.success { background: var(--cb-success); }
811
- .status-dot.warning { background: var(--cb-warning); }
812
- .status-dot.error { background: var(--cb-danger); }
813
-
814
- /* --- Waterfall --- */
815
- .waterfall {
816
- display: flex;
817
- flex-direction: column;
818
- gap: 1px;
819
- }
820
-
821
- .waterfall-header {
822
- display: flex;
823
- justify-content: space-between;
824
- padding: 0.5rem 0.75rem;
825
- font-size: 0.6875rem;
826
- font-weight: 600;
827
- text-transform: uppercase;
828
- letter-spacing: 0.04em;
829
- color: var(--cb-text-muted);
830
- border-bottom: 1px solid var(--cb-border);
831
- margin-bottom: 0.25rem;
832
- }
833
-
834
- .waterfall-row {
835
- padding: 0 0.75rem;
836
- cursor: pointer;
837
- border-radius: var(--cb-radius-sm);
838
- transition: background 0.1s ease;
839
- }
840
-
841
- .waterfall-row:hover .waterfall-bar-container {
842
- background: var(--cb-border-hover);
843
- }
844
-
845
- .waterfall-row.selected {
846
- /* No background change */
847
- }
848
-
849
- .waterfall-bar-container {
850
- height: 28px;
851
- background: var(--cb-bg-muted);
852
- border-radius: var(--cb-radius-sm);
853
- position: relative;
854
- overflow: hidden;
855
- display: flex;
856
- align-items: center;
857
- justify-content: space-between;
858
- }
859
-
860
- .waterfall-label {
861
- position: relative;
862
- z-index: 1;
863
- font-size: 0.75rem;
864
- color: var(--cb-text);
865
- font-family: var(--cb-font-mono);
866
- padding: 2px 6px;
867
- white-space: nowrap;
868
- overflow: hidden;
869
- text-overflow: ellipsis;
870
- max-width: 100%;
871
- background: rgba(255, 255, 255, 0.5);
872
- border-radius: 3px;
873
- margin-left: 3px;
874
- }
875
-
876
- .waterfall-bar {
877
- position: absolute;
878
- height: 100%;
879
- border-radius: var(--cb-radius-sm);
880
- min-width: 3px;
881
- opacity: 0.85;
882
- transition: opacity 0.15s ease;
883
- }
884
-
885
- .waterfall-bar:hover {
886
- opacity: 1;
887
- }
888
-
889
- /* Waterfall bar colors */
890
- .waterfall-bar.sql { background: var(--cb-info); }
891
- .waterfall-bar.cache { background: var(--cb-success); }
892
- .waterfall-bar.view { background: var(--cb-warning); }
893
- .waterfall-bar.http { background: #9A6B8A; }
894
- .waterfall-bar.mailer { background: #B07A8A; }
895
- .waterfall-bar.job { background: #8A9A6B; }
896
- .waterfall-bar.controller { background: #666; }
897
- .waterfall-bar.other { background: var(--cb-border-hover); }
898
-
899
- .waterfall-duration {
900
- position: relative;
901
- z-index: 1;
902
- font-size: 0.75rem;
903
- color: var(--cb-text);
904
- font-variant-numeric: tabular-nums;
905
- font-family: var(--cb-font-mono);
906
- background: rgba(255, 255, 255, 0.5);
907
- border-radius: 3px;
908
- padding: 2px 6px;
909
- margin-right: 3px;
910
- flex-shrink: 0;
911
- }
912
-
913
- /* Span detail panel */
914
- .span-detail {
915
- display: none;
916
- margin: 0 0.75rem 0.5rem 1.5rem;
917
- padding: 0.75rem 1rem;
918
- background: var(--cb-text);
919
- border-radius: var(--cb-radius-sm) var(--cb-radius) var(--cb-radius) var(--cb-radius-sm);
920
- font-size: 0.8125rem;
921
- border-left: 3px solid var(--cb-border-hover);
922
- }
923
-
924
- .span-detail.visible {
925
- display: block;
926
- }
927
-
928
- .span-detail.sql { border-left-color: var(--cb-info); }
929
- .span-detail.cache { border-left-color: var(--cb-success); }
930
- .span-detail.view { border-left-color: var(--cb-warning); }
931
- .span-detail.http { border-left-color: #9A6B8A; }
932
- .span-detail.mailer { border-left-color: #B07A8A; }
933
- .span-detail.job { border-left-color: #8A9A6B; }
934
- .span-detail.controller { border-left-color: #666; }
935
- .span-detail.other { border-left-color: var(--cb-border-hover); }
936
-
937
- .span-detail pre {
938
- margin: 0;
939
- padding: 0;
940
- background: transparent;
941
- white-space: pre-wrap;
942
- word-break: break-all;
943
- color: #e5e5e5;
944
- font-size: 0.75rem;
945
- line-height: 1.5;
946
- }
947
-
948
- /* Legend */
949
- .legend {
950
- display: flex;
951
- gap: 0;
952
- flex-wrap: wrap;
953
- padding: 0.625rem 1rem;
954
- background: var(--cb-bg-subtle);
955
- border-bottom: 1px solid var(--cb-border);
956
- }
957
-
958
- .legend-item {
959
- display: flex;
960
- align-items: center;
961
- gap: 0.375rem;
962
- font-size: 0.75rem;
963
- color: var(--cb-text-secondary);
964
- }
965
-
966
- .legend-color {
967
- width: 12px;
968
- height: 12px;
969
- border-radius: 3px;
970
- }
971
-
972
- .legend-color.sql { background: var(--cb-info); }
973
- .legend-color.cache { background: var(--cb-success); }
974
- .legend-color.view { background: var(--cb-warning); }
975
- .legend-color.http { background: #9A6B8A; }
976
- .legend-color.mailer { background: #B07A8A; }
977
- .legend-color.job { background: #8A9A6B; }
978
- .legend-color.controller { background: #666; }
979
- .legend-color.other { background: var(--cb-border-hover); }
980
- .legend-color.all {
981
- background: linear-gradient(135deg, var(--cb-info) 0%, var(--cb-success) 25%, var(--cb-warning) 50%, #9A6B8A 75%, var(--cb-text-secondary) 100%);
982
- }
983
-
984
- /* Clickable legend items */
985
- .legend-item.clickable {
986
- cursor: pointer;
987
- padding: 0.3rem 0.625rem;
988
- border-radius: var(--cb-radius-sm);
989
- transition: all 0.15s ease;
990
- }
991
-
992
- .legend-item.clickable:hover {
993
- background: var(--cb-bg-muted);
994
- }
995
-
996
- .legend-item.clickable.active {
997
- background: var(--cb-text);
998
- color: white;
999
- }
1000
-
1001
- .waterfall-row.hidden {
1002
- display: none;
1003
- }
1004
-
1005
- .span-detail.hidden-by-filter {
1006
- display: none !important;
1007
- }
1008
-
1009
- /* --- SQL Tooltip --- */
1010
- #sql-tooltip {
1011
- position: fixed;
1012
- top: 50%;
1013
- left: 50%;
1014
- transform: translate(-50%, -50%);
1015
- z-index: 1000;
1016
- background: var(--cb-text);
1017
- color: #e5e5e5;
1018
- padding: 1rem 1.25rem;
1019
- border-radius: var(--cb-radius);
1020
- font-size: 0.8125rem;
1021
- font-family: var(--cb-font-mono);
1022
- white-space: pre-wrap;
1023
- word-break: break-all;
1024
- max-width: 600px;
1025
- max-height: 200px;
1026
- overflow: auto;
1027
- box-shadow: var(--cb-shadow-lg);
1028
- pointer-events: none;
1029
- opacity: 0;
1030
- visibility: hidden;
1031
- transition: opacity 0.15s ease, visibility 0.15s ease;
1032
- }
1033
-
1034
- #sql-tooltip.visible {
1035
- opacity: 1;
1036
- visibility: visible;
1037
- }
1038
-
1039
- /* --- Code Blocks --- */
1040
- .code-path {
1041
- font-family: var(--cb-font-mono);
1042
- font-size: 0.8125rem;
1043
- color: var(--cb-text-secondary);
1044
- background: var(--cb-bg-subtle);
1045
- padding: 0.125rem 0.375rem;
1046
- border-radius: var(--cb-radius-sm);
1047
- display: inline-block;
1048
- }
1049
-
1050
- pre {
1051
- background: var(--cb-text);
1052
- color: #e5e5e5;
1053
- padding: 1rem;
1054
- border-radius: var(--cb-radius);
1055
- overflow-x: auto;
1056
- font-size: 0.8125rem;
1057
- line-height: 1.5;
1058
- }
1059
-
1060
- /* Statement block */
1061
- .statement-block {
1062
- background: var(--cb-text);
1063
- border-radius: var(--cb-radius);
1064
- padding: 1rem;
1065
- overflow-x: auto;
1066
- }
1067
-
1068
- .statement-block pre {
1069
- margin: 0;
1070
- padding: 0;
1071
- white-space: pre-wrap;
1072
- word-break: break-all;
1073
- color: #e5e5e5;
1074
- font-family: var(--cb-font-mono);
1075
- font-size: 0.8125rem;
1076
- line-height: 1.5;
1077
- }
1078
-
1079
- /* Stacktrace */
1080
- .stacktrace-list {
1081
- list-style: none;
1082
- padding: 0;
1083
- margin: 0;
1084
- font-family: var(--cb-font-mono);
1085
- font-size: 0.75rem;
1086
- background: var(--cb-bg-subtle);
1087
- border-radius: var(--cb-radius);
1088
- overflow: hidden;
1089
- }
1090
-
1091
- .stacktrace-list li {
1092
- padding: 0.375rem 0.75rem;
1093
- border-bottom: 1px solid var(--cb-border);
1094
- color: var(--cb-text-secondary);
1095
- }
1096
-
1097
- .stacktrace-list li:last-child {
1098
- border-bottom: none;
1099
- }
1100
-
1101
- .stacktrace-list .file-path { color: var(--cb-text-secondary); }
1102
- .stacktrace-list .line-number { color: var(--cb-text-muted); }
1103
- .stacktrace-list .method-name { color: var(--cb-text); }
1104
-
1105
- /* Events section */
1106
- .event-item {
1107
- padding: 0.75rem;
1108
- background: var(--cb-bg-subtle);
1109
- border-radius: var(--cb-radius-sm);
1110
- margin-bottom: 0.5rem;
1111
- }
1112
-
1113
- .event-name {
1114
- font-weight: 600;
1115
- color: var(--cb-danger);
1116
- margin-bottom: 0.5rem;
1117
- font-size: 0.8125rem;
1118
- }
1119
-
1120
- .event-props {
1121
- font-size: 0.8125rem;
1122
- font-family: var(--cb-font-mono);
1123
- color: var(--cb-text-secondary);
1124
- }
1125
-
1126
- /* --- Buttons --- */
1127
- .copy-ai-btn,
1128
- .collapse-btn {
1129
- display: inline-flex;
1130
- align-items: center;
1131
- gap: 0.375rem;
1132
- padding: 0.3rem 0.625rem;
1133
- font-size: 0.75rem;
1134
- font-weight: 500;
1135
- font-family: var(--cb-font);
1136
- color: var(--cb-text-secondary);
1137
- background: var(--cb-bg);
1138
- border: 1px solid var(--cb-border);
1139
- border-radius: var(--cb-radius);
1140
- cursor: pointer;
1141
- transition: all 0.15s ease;
1142
- }
1143
-
1144
- .copy-ai-btn:hover,
1145
- .collapse-btn:hover {
1146
- background: var(--cb-bg-subtle);
1147
- color: var(--cb-text);
1148
- border-color: var(--cb-border-hover);
1149
- }
1150
-
1151
- .copy-ai-btn.copied {
1152
- background: var(--cb-success);
1153
- color: white;
1154
- border-color: var(--cb-success);
1155
- }
1156
-
1157
- /* --- Alert --- */
1158
- .alert {
1159
- padding: 0.625rem 1rem;
1160
- border-radius: var(--cb-radius);
1161
- margin-bottom: 0.75rem;
1162
- font-size: 0.8125rem;
1163
- }
1164
-
1165
- .alert-danger {
1166
- background: rgba(197,48,48,0.1);
1167
- color: var(--cb-danger);
1168
- border: 1px solid rgba(197,48,48,0.2);
1169
- }
1170
-
1171
- .alert-success {
1172
- background: rgba(43,122,62,0.1);
1173
- color: var(--cb-success);
1174
- border: 1px solid rgba(43,122,62,0.2);
1175
- }
1176
-
1177
- /* --- Muted --- */
1178
- .muted { color: var(--cb-text-muted); }
1179
-
1180
- /* --- Responsive --- */
1181
- @media (max-width: 1024px) {
1182
- .sidebar {
1183
- width: var(--cb-sidebar-collapsed);
1184
- }
1185
- .sidebar-header {
1186
- padding: 1rem 0.75rem;
1187
- justify-content: center;
1188
- }
1189
- .logo-text, .nav-section-title, .nav-item span, .nav-item-count, .btn-clear span {
1190
- display: none;
1191
- }
1192
- .nav-item {
1193
- justify-content: center;
1194
- padding: 0.625rem;
1195
- }
1196
- .nav-item i,
1197
- .nav-item svg {
1198
- margin: 0;
1199
- }
1200
- .btn-clear {
1201
- justify-content: center;
1202
- padding: 0.625rem;
1203
- }
1204
- .main-content {
1205
- margin-left: var(--cb-sidebar-collapsed);
1206
- }
1207
- .sidebar-ad {
1208
- display: none;
1209
- }
1210
- }
1211
-
1212
- @media (max-width: 768px) {
1213
- .page-header {
1214
- flex-direction: column;
1215
- align-items: flex-start;
1216
- padding: 1rem;
1217
- }
1218
- .page-body {
1219
- padding: 1rem;
1220
- }
1221
- .detail-meta {
1222
- gap: 1rem;
1223
- }
1224
- .section-grid {
1225
- grid-template-columns: 1fr;
1226
- }
1227
- }
1228
-
1229
- /* Empty clues (for waterfall empty state) */
1230
- .empty-clues {
1231
- text-align: center;
1232
- padding: 2.5rem 1rem;
1233
- color: var(--cb-text-secondary);
1234
- }
1235
-
1236
- .empty-clues svg {
1237
- width: 2.5rem;
1238
- height: 2.5rem;
1239
- margin-bottom: 0.75rem;
1240
- color: var(--cb-text-muted);
1241
- }
1242
-
1243
- .empty-clues p {
1244
- font-size: 0.8125rem;
1245
- }