findbug 0.3.5 → 0.5.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.
- checksums.yaml +4 -4
- data/README.md +49 -34
- data/app/controllers/findbug/alerts_controller.rb +224 -0
- data/app/models/findbug/alert_channel.rb +167 -0
- data/app/models/findbug/error_event.rb +34 -6
- data/app/models/findbug/performance_event.rb +38 -16
- data/app/views/findbug/alerts/edit.html.erb +133 -0
- data/app/views/findbug/alerts/index.html.erb +127 -0
- data/app/views/findbug/alerts/new.html.erb +154 -0
- data/app/views/layouts/findbug/application.html.erb +56 -1
- data/docs/docs.html +976 -0
- data/docs/index.html +816 -22
- data/lib/findbug/adapter_helper.rb +74 -0
- data/lib/findbug/alerts/dispatcher.rb +18 -32
- data/lib/findbug/configuration.rb +17 -56
- data/lib/findbug/engine.rb +9 -0
- data/lib/findbug/railtie.rb +8 -0
- data/lib/findbug/version.rb +1 -1
- data/lib/findbug.rb +1 -0
- data/lib/generators/findbug/install_generator.rb +6 -0
- data/lib/generators/findbug/templates/POST_INSTALL +5 -8
- data/lib/generators/findbug/templates/create_findbug_alert_channels.rb +24 -0
- data/lib/generators/findbug/templates/create_findbug_error_events.rb +3 -3
- data/lib/generators/findbug/templates/create_findbug_performance_events.rb +3 -3
- data/lib/generators/findbug/templates/initializer.rb +3 -26
- data/lib/generators/findbug/upgrade_generator.rb +79 -0
- metadata +15 -3
data/docs/index.html
CHANGED
|
@@ -961,6 +961,150 @@
|
|
|
961
961
|
.demo-grid-2 { grid-template-columns: 1fr; }
|
|
962
962
|
}
|
|
963
963
|
|
|
964
|
+
/* Demo Badge Info */
|
|
965
|
+
.demo-badge-info {
|
|
966
|
+
background-color: hsl(var(--info) / 0.15);
|
|
967
|
+
color: hsl(var(--info));
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/* Demo Toggle */
|
|
971
|
+
.demo-toggle {
|
|
972
|
+
position: relative;
|
|
973
|
+
display: inline-block;
|
|
974
|
+
width: 2rem;
|
|
975
|
+
height: 1.125rem;
|
|
976
|
+
}
|
|
977
|
+
.demo-toggle input { display: none; }
|
|
978
|
+
.demo-toggle-slider {
|
|
979
|
+
position: absolute;
|
|
980
|
+
inset: 0;
|
|
981
|
+
border-radius: 9999px;
|
|
982
|
+
background-color: hsl(0 62.8% 30.6%);
|
|
983
|
+
transition: background-color 0.2s;
|
|
984
|
+
}
|
|
985
|
+
.demo-toggle-slider::before {
|
|
986
|
+
content: '';
|
|
987
|
+
position: absolute;
|
|
988
|
+
width: 0.875rem;
|
|
989
|
+
height: 0.875rem;
|
|
990
|
+
left: 0.125rem;
|
|
991
|
+
top: 50%;
|
|
992
|
+
transform: translateY(-50%);
|
|
993
|
+
border-radius: 50%;
|
|
994
|
+
background: white;
|
|
995
|
+
transition: transform 0.2s;
|
|
996
|
+
}
|
|
997
|
+
.demo-toggle input:checked + .demo-toggle-slider {
|
|
998
|
+
background-color: hsl(var(--success));
|
|
999
|
+
}
|
|
1000
|
+
.demo-toggle input:checked + .demo-toggle-slider::before {
|
|
1001
|
+
transform: translateY(-50%) translateX(0.875rem);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
/* Demo Icon Button */
|
|
1005
|
+
.demo-btn-icon {
|
|
1006
|
+
display: inline-flex;
|
|
1007
|
+
align-items: center;
|
|
1008
|
+
justify-content: center;
|
|
1009
|
+
width: 1.75rem;
|
|
1010
|
+
height: 1.75rem;
|
|
1011
|
+
border-radius: var(--radius);
|
|
1012
|
+
color: hsl(var(--muted-foreground));
|
|
1013
|
+
background: transparent;
|
|
1014
|
+
border: none;
|
|
1015
|
+
cursor: pointer;
|
|
1016
|
+
transition: all 0.15s;
|
|
1017
|
+
}
|
|
1018
|
+
.demo-btn-icon:hover {
|
|
1019
|
+
background-color: hsl(var(--muted));
|
|
1020
|
+
color: hsl(var(--foreground));
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/* Demo Tab Content */
|
|
1024
|
+
.demo-tab-content { display: none; }
|
|
1025
|
+
.demo-tab-content.active { display: block; }
|
|
1026
|
+
|
|
1027
|
+
/* Demo Filter Bar */
|
|
1028
|
+
.demo-filter-bar {
|
|
1029
|
+
display: flex;
|
|
1030
|
+
justify-content: space-between;
|
|
1031
|
+
align-items: center;
|
|
1032
|
+
gap: 0.75rem;
|
|
1033
|
+
margin-bottom: 0.75rem;
|
|
1034
|
+
flex-wrap: wrap;
|
|
1035
|
+
}
|
|
1036
|
+
.demo-filter-bar-filters {
|
|
1037
|
+
display: flex;
|
|
1038
|
+
gap: 0.5rem;
|
|
1039
|
+
flex-wrap: wrap;
|
|
1040
|
+
}
|
|
1041
|
+
.demo-select {
|
|
1042
|
+
appearance: none;
|
|
1043
|
+
background-color: hsl(var(--secondary));
|
|
1044
|
+
color: hsl(var(--foreground));
|
|
1045
|
+
border: 1px solid hsl(var(--border));
|
|
1046
|
+
border-radius: var(--radius);
|
|
1047
|
+
padding: 0.375rem 1.75rem 0.375rem 0.625rem;
|
|
1048
|
+
font-size: 0.75rem;
|
|
1049
|
+
cursor: pointer;
|
|
1050
|
+
background-image: url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23999' fill='none' stroke-width='1.5'/%3E%3C/svg%3E");
|
|
1051
|
+
background-repeat: no-repeat;
|
|
1052
|
+
background-position: right 0.5rem center;
|
|
1053
|
+
}
|
|
1054
|
+
.demo-search-input {
|
|
1055
|
+
background-color: hsl(var(--secondary));
|
|
1056
|
+
color: hsl(var(--foreground));
|
|
1057
|
+
border: 1px solid hsl(var(--border));
|
|
1058
|
+
border-radius: var(--radius);
|
|
1059
|
+
padding: 0.375rem 0.625rem;
|
|
1060
|
+
font-size: 0.75rem;
|
|
1061
|
+
width: 160px;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
/* Demo Chart */
|
|
1065
|
+
.demo-chart-container {
|
|
1066
|
+
display: flex;
|
|
1067
|
+
align-items: flex-end;
|
|
1068
|
+
gap: 3px;
|
|
1069
|
+
height: 80px;
|
|
1070
|
+
padding: 1rem 1.25rem 0.25rem;
|
|
1071
|
+
}
|
|
1072
|
+
.demo-chart-bar {
|
|
1073
|
+
flex: 1;
|
|
1074
|
+
background: hsl(var(--info) / 0.6);
|
|
1075
|
+
border-radius: 2px 2px 0 0;
|
|
1076
|
+
min-width: 4px;
|
|
1077
|
+
transition: background 0.15s;
|
|
1078
|
+
}
|
|
1079
|
+
.demo-chart-bar:hover {
|
|
1080
|
+
background: hsl(var(--info));
|
|
1081
|
+
}
|
|
1082
|
+
.demo-chart-labels {
|
|
1083
|
+
display: flex;
|
|
1084
|
+
justify-content: space-between;
|
|
1085
|
+
padding: 0.375rem 1.25rem 0.75rem;
|
|
1086
|
+
font-size: 0.625rem;
|
|
1087
|
+
color: hsl(var(--muted-foreground));
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
/* Demo Action Buttons (Resolve/Ignore) */
|
|
1091
|
+
.demo-btn-sm {
|
|
1092
|
+
display: inline-flex;
|
|
1093
|
+
align-items: center;
|
|
1094
|
+
padding: 0.1875rem 0.5rem;
|
|
1095
|
+
font-size: 0.6875rem;
|
|
1096
|
+
font-weight: 500;
|
|
1097
|
+
border-radius: var(--radius);
|
|
1098
|
+
border: 1px solid hsl(var(--border));
|
|
1099
|
+
background: transparent;
|
|
1100
|
+
color: hsl(var(--foreground));
|
|
1101
|
+
cursor: pointer;
|
|
1102
|
+
}
|
|
1103
|
+
.demo-btn-sm.ghost {
|
|
1104
|
+
border-color: transparent;
|
|
1105
|
+
color: hsl(var(--muted-foreground));
|
|
1106
|
+
}
|
|
1107
|
+
|
|
964
1108
|
@media (max-width: 640px) {
|
|
965
1109
|
.demo-stats-grid { grid-template-columns: 1fr; }
|
|
966
1110
|
.demo-app-nav { display: none; }
|
|
@@ -1453,29 +1597,189 @@
|
|
|
1453
1597
|
/* CTA Section */
|
|
1454
1598
|
.cta {
|
|
1455
1599
|
padding: 5rem 0;
|
|
1456
|
-
|
|
1600
|
+
background: hsl(0 0% 2%);
|
|
1457
1601
|
}
|
|
1458
1602
|
|
|
1459
|
-
.cta
|
|
1460
|
-
|
|
1603
|
+
.cta-box {
|
|
1604
|
+
display: grid;
|
|
1605
|
+
grid-template-columns: 1fr 1.2fr;
|
|
1606
|
+
border-radius: 1.5rem;
|
|
1607
|
+
overflow: hidden;
|
|
1608
|
+
border: 1px solid hsl(var(--border));
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
.cta-content {
|
|
1612
|
+
display: flex;
|
|
1613
|
+
flex-direction: column;
|
|
1614
|
+
justify-content: center;
|
|
1615
|
+
padding: 3rem;
|
|
1616
|
+
position: relative;
|
|
1617
|
+
z-index: 2;
|
|
1618
|
+
background: linear-gradient(135deg,
|
|
1619
|
+
hsl(145 70% 22%) 0%,
|
|
1620
|
+
hsl(170 65% 30%) 50%,
|
|
1621
|
+
hsl(195 75% 40%) 100%
|
|
1622
|
+
);
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
.cta-content::before {
|
|
1626
|
+
content: '';
|
|
1627
|
+
position: absolute;
|
|
1628
|
+
inset: 0;
|
|
1629
|
+
background:
|
|
1630
|
+
radial-gradient(ellipse 80% 50% at 20% 40%, hsl(145 100% 45% / 0.3), transparent),
|
|
1631
|
+
radial-gradient(ellipse 60% 80% at 80% 80%, hsl(195 100% 55% / 0.35), transparent),
|
|
1632
|
+
radial-gradient(ellipse 50% 50% at 50% 20%, hsl(170 100% 45% / 0.2), transparent);
|
|
1633
|
+
z-index: -1;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
.cta-content h2 {
|
|
1637
|
+
font-size: 2.25rem;
|
|
1461
1638
|
font-weight: 700;
|
|
1462
1639
|
letter-spacing: -0.025em;
|
|
1463
|
-
margin-bottom:
|
|
1640
|
+
margin-bottom: 1rem;
|
|
1641
|
+
line-height: 1.2;
|
|
1642
|
+
color: hsl(var(--foreground));
|
|
1464
1643
|
}
|
|
1465
1644
|
|
|
1466
|
-
.cta p {
|
|
1645
|
+
.cta-content p {
|
|
1467
1646
|
font-size: 1rem;
|
|
1468
|
-
color:
|
|
1647
|
+
color: white;
|
|
1469
1648
|
margin-bottom: 1.5rem;
|
|
1649
|
+
max-width: 320px;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
.cta-preview {
|
|
1653
|
+
position: relative;
|
|
1654
|
+
display: flex;
|
|
1655
|
+
align-items: center;
|
|
1656
|
+
justify-content: center;
|
|
1657
|
+
padding: 2rem;
|
|
1658
|
+
background: hsl(0 0% 2%);
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
.cta-preview-window {
|
|
1662
|
+
width: 100%;
|
|
1470
1663
|
max-width: 400px;
|
|
1471
|
-
|
|
1472
|
-
|
|
1664
|
+
background: hsl(var(--card));
|
|
1665
|
+
border: 1px solid hsl(var(--border));
|
|
1666
|
+
border-radius: 12px;
|
|
1667
|
+
overflow: hidden;
|
|
1668
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
.cta-preview-titlebar {
|
|
1672
|
+
display: flex;
|
|
1673
|
+
align-items: center;
|
|
1674
|
+
gap: 0.5rem;
|
|
1675
|
+
padding: 0.75rem 1rem;
|
|
1676
|
+
background: hsl(var(--secondary));
|
|
1677
|
+
border-bottom: 1px solid hsl(var(--border));
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
.cta-preview-dot {
|
|
1681
|
+
width: 10px;
|
|
1682
|
+
height: 10px;
|
|
1683
|
+
border-radius: 50%;
|
|
1684
|
+
background: hsl(var(--muted-foreground) / 0.3);
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
.cta-preview-content {
|
|
1688
|
+
padding: 1.25rem;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
.cta-preview-header {
|
|
1692
|
+
display: flex;
|
|
1693
|
+
align-items: center;
|
|
1694
|
+
gap: 0.75rem;
|
|
1695
|
+
margin-bottom: 1rem;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
.cta-preview-logo {
|
|
1699
|
+
width: 32px;
|
|
1700
|
+
height: 32px;
|
|
1701
|
+
background: hsl(var(--destructive) / 0.15);
|
|
1702
|
+
border-radius: 8px;
|
|
1703
|
+
display: flex;
|
|
1704
|
+
align-items: center;
|
|
1705
|
+
justify-content: center;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
.cta-preview-logo svg {
|
|
1709
|
+
width: 18px;
|
|
1710
|
+
height: 18px;
|
|
1711
|
+
color: hsl(var(--destructive));
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
.cta-preview-title {
|
|
1715
|
+
font-weight: 600;
|
|
1716
|
+
font-size: 0.9375rem;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
.cta-preview-stats {
|
|
1720
|
+
display: grid;
|
|
1721
|
+
grid-template-columns: repeat(3, 1fr);
|
|
1722
|
+
gap: 0.75rem;
|
|
1723
|
+
margin-bottom: 1rem;
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
.cta-stat-card {
|
|
1727
|
+
background: hsl(var(--secondary));
|
|
1728
|
+
border-radius: 8px;
|
|
1729
|
+
padding: 0.75rem;
|
|
1730
|
+
text-align: center;
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
.cta-stat-value {
|
|
1734
|
+
font-size: 1.25rem;
|
|
1735
|
+
font-weight: 700;
|
|
1736
|
+
color: hsl(var(--foreground));
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
.cta-stat-label {
|
|
1740
|
+
font-size: 0.6875rem;
|
|
1741
|
+
color: hsl(var(--muted-foreground));
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
.cta-preview-chart {
|
|
1745
|
+
height: 60px;
|
|
1746
|
+
background: hsl(var(--secondary));
|
|
1747
|
+
border-radius: 8px;
|
|
1748
|
+
display: flex;
|
|
1749
|
+
align-items: flex-end;
|
|
1750
|
+
justify-content: space-around;
|
|
1751
|
+
padding: 0.75rem;
|
|
1752
|
+
gap: 4px;
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
.cta-chart-bar {
|
|
1756
|
+
width: 12px;
|
|
1757
|
+
background: linear-gradient(to top, hsl(var(--success)), hsl(var(--success) / 0.5));
|
|
1758
|
+
border-radius: 2px;
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
@media (max-width: 900px) {
|
|
1762
|
+
.cta-box {
|
|
1763
|
+
grid-template-columns: 1fr;
|
|
1764
|
+
}
|
|
1765
|
+
.cta-content {
|
|
1766
|
+
padding: 2.5rem 1.5rem;
|
|
1767
|
+
text-align: center;
|
|
1768
|
+
align-items: center;
|
|
1769
|
+
}
|
|
1770
|
+
.cta-content h2 {
|
|
1771
|
+
font-size: 1.75rem;
|
|
1772
|
+
}
|
|
1773
|
+
.cta-preview {
|
|
1774
|
+
padding: 1.5rem;
|
|
1775
|
+
}
|
|
1473
1776
|
}
|
|
1474
1777
|
|
|
1475
1778
|
/* Footer */
|
|
1476
1779
|
footer {
|
|
1477
1780
|
padding: 2rem 0;
|
|
1478
1781
|
text-align: center;
|
|
1782
|
+
background: hsl(0 0% 2%);
|
|
1479
1783
|
}
|
|
1480
1784
|
|
|
1481
1785
|
.footer-links {
|
|
@@ -1539,6 +1843,7 @@
|
|
|
1539
1843
|
<a href="#comparison">Compare</a>
|
|
1540
1844
|
<a href="#architecture">Architecture</a>
|
|
1541
1845
|
<a href="#demo">Demo</a>
|
|
1846
|
+
<a href="/docs">Docs</a>
|
|
1542
1847
|
</div>
|
|
1543
1848
|
<div class="nav-right">
|
|
1544
1849
|
<a href="#demo" class="btn btn-primary btn-sm">
|
|
@@ -1557,7 +1862,7 @@
|
|
|
1557
1862
|
<div class="container">
|
|
1558
1863
|
<div class="hero-badge">
|
|
1559
1864
|
<span>NEW</span>
|
|
1560
|
-
v0.
|
|
1865
|
+
v0.5.0 — now database-agnostic (PostgreSQL · MySQL · SQLite) with full test coverage
|
|
1561
1866
|
</div>
|
|
1562
1867
|
<h1>Catch bugs<br>before your users do</h1>
|
|
1563
1868
|
<p>
|
|
@@ -1575,7 +1880,7 @@
|
|
|
1575
1880
|
</div>
|
|
1576
1881
|
<div class="hero-code">
|
|
1577
1882
|
<span class="comment"># Add to your Gemfile:</span><br>
|
|
1578
|
-
<span class="keyword">gem</span> <span class="string">"findbug", "~> 0.
|
|
1883
|
+
<span class="keyword">gem</span> <span class="string">"findbug", "~> 0.5.0"</span><br><br>
|
|
1579
1884
|
<span class="comment"># Install and you're done!</span><br>
|
|
1580
1885
|
$ rails generate findbug:install<br>
|
|
1581
1886
|
$ rails db:migrate<br><br>
|
|
@@ -1633,7 +1938,7 @@
|
|
|
1633
1938
|
<!-- Self-Hosted - Narrow Card with Privacy Visual -->
|
|
1634
1939
|
<div class="bento-card bento-narrow">
|
|
1635
1940
|
<h3>Self-Hosted</h3>
|
|
1636
|
-
<p>Your data stays on your infrastructure.
|
|
1941
|
+
<p>Your data stays on your infrastructure. Database-agnostic — works with PostgreSQL, MySQL, or SQLite.</p>
|
|
1637
1942
|
<div class="visual">
|
|
1638
1943
|
<div class="privacy-visual">
|
|
1639
1944
|
<div class="server-icon">
|
|
@@ -1949,6 +2254,10 @@
|
|
|
1949
2254
|
<div class="comparison-highlight-value">2 min</div>
|
|
1950
2255
|
<div class="comparison-highlight-label">Setup time</div>
|
|
1951
2256
|
</div>
|
|
2257
|
+
<div class="comparison-highlight-item">
|
|
2258
|
+
<div class="comparison-highlight-value">79</div>
|
|
2259
|
+
<div class="comparison-highlight-label">Passing specs</div>
|
|
2260
|
+
</div>
|
|
1952
2261
|
</div>
|
|
1953
2262
|
</div>
|
|
1954
2263
|
</div>
|
|
@@ -2046,7 +2355,7 @@
|
|
|
2046
2355
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>
|
|
2047
2356
|
</div>
|
|
2048
2357
|
<div class="flow-node-title">Your Database</div>
|
|
2049
|
-
<div class="flow-node-desc">PostgreSQL
|
|
2358
|
+
<div class="flow-node-desc">PostgreSQL · MySQL · SQLite</div>
|
|
2050
2359
|
</div>
|
|
2051
2360
|
|
|
2052
2361
|
<div class="flow-arrow">
|
|
@@ -2126,9 +2435,10 @@
|
|
|
2126
2435
|
<span>FindBug</span>
|
|
2127
2436
|
</div>
|
|
2128
2437
|
<nav class="demo-app-nav">
|
|
2129
|
-
<a class="active">Dashboard</a>
|
|
2130
|
-
<a>Errors</a>
|
|
2131
|
-
<a>Performance</a>
|
|
2438
|
+
<a class="active" onclick="switchDemoTab('dashboard', this)">Dashboard</a>
|
|
2439
|
+
<a onclick="switchDemoTab('errors', this)">Errors</a>
|
|
2440
|
+
<a onclick="switchDemoTab('performance', this)">Performance</a>
|
|
2441
|
+
<a onclick="switchDemoTab('alerts', this)">Alerts</a>
|
|
2132
2442
|
</nav>
|
|
2133
2443
|
<div class="demo-header-right">
|
|
2134
2444
|
<div class="demo-health-indicator">
|
|
@@ -2138,8 +2448,10 @@
|
|
|
2138
2448
|
</div>
|
|
2139
2449
|
</div>
|
|
2140
2450
|
|
|
2141
|
-
<!-- Main Content
|
|
2451
|
+
<!-- Main Content -->
|
|
2142
2452
|
<div class="demo-main">
|
|
2453
|
+
<!-- Dashboard Tab -->
|
|
2454
|
+
<div class="demo-tab-content active" id="demo-tab-dashboard">
|
|
2143
2455
|
<h1 class="demo-page-title">Dashboard</h1>
|
|
2144
2456
|
<p class="demo-page-description">Monitor errors and performance across your application.</p>
|
|
2145
2457
|
|
|
@@ -2252,6 +2564,422 @@
|
|
|
2252
2564
|
</table>
|
|
2253
2565
|
</div>
|
|
2254
2566
|
</div>
|
|
2567
|
+
</div><!-- /demo-tab-dashboard -->
|
|
2568
|
+
|
|
2569
|
+
<!-- Errors Tab -->
|
|
2570
|
+
<div class="demo-tab-content" id="demo-tab-errors">
|
|
2571
|
+
<h1 class="demo-page-title">Errors</h1>
|
|
2572
|
+
<p class="demo-page-description">Track and manage application errors.</p>
|
|
2573
|
+
|
|
2574
|
+
<!-- Filter Bar -->
|
|
2575
|
+
<div class="demo-filter-bar">
|
|
2576
|
+
<div class="demo-filter-bar-filters">
|
|
2577
|
+
<select class="demo-select"><option>Unresolved</option><option>Resolved</option><option>Ignored</option><option>All Statuses</option></select>
|
|
2578
|
+
<select class="demo-select"><option>All Severities</option><option>Error</option><option>Warning</option><option>Info</option></select>
|
|
2579
|
+
<select class="demo-select"><option>All Time</option><option>Last Hour</option><option>Last 24 Hours</option><option>Last 7 Days</option></select>
|
|
2580
|
+
<select class="demo-select"><option>Most Recent</option><option>Most Occurrences</option><option>Oldest</option></select>
|
|
2581
|
+
</div>
|
|
2582
|
+
<input type="text" class="demo-search-input" placeholder="Search errors...">
|
|
2583
|
+
</div>
|
|
2584
|
+
|
|
2585
|
+
<p class="demo-text-muted demo-text-xs" style="margin-bottom: 0.75rem;">Showing 5 of 12 errors</p>
|
|
2586
|
+
|
|
2587
|
+
<!-- Errors Table -->
|
|
2588
|
+
<div class="demo-card">
|
|
2589
|
+
<table class="demo-table">
|
|
2590
|
+
<thead>
|
|
2591
|
+
<tr>
|
|
2592
|
+
<th style="width: 45%;">Error</th>
|
|
2593
|
+
<th>Status</th>
|
|
2594
|
+
<th>Count</th>
|
|
2595
|
+
<th>Last Seen</th>
|
|
2596
|
+
<th>Actions</th>
|
|
2597
|
+
</tr>
|
|
2598
|
+
</thead>
|
|
2599
|
+
<tbody>
|
|
2600
|
+
<tr>
|
|
2601
|
+
<td>
|
|
2602
|
+
<a href="#" class="demo-font-mono" style="font-weight: 600;">Stripe::CardError</a><br>
|
|
2603
|
+
<span class="demo-text-muted demo-text-sm">Your card was declined</span>
|
|
2604
|
+
<div style="margin-top: 0.25rem;">
|
|
2605
|
+
<span class="demo-badge demo-badge-error">error</span>
|
|
2606
|
+
<span class="demo-text-muted demo-text-xs" style="margin-left: 0.5rem;">production</span>
|
|
2607
|
+
</div>
|
|
2608
|
+
</td>
|
|
2609
|
+
<td><span class="demo-badge demo-badge-error">unresolved</span></td>
|
|
2610
|
+
<td><strong>142</strong></td>
|
|
2611
|
+
<td class="demo-text-muted demo-text-sm">2 minutes ago</td>
|
|
2612
|
+
<td>
|
|
2613
|
+
<button class="demo-btn-sm">Resolve</button>
|
|
2614
|
+
<button class="demo-btn-sm ghost">Ignore</button>
|
|
2615
|
+
</td>
|
|
2616
|
+
</tr>
|
|
2617
|
+
<tr>
|
|
2618
|
+
<td>
|
|
2619
|
+
<a href="#" class="demo-font-mono" style="font-weight: 600;">ActiveRecord::RecordInvalid</a><br>
|
|
2620
|
+
<span class="demo-text-muted demo-text-sm">Validation failed: Email has already been taken</span>
|
|
2621
|
+
<div style="margin-top: 0.25rem;">
|
|
2622
|
+
<span class="demo-badge demo-badge-error">error</span>
|
|
2623
|
+
<span class="demo-text-muted demo-text-xs" style="margin-left: 0.5rem;">production</span>
|
|
2624
|
+
</div>
|
|
2625
|
+
</td>
|
|
2626
|
+
<td><span class="demo-badge demo-badge-error">unresolved</span></td>
|
|
2627
|
+
<td><strong>89</strong></td>
|
|
2628
|
+
<td class="demo-text-muted demo-text-sm">5 minutes ago</td>
|
|
2629
|
+
<td>
|
|
2630
|
+
<button class="demo-btn-sm">Resolve</button>
|
|
2631
|
+
<button class="demo-btn-sm ghost">Ignore</button>
|
|
2632
|
+
</td>
|
|
2633
|
+
</tr>
|
|
2634
|
+
<tr>
|
|
2635
|
+
<td>
|
|
2636
|
+
<a href="#" class="demo-font-mono" style="font-weight: 600;">Net::ReadTimeout</a><br>
|
|
2637
|
+
<span class="demo-text-muted demo-text-sm">Request to api.example.com timed out</span>
|
|
2638
|
+
<div style="margin-top: 0.25rem;">
|
|
2639
|
+
<span class="demo-badge demo-badge-warning">warning</span>
|
|
2640
|
+
<span class="demo-text-muted demo-text-xs" style="margin-left: 0.5rem;">production</span>
|
|
2641
|
+
</div>
|
|
2642
|
+
</td>
|
|
2643
|
+
<td><span class="demo-badge demo-badge-error">unresolved</span></td>
|
|
2644
|
+
<td><strong>23</strong></td>
|
|
2645
|
+
<td class="demo-text-muted demo-text-sm">12 minutes ago</td>
|
|
2646
|
+
<td>
|
|
2647
|
+
<button class="demo-btn-sm">Resolve</button>
|
|
2648
|
+
<button class="demo-btn-sm ghost">Ignore</button>
|
|
2649
|
+
</td>
|
|
2650
|
+
</tr>
|
|
2651
|
+
<tr>
|
|
2652
|
+
<td>
|
|
2653
|
+
<a href="#" class="demo-font-mono" style="font-weight: 600;">NoMethodError</a><br>
|
|
2654
|
+
<span class="demo-text-muted demo-text-sm">undefined method 'name' for nil</span>
|
|
2655
|
+
<div style="margin-top: 0.25rem;">
|
|
2656
|
+
<span class="demo-badge demo-badge-error">error</span>
|
|
2657
|
+
<span class="demo-text-muted demo-text-xs" style="margin-left: 0.5rem;">staging</span>
|
|
2658
|
+
</div>
|
|
2659
|
+
</td>
|
|
2660
|
+
<td><span class="demo-badge demo-badge-error">unresolved</span></td>
|
|
2661
|
+
<td><strong>8</strong></td>
|
|
2662
|
+
<td class="demo-text-muted demo-text-sm">34 minutes ago</td>
|
|
2663
|
+
<td>
|
|
2664
|
+
<button class="demo-btn-sm">Resolve</button>
|
|
2665
|
+
<button class="demo-btn-sm ghost">Ignore</button>
|
|
2666
|
+
</td>
|
|
2667
|
+
</tr>
|
|
2668
|
+
<tr>
|
|
2669
|
+
<td>
|
|
2670
|
+
<a href="#" class="demo-font-mono" style="font-weight: 600;">ActionController::ParameterMissing</a><br>
|
|
2671
|
+
<span class="demo-text-muted demo-text-sm">param is missing or the value is empty: user</span>
|
|
2672
|
+
<div style="margin-top: 0.25rem;">
|
|
2673
|
+
<span class="demo-badge demo-badge-error">error</span>
|
|
2674
|
+
<span class="demo-text-muted demo-text-xs" style="margin-left: 0.5rem;">production</span>
|
|
2675
|
+
</div>
|
|
2676
|
+
</td>
|
|
2677
|
+
<td><span class="demo-badge demo-badge-error">unresolved</span></td>
|
|
2678
|
+
<td><strong>3</strong></td>
|
|
2679
|
+
<td class="demo-text-muted demo-text-sm">1 hour ago</td>
|
|
2680
|
+
<td>
|
|
2681
|
+
<button class="demo-btn-sm">Resolve</button>
|
|
2682
|
+
<button class="demo-btn-sm ghost">Ignore</button>
|
|
2683
|
+
</td>
|
|
2684
|
+
</tr>
|
|
2685
|
+
</tbody>
|
|
2686
|
+
</table>
|
|
2687
|
+
</div>
|
|
2688
|
+
</div><!-- /demo-tab-errors -->
|
|
2689
|
+
|
|
2690
|
+
<!-- Performance Tab -->
|
|
2691
|
+
<div class="demo-tab-content" id="demo-tab-performance">
|
|
2692
|
+
<h1 class="demo-page-title">Performance</h1>
|
|
2693
|
+
|
|
2694
|
+
<!-- Time filter -->
|
|
2695
|
+
<div style="margin-bottom: 1.5rem;">
|
|
2696
|
+
<select class="demo-select"><option>Last 24 Hours</option><option>Last Hour</option><option>Last 7 Days</option><option>Last 30 Days</option></select>
|
|
2697
|
+
</div>
|
|
2698
|
+
|
|
2699
|
+
<!-- Stats Grid -->
|
|
2700
|
+
<div class="demo-stats-grid">
|
|
2701
|
+
<div class="demo-stat-card">
|
|
2702
|
+
<div class="demo-stat-label">Total Requests</div>
|
|
2703
|
+
<div class="demo-stat-value">1,847</div>
|
|
2704
|
+
</div>
|
|
2705
|
+
<div class="demo-stat-card">
|
|
2706
|
+
<div class="demo-stat-label">Avg Duration</div>
|
|
2707
|
+
<div class="demo-stat-value warning">142<span class="unit">ms</span></div>
|
|
2708
|
+
</div>
|
|
2709
|
+
<div class="demo-stat-card">
|
|
2710
|
+
<div class="demo-stat-label">Max Duration</div>
|
|
2711
|
+
<div class="demo-stat-value">1,245<span class="unit">ms</span></div>
|
|
2712
|
+
</div>
|
|
2713
|
+
<div class="demo-stat-card">
|
|
2714
|
+
<div class="demo-stat-label">N+1 Rate</div>
|
|
2715
|
+
<div class="demo-stat-value warning">12%</div>
|
|
2716
|
+
</div>
|
|
2717
|
+
</div>
|
|
2718
|
+
|
|
2719
|
+
<div class="demo-grid-2">
|
|
2720
|
+
<!-- Slowest Endpoints -->
|
|
2721
|
+
<div class="demo-card">
|
|
2722
|
+
<div class="demo-card-header">
|
|
2723
|
+
<div><h2 class="demo-card-title">Slowest Endpoints</h2></div>
|
|
2724
|
+
</div>
|
|
2725
|
+
<table class="demo-table">
|
|
2726
|
+
<thead>
|
|
2727
|
+
<tr>
|
|
2728
|
+
<th>Endpoint</th>
|
|
2729
|
+
<th>Avg</th>
|
|
2730
|
+
<th>Max</th>
|
|
2731
|
+
<th>Count</th>
|
|
2732
|
+
</tr>
|
|
2733
|
+
</thead>
|
|
2734
|
+
<tbody>
|
|
2735
|
+
<tr>
|
|
2736
|
+
<td><a href="#" class="demo-font-mono demo-text-sm">OrdersController#create</a></td>
|
|
2737
|
+
<td><span class="demo-badge demo-badge-warning">847ms</span></td>
|
|
2738
|
+
<td class="demo-text-muted demo-text-sm">1,245ms</td>
|
|
2739
|
+
<td>312</td>
|
|
2740
|
+
</tr>
|
|
2741
|
+
<tr>
|
|
2742
|
+
<td><a href="#" class="demo-font-mono demo-text-sm">ReportsController#index</a></td>
|
|
2743
|
+
<td><span class="demo-badge demo-badge-warning">623ms</span></td>
|
|
2744
|
+
<td class="demo-text-muted demo-text-sm">982ms</td>
|
|
2745
|
+
<td>156</td>
|
|
2746
|
+
</tr>
|
|
2747
|
+
<tr>
|
|
2748
|
+
<td><a href="#" class="demo-font-mono demo-text-sm">UsersController#show</a></td>
|
|
2749
|
+
<td><span class="demo-badge demo-badge-muted">156ms</span></td>
|
|
2750
|
+
<td class="demo-text-muted demo-text-sm">298ms</td>
|
|
2751
|
+
<td>847</td>
|
|
2752
|
+
</tr>
|
|
2753
|
+
<tr>
|
|
2754
|
+
<td><a href="#" class="demo-font-mono demo-text-sm">Api::V1::ProductsController#index</a></td>
|
|
2755
|
+
<td><span class="demo-badge demo-badge-muted">89ms</span></td>
|
|
2756
|
+
<td class="demo-text-muted demo-text-sm">201ms</td>
|
|
2757
|
+
<td>1,203</td>
|
|
2758
|
+
</tr>
|
|
2759
|
+
</tbody>
|
|
2760
|
+
</table>
|
|
2761
|
+
</div>
|
|
2762
|
+
|
|
2763
|
+
<!-- N+1 Hotspots -->
|
|
2764
|
+
<div class="demo-card">
|
|
2765
|
+
<div class="demo-card-header">
|
|
2766
|
+
<div><h2 class="demo-card-title">N+1 Hotspots</h2></div>
|
|
2767
|
+
</div>
|
|
2768
|
+
<table class="demo-table">
|
|
2769
|
+
<thead>
|
|
2770
|
+
<tr>
|
|
2771
|
+
<th>Endpoint</th>
|
|
2772
|
+
<th>N+1 Count</th>
|
|
2773
|
+
<th>Avg Queries</th>
|
|
2774
|
+
</tr>
|
|
2775
|
+
</thead>
|
|
2776
|
+
<tbody>
|
|
2777
|
+
<tr>
|
|
2778
|
+
<td><a href="#" class="demo-font-mono demo-text-sm">OrdersController#create</a></td>
|
|
2779
|
+
<td><span class="demo-badge demo-badge-warning">47</span></td>
|
|
2780
|
+
<td>18</td>
|
|
2781
|
+
</tr>
|
|
2782
|
+
<tr>
|
|
2783
|
+
<td><a href="#" class="demo-font-mono demo-text-sm">ReportsController#index</a></td>
|
|
2784
|
+
<td><span class="demo-badge demo-badge-warning">23</span></td>
|
|
2785
|
+
<td>12</td>
|
|
2786
|
+
</tr>
|
|
2787
|
+
<tr>
|
|
2788
|
+
<td><a href="#" class="demo-font-mono demo-text-sm">UsersController#show</a></td>
|
|
2789
|
+
<td><span class="demo-badge demo-badge-muted">5</span></td>
|
|
2790
|
+
<td>4</td>
|
|
2791
|
+
</tr>
|
|
2792
|
+
</tbody>
|
|
2793
|
+
</table>
|
|
2794
|
+
</div>
|
|
2795
|
+
</div>
|
|
2796
|
+
|
|
2797
|
+
<!-- Throughput Chart -->
|
|
2798
|
+
<div class="demo-card">
|
|
2799
|
+
<div class="demo-card-header">
|
|
2800
|
+
<div>
|
|
2801
|
+
<h2 class="demo-card-title">Throughput Over Time</h2>
|
|
2802
|
+
<p class="demo-card-description">Requests per interval</p>
|
|
2803
|
+
</div>
|
|
2804
|
+
</div>
|
|
2805
|
+
<div class="demo-chart-container">
|
|
2806
|
+
<div class="demo-chart-bar" style="height: 25%;"></div>
|
|
2807
|
+
<div class="demo-chart-bar" style="height: 18%;"></div>
|
|
2808
|
+
<div class="demo-chart-bar" style="height: 30%;"></div>
|
|
2809
|
+
<div class="demo-chart-bar" style="height: 45%;"></div>
|
|
2810
|
+
<div class="demo-chart-bar" style="height: 38%;"></div>
|
|
2811
|
+
<div class="demo-chart-bar" style="height: 52%;"></div>
|
|
2812
|
+
<div class="demo-chart-bar" style="height: 68%;"></div>
|
|
2813
|
+
<div class="demo-chart-bar" style="height: 85%;"></div>
|
|
2814
|
+
<div class="demo-chart-bar" style="height: 100%;"></div>
|
|
2815
|
+
<div class="demo-chart-bar" style="height: 92%;"></div>
|
|
2816
|
+
<div class="demo-chart-bar" style="height: 78%;"></div>
|
|
2817
|
+
<div class="demo-chart-bar" style="height: 65%;"></div>
|
|
2818
|
+
<div class="demo-chart-bar" style="height: 55%;"></div>
|
|
2819
|
+
<div class="demo-chart-bar" style="height: 48%;"></div>
|
|
2820
|
+
<div class="demo-chart-bar" style="height: 60%;"></div>
|
|
2821
|
+
<div class="demo-chart-bar" style="height: 72%;"></div>
|
|
2822
|
+
<div class="demo-chart-bar" style="height: 80%;"></div>
|
|
2823
|
+
<div class="demo-chart-bar" style="height: 75%;"></div>
|
|
2824
|
+
<div class="demo-chart-bar" style="height: 58%;"></div>
|
|
2825
|
+
<div class="demo-chart-bar" style="height: 42%;"></div>
|
|
2826
|
+
<div class="demo-chart-bar" style="height: 35%;"></div>
|
|
2827
|
+
<div class="demo-chart-bar" style="height: 28%;"></div>
|
|
2828
|
+
<div class="demo-chart-bar" style="height: 22%;"></div>
|
|
2829
|
+
<div class="demo-chart-bar" style="height: 15%;"></div>
|
|
2830
|
+
</div>
|
|
2831
|
+
<div class="demo-chart-labels">
|
|
2832
|
+
<span>00:00</span>
|
|
2833
|
+
<span>23:00</span>
|
|
2834
|
+
</div>
|
|
2835
|
+
</div>
|
|
2836
|
+
</div><!-- /demo-tab-performance -->
|
|
2837
|
+
|
|
2838
|
+
<!-- Alerts Tab -->
|
|
2839
|
+
<div class="demo-tab-content" id="demo-tab-alerts">
|
|
2840
|
+
<h1 class="demo-page-title">Alerts</h1>
|
|
2841
|
+
<p class="demo-page-description">Manage alert channels and send test notifications.</p>
|
|
2842
|
+
|
|
2843
|
+
<!-- Stats Grid -->
|
|
2844
|
+
<div class="demo-stats-grid" style="grid-template-columns: repeat(3, 1fr);">
|
|
2845
|
+
<div class="demo-stat-card">
|
|
2846
|
+
<div class="demo-stat-label">Total Channels</div>
|
|
2847
|
+
<div class="demo-stat-value" style="font-size: 1.5rem;">3</div>
|
|
2848
|
+
<div class="demo-stat-change">2 enabled</div>
|
|
2849
|
+
</div>
|
|
2850
|
+
<div class="demo-stat-card">
|
|
2851
|
+
<div class="demo-stat-label">Throttle Period</div>
|
|
2852
|
+
<div class="demo-stat-value" style="font-size: 1.5rem;">300s</div>
|
|
2853
|
+
<div class="demo-stat-change">5 minutes between alerts per error</div>
|
|
2854
|
+
</div>
|
|
2855
|
+
<div class="demo-stat-card">
|
|
2856
|
+
<div class="demo-stat-label">Alert Status</div>
|
|
2857
|
+
<div style="margin-top: 0.5rem;">
|
|
2858
|
+
<span class="demo-health-dot" style="display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50; vertical-align: middle;"></span>
|
|
2859
|
+
<span class="demo-text-sm">Active</span>
|
|
2860
|
+
</div>
|
|
2861
|
+
<div class="demo-stat-change">Alerts will be sent when errors occur</div>
|
|
2862
|
+
</div>
|
|
2863
|
+
</div>
|
|
2864
|
+
|
|
2865
|
+
<!-- Add Channel Button -->
|
|
2866
|
+
<div style="display: flex; justify-content: flex-end; margin-bottom: 1rem;">
|
|
2867
|
+
<button class="demo-btn-outline" style="gap: 0.375rem; display: inline-flex; align-items: center;">
|
|
2868
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2869
|
+
<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
|
|
2870
|
+
</svg>
|
|
2871
|
+
Add Alert Channel
|
|
2872
|
+
</button>
|
|
2873
|
+
</div>
|
|
2874
|
+
|
|
2875
|
+
<!-- Channels Table -->
|
|
2876
|
+
<div class="demo-card">
|
|
2877
|
+
<table class="demo-table">
|
|
2878
|
+
<thead>
|
|
2879
|
+
<tr>
|
|
2880
|
+
<th>Channel</th>
|
|
2881
|
+
<th>Config</th>
|
|
2882
|
+
<th style="text-align: center;">Status</th>
|
|
2883
|
+
<th style="text-align: right;">Actions</th>
|
|
2884
|
+
</tr>
|
|
2885
|
+
</thead>
|
|
2886
|
+
<tbody>
|
|
2887
|
+
<tr>
|
|
2888
|
+
<td>
|
|
2889
|
+
<strong>Production Slack</strong>
|
|
2890
|
+
<span class="demo-badge demo-badge-info" style="margin-left: 0.5rem;">Slack</span>
|
|
2891
|
+
</td>
|
|
2892
|
+
<td class="demo-text-muted demo-text-sm demo-font-mono">https://hooks.slack.com/service********</td>
|
|
2893
|
+
<td style="text-align: center;">
|
|
2894
|
+
<label class="demo-toggle">
|
|
2895
|
+
<input type="checkbox" checked>
|
|
2896
|
+
<span class="demo-toggle-slider"></span>
|
|
2897
|
+
</label>
|
|
2898
|
+
</td>
|
|
2899
|
+
<td>
|
|
2900
|
+
<div style="display: flex; gap: 0.25rem; justify-content: flex-end; align-items: center;">
|
|
2901
|
+
<button class="demo-btn-icon" title="Send test alert">
|
|
2902
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2903
|
+
<path d="M22 2 11 13"/><path d="m22 2-7 20-4-9-9-4 20-7z"/>
|
|
2904
|
+
</svg>
|
|
2905
|
+
</button>
|
|
2906
|
+
<button class="demo-btn-icon" title="Edit">
|
|
2907
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2908
|
+
<path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/>
|
|
2909
|
+
</svg>
|
|
2910
|
+
</button>
|
|
2911
|
+
<button class="demo-btn-icon" title="Delete" style="color: hsl(var(--error) / 0.7);">
|
|
2912
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2913
|
+
<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>
|
|
2914
|
+
</svg>
|
|
2915
|
+
</button>
|
|
2916
|
+
</div>
|
|
2917
|
+
</td>
|
|
2918
|
+
</tr>
|
|
2919
|
+
<tr>
|
|
2920
|
+
<td>
|
|
2921
|
+
<strong>Dev Team Email</strong>
|
|
2922
|
+
<span class="demo-badge demo-badge-info" style="margin-left: 0.5rem;">Email</span>
|
|
2923
|
+
</td>
|
|
2924
|
+
<td class="demo-text-muted demo-text-sm demo-font-mono">team@example.com, oncall@example.com</td>
|
|
2925
|
+
<td style="text-align: center;">
|
|
2926
|
+
<label class="demo-toggle">
|
|
2927
|
+
<input type="checkbox" checked>
|
|
2928
|
+
<span class="demo-toggle-slider"></span>
|
|
2929
|
+
</label>
|
|
2930
|
+
</td>
|
|
2931
|
+
<td>
|
|
2932
|
+
<div style="display: flex; gap: 0.25rem; justify-content: flex-end; align-items: center;">
|
|
2933
|
+
<button class="demo-btn-icon" title="Send test alert">
|
|
2934
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2935
|
+
<path d="M22 2 11 13"/><path d="m22 2-7 20-4-9-9-4 20-7z"/>
|
|
2936
|
+
</svg>
|
|
2937
|
+
</button>
|
|
2938
|
+
<button class="demo-btn-icon" title="Edit">
|
|
2939
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2940
|
+
<path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/>
|
|
2941
|
+
</svg>
|
|
2942
|
+
</button>
|
|
2943
|
+
<button class="demo-btn-icon" title="Delete" style="color: hsl(var(--error) / 0.7);">
|
|
2944
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2945
|
+
<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>
|
|
2946
|
+
</svg>
|
|
2947
|
+
</button>
|
|
2948
|
+
</div>
|
|
2949
|
+
</td>
|
|
2950
|
+
</tr>
|
|
2951
|
+
<tr>
|
|
2952
|
+
<td>
|
|
2953
|
+
<strong>Discord Staging</strong>
|
|
2954
|
+
<span class="demo-badge demo-badge-info" style="margin-left: 0.5rem;">Discord</span>
|
|
2955
|
+
</td>
|
|
2956
|
+
<td class="demo-text-muted demo-text-sm demo-font-mono">https://discord.com/api/web********</td>
|
|
2957
|
+
<td style="text-align: center;">
|
|
2958
|
+
<label class="demo-toggle">
|
|
2959
|
+
<input type="checkbox">
|
|
2960
|
+
<span class="demo-toggle-slider"></span>
|
|
2961
|
+
</label>
|
|
2962
|
+
</td>
|
|
2963
|
+
<td>
|
|
2964
|
+
<div style="display: flex; gap: 0.25rem; justify-content: flex-end; align-items: center;">
|
|
2965
|
+
<button class="demo-btn-icon" title="Edit">
|
|
2966
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2967
|
+
<path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/>
|
|
2968
|
+
</svg>
|
|
2969
|
+
</button>
|
|
2970
|
+
<button class="demo-btn-icon" title="Delete" style="color: hsl(var(--error) / 0.7);">
|
|
2971
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2972
|
+
<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>
|
|
2973
|
+
</svg>
|
|
2974
|
+
</button>
|
|
2975
|
+
</div>
|
|
2976
|
+
</td>
|
|
2977
|
+
</tr>
|
|
2978
|
+
</tbody>
|
|
2979
|
+
</table>
|
|
2980
|
+
</div>
|
|
2981
|
+
</div><!-- /demo-tab-alerts -->
|
|
2982
|
+
|
|
2255
2983
|
</div>
|
|
2256
2984
|
</div>
|
|
2257
2985
|
</div>
|
|
@@ -2261,12 +2989,59 @@
|
|
|
2261
2989
|
<!-- CTA Section -->
|
|
2262
2990
|
<section class="cta">
|
|
2263
2991
|
<div class="container">
|
|
2264
|
-
<
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2992
|
+
<div class="cta-box">
|
|
2993
|
+
<div class="cta-content">
|
|
2994
|
+
<h2>Own Your<br>Error Data</h2>
|
|
2995
|
+
<p>Open source, self-hosted, and forever free. Your errors, your infrastructure, your rules.</p>
|
|
2996
|
+
<a href="https://github.com/ITSSOUMIT/findbug" target="_blank" class="btn btn-primary">
|
|
2997
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
|
2998
|
+
Get Started
|
|
2999
|
+
</a>
|
|
3000
|
+
</div>
|
|
3001
|
+
<div class="cta-preview">
|
|
3002
|
+
<div class="cta-preview-window">
|
|
3003
|
+
<div class="cta-preview-titlebar">
|
|
3004
|
+
<span class="cta-preview-dot"></span>
|
|
3005
|
+
<span class="cta-preview-dot"></span>
|
|
3006
|
+
<span class="cta-preview-dot"></span>
|
|
3007
|
+
</div>
|
|
3008
|
+
<div class="cta-preview-content">
|
|
3009
|
+
<div class="cta-preview-header">
|
|
3010
|
+
<div class="cta-preview-logo">
|
|
3011
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
|
|
3012
|
+
</div>
|
|
3013
|
+
<span class="cta-preview-title">FindBug Dashboard</span>
|
|
3014
|
+
</div>
|
|
3015
|
+
<div class="cta-preview-stats">
|
|
3016
|
+
<div class="cta-stat-card">
|
|
3017
|
+
<div class="cta-stat-value">12</div>
|
|
3018
|
+
<div class="cta-stat-label">Errors</div>
|
|
3019
|
+
</div>
|
|
3020
|
+
<div class="cta-stat-card">
|
|
3021
|
+
<div class="cta-stat-value">847</div>
|
|
3022
|
+
<div class="cta-stat-label">Requests</div>
|
|
3023
|
+
</div>
|
|
3024
|
+
<div class="cta-stat-card">
|
|
3025
|
+
<div class="cta-stat-value">42ms</div>
|
|
3026
|
+
<div class="cta-stat-label">Avg Time</div>
|
|
3027
|
+
</div>
|
|
3028
|
+
</div>
|
|
3029
|
+
<div class="cta-preview-chart">
|
|
3030
|
+
<div class="cta-chart-bar" style="height: 25%;"></div>
|
|
3031
|
+
<div class="cta-chart-bar" style="height: 45%;"></div>
|
|
3032
|
+
<div class="cta-chart-bar" style="height: 30%;"></div>
|
|
3033
|
+
<div class="cta-chart-bar" style="height: 60%;"></div>
|
|
3034
|
+
<div class="cta-chart-bar" style="height: 80%;"></div>
|
|
3035
|
+
<div class="cta-chart-bar" style="height: 55%;"></div>
|
|
3036
|
+
<div class="cta-chart-bar" style="height: 70%;"></div>
|
|
3037
|
+
<div class="cta-chart-bar" style="height: 90%;"></div>
|
|
3038
|
+
<div class="cta-chart-bar" style="height: 65%;"></div>
|
|
3039
|
+
<div class="cta-chart-bar" style="height: 40%;"></div>
|
|
3040
|
+
</div>
|
|
3041
|
+
</div>
|
|
3042
|
+
</div>
|
|
3043
|
+
</div>
|
|
3044
|
+
</div>
|
|
2270
3045
|
</div>
|
|
2271
3046
|
</section>
|
|
2272
3047
|
|
|
@@ -2284,5 +3059,24 @@
|
|
|
2284
3059
|
</p>
|
|
2285
3060
|
</div>
|
|
2286
3061
|
</footer>
|
|
3062
|
+
|
|
3063
|
+
<script>
|
|
3064
|
+
function switchDemoTab(tab, navLink) {
|
|
3065
|
+
// Update nav
|
|
3066
|
+
document.querySelectorAll('.demo-app-nav a').forEach(function(a) { a.classList.remove('active'); });
|
|
3067
|
+
navLink.classList.add('active');
|
|
3068
|
+
|
|
3069
|
+
// Update content
|
|
3070
|
+
document.querySelectorAll('.demo-tab-content').forEach(function(el) { el.classList.remove('active'); });
|
|
3071
|
+
var target = document.getElementById('demo-tab-' + tab);
|
|
3072
|
+
if (target) target.classList.add('active');
|
|
3073
|
+
|
|
3074
|
+
// Update URL bar
|
|
3075
|
+
var urls = { dashboard: 'localhost:3010/findbug', errors: 'localhost:3010/findbug/errors', performance: 'localhost:3010/findbug/performance', alerts: 'localhost:3010/findbug/alerts' };
|
|
3076
|
+
var urlBar = document.querySelector('.demo-titlebar .url');
|
|
3077
|
+
if (urlBar && urls[tab]) urlBar.textContent = urls[tab];
|
|
3078
|
+
}
|
|
3079
|
+
</script>
|
|
3080
|
+
|
|
2287
3081
|
</body>
|
|
2288
3082
|
</html>
|