Added EonaCat.LogStack.Status
Updated EonaCat.LogStack.LogClient to support EonaCat.LogStack.Status
This commit is contained in:
162
EonaCat.LogStack.Status/Pages/Index.cshtml
Normal file
162
EonaCat.LogStack.Status/Pages/Index.cshtml
Normal file
@@ -0,0 +1,162 @@
|
||||
@page
|
||||
@model IndexModel
|
||||
@{
|
||||
ViewData["Title"] = "Dashboard";
|
||||
ViewData["Page"] = "dashboard";
|
||||
}
|
||||
<div data-autorefresh="true">
|
||||
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card @(Model.Stats.DownCount > 0 ? "down" : Model.Stats.UpCount > 0 ? "up" : "neutral")">
|
||||
<div class="stat-label">Overall</div>
|
||||
<div class="stat-value" style="font-size:22px">
|
||||
@if (Model.Stats.DownCount > 0) { <span style="color:var(--down)">DEGRADED</span> }
|
||||
else if (Model.Stats.WarnCount > 0) { <span style="color:var(--warn)">WARNING</span> }
|
||||
else if (Model.Stats.UpCount > 0) { <span style="color:var(--up)">OPERATIONAL</span> }
|
||||
else { <span style="color:var(--unknown)">UNKNOWN</span> }
|
||||
</div>
|
||||
<div class="stat-sub">@Model.Stats.TotalMonitors monitor(s) active</div>
|
||||
</div>
|
||||
<div class="stat-card up">
|
||||
<div class="stat-label">Online</div>
|
||||
<div class="stat-value">@Model.Stats.UpCount</div>
|
||||
<div class="stat-sub">monitors up</div>
|
||||
</div>
|
||||
<div class="stat-card down">
|
||||
<div class="stat-label">Offline</div>
|
||||
<div class="stat-value">@Model.Stats.DownCount</div>
|
||||
<div class="stat-sub">monitors down</div>
|
||||
</div>
|
||||
<div class="stat-card warn">
|
||||
<div class="stat-label">Warnings</div>
|
||||
<div class="stat-value">@Model.Stats.WarnCount</div>
|
||||
<div class="stat-sub">monitors degraded</div>
|
||||
</div>
|
||||
@if (Model.ShowUptime)
|
||||
{
|
||||
<div class="stat-card info">
|
||||
<div class="stat-label">Uptime</div>
|
||||
<div class="stat-value">@Model.Stats.OverallUptime.ToString("F1")%</div>
|
||||
<div class="stat-sub">overall availability</div>
|
||||
</div>
|
||||
}
|
||||
<div class="stat-card @(Model.Stats.CertExpired > 0 ? "down" : Model.Stats.CertExpiringSoon > 0 ? "warn" : "neutral")">
|
||||
<div class="stat-label">Certificates</div>
|
||||
<div class="stat-value">@Model.Stats.CertCount</div>
|
||||
<div class="stat-sub">
|
||||
@if (Model.Stats.CertExpired > 0) { <span class="text-down">@Model.Stats.CertExpired expired</span> }
|
||||
else if (Model.Stats.CertExpiringSoon > 0) { <span class="text-warn">@Model.Stats.CertExpiringSoon expiring soon</span> }
|
||||
else { <span>all valid</span> }
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.IsAdmin)
|
||||
{
|
||||
<div class="stat-card @(Model.Stats.ErrorLogs > 0 ? "warn" : "neutral")">
|
||||
<div class="stat-label">Log Errors</div>
|
||||
<div class="stat-value">@Model.Stats.ErrorLogs</div>
|
||||
<div class="stat-sub">@Model.Stats.TotalLogs total entries</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (Model.Monitors.Any())
|
||||
{
|
||||
var groups = Model.Monitors.GroupBy(m => m.GroupName ?? "General");
|
||||
foreach (var group in groups)
|
||||
{
|
||||
<div class="card mb-2 mt-2">
|
||||
<div class="card-header">
|
||||
<span class="card-title">@group.Key</span>
|
||||
<span class="mono" style="font-size:11px;color:var(--text-muted)">@group.Count() services</span>
|
||||
</div>
|
||||
<div style="padding: 8px;">
|
||||
@foreach (var m in group)
|
||||
{
|
||||
var badgeClass = m.LastStatus switch {
|
||||
MonitorStatus.Up => "badge-up",
|
||||
MonitorStatus.Down => "badge-down",
|
||||
MonitorStatus.Warning or MonitorStatus.Degraded => "badge-warn",
|
||||
_ => "badge-unknown"
|
||||
};
|
||||
var checks = Model.RecentChecks.ContainsKey(m.Id) ? Model.RecentChecks[m.Id] : new();
|
||||
<div class="monitor-row">
|
||||
<div>
|
||||
<div class="monitor-name">@m.Name
|
||||
@if (!m.IsPublic && Model.IsAdmin) { <span class="badge badge-info" style="font-size:8px;padding:1px 5px">PRIVATE</span> }
|
||||
</div>
|
||||
<div class="monitor-host">@(m.Url ?? (m.Host + (m.Port.HasValue ? ":" + m.Port : "")))</div>
|
||||
</div>
|
||||
<div class="monitor-type">@m.Type.ToString().ToUpper()</div>
|
||||
<div>
|
||||
@if (Model.ShowUptime && checks.Any())
|
||||
{
|
||||
<div class="uptime-bar" title="Last 7 days">
|
||||
@foreach (var c in checks)
|
||||
{
|
||||
var cls = c.Status switch { MonitorStatus.Up => "up", MonitorStatus.Down => "down", MonitorStatus.Warning or MonitorStatus.Degraded => "warn", _ => "unknown" };
|
||||
<div class="uptime-block @cls" title="@c.CheckedAt.ToString("g"): @c.Status"></div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="monitor-latency">
|
||||
@if (m.LastResponseMs.HasValue) { <span>@((int)m.LastResponseMs.Value)ms</span> }
|
||||
</div>
|
||||
<div><span class="badge @badgeClass">@m.LastStatus</span></div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="empty-state">
|
||||
<div class="empty-state-icon">◎</div>
|
||||
<div class="empty-state-text">No monitors have been configured</div>
|
||||
@if (Model.IsAdmin) { <div class="mt-2"><a href="/admin/monitors" class="btn btn-primary">Add Monitor</a></div> }
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Model.Certificates.Any())
|
||||
{
|
||||
<div class="card mt-2">
|
||||
<div class="card-header">
|
||||
<span class="card-title">SSL Certificates</span>
|
||||
</div>
|
||||
<div style="padding: 0 4px;">
|
||||
<table class="data-table">
|
||||
<thead><tr>
|
||||
<th>Domain</th>
|
||||
<th>Name</th>
|
||||
<th>Expires</th>
|
||||
<th>Days Left</th>
|
||||
<th>Status</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
@foreach (var c in Model.Certificates)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var daysLeft = c.ExpiresAt.HasValue ? (int)(c.ExpiresAt.Value - now).TotalDays : (int?)null;
|
||||
var expiryClass = daysLeft == null ? "" : daysLeft <= 0 ? "cert-expiry-expired" : daysLeft <= 7 ? "cert-expiry-critical" : daysLeft <= 30 ? "cert-expiry-warn" : "cert-expiry-ok";
|
||||
<tr>
|
||||
<td class="mono" style="color:var(--text-primary)">@c.Domain:@c.Port</td>
|
||||
<td>@c.Name</td>
|
||||
<td class="mono @expiryClass">@(c.ExpiresAt?.ToString("yyyy-MM-dd") ?? "unknown")</td>
|
||||
<td class="mono @expiryClass">@(daysLeft.HasValue ? daysLeft + "d" : "—")</td>
|
||||
<td>
|
||||
@if (daysLeft == null) { <span class="badge badge-unknown">Unknown</span> }
|
||||
else if (daysLeft <= 0) { <span class="badge badge-down">EXPIRED</span> }
|
||||
else if (daysLeft <= 7) { <span class="badge badge-down">CRITICAL</span> }
|
||||
else if (daysLeft <= 30) { <span class="badge badge-warn">EXPIRING</span> }
|
||||
else { <span class="badge badge-up">VALID</span> }
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
Reference in New Issue
Block a user