productionalizing?

This commit is contained in:
2026-02-11 17:12:00 -06:00
parent 99bf0f6c5f
commit a7635c62d3
6 changed files with 328 additions and 359 deletions

View File

@@ -104,11 +104,30 @@ strong {
color: #ecebeb;
}
p, li {
ul {
margin: 0;
padding-left: 1.5em;
color: #a8a8a8;
}
li {
margin-bottom: 0.5em;
color: #a8a8a8;
}
strong {
color: #ecebeb;
}
p, li, span {
color: rgb(212, 212, 212);
font-size: 1rem;
}
span {
font-size: .8rem;
}
a, a p {
color: #a0a0a0a0;
text-decoration: none;
@@ -1297,20 +1316,116 @@ tr {
font-size: 1rem;
}
.status-info {
/* Overall Status Bar */
/* Overall Status Bar */
.overall-status-bar {
background: rgba(24, 24, 24, 0.95);
border-radius: 0.5em;
padding: 2em;
margin-bottom: 2em;
border-top: solid 4px rgba(139, 36, 36, 0.5);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
transition: border-color 0.5s ease;
}
.overall-status-bar.all-operational {
border-top-color: rgba(76, 175, 80, 0.8);
}
.overall-status-bar.partial-outage {
border-top-color: rgba(255, 193, 7, 0.8);
}
.overall-status-bar.major-outage {
border-top-color: rgba(244, 67, 54, 0.8);
}
.overall-status-content {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2em;
padding: 1em;
background: rgba(24, 24, 24, 0.85);
border-radius: 0.5em;
border: solid 2px rgba(139, 36, 36, 0.5);
flex-wrap: wrap;
gap: 2em;
}
.status-info span {
.overall-status-indicator {
display: flex;
align-items: center;
gap: 1.5em;
}
.overall-status-icon {
font-size: 3rem;
line-height: 1;
animation: spin 2s linear infinite;
}
.overall-status-icon.operational {
color: #4caf50;
animation: none;
}
.overall-status-icon.partial {
color: #ffc107;
animation: pulse-icon 1.5s ease-in-out infinite;
}
.overall-status-icon.major {
color: #f44336;
animation: none;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes pulse-icon {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.overall-status-title {
margin: 0;
font-size: 1.5rem;
color: #ecebeb;
font-weight: 600;
}
.overall-status-subtitle {
margin: 0.3em 0 0 0;
font-size: 1rem;
color: #a8a8a8;
font-size: 0.9rem;
}
.overall-status-metrics {
display: flex;
gap: 2em;
}
.metric-box {
display: flex;
flex-direction: column;
align-items: center;
padding: 1em 1.5em;
background: rgba(0, 0, 0, 0.3);
border-radius: 0.5em;
min-width: 80px;
}
.metric-number {
font-size: 2rem;
font-weight: bold;
color: #ecebeb;
line-height: 1;
}
.metric-label {
font-size: 0.85rem;
color: #a8a8a8;
margin-top: 0.3em;
text-transform: uppercase;
letter-spacing: 0.5px;
}
#refreshBtn {
@@ -1504,35 +1619,28 @@ tr {
}
.uptime-values strong {
color: #4caf50;
font-weight: 600;
}
.status-info-box {
background: rgba(24, 24, 24, 0.85);
border-radius: 0.5em;
padding: 1.5em;
border: solid 2px rgba(139, 36, 36, 0.5);
margin-top: 2em;
/* Uptime color coding based on percentage */
.uptime-excellent {
color: #4caf50 !important; /* 99%+ - Green */
}
.status-info-box h4 {
margin-top: 0;
color: #ecebeb;
.uptime-good {
color: #8bc34a !important; /* 95-99% - Light green */
}
.status-info-box ul {
margin: 0;
padding-left: 1.5em;
color: #a8a8a8;
.uptime-fair {
color: #ffc107 !important; /* 90-95% - Yellow */
}
.status-info-box li {
margin-bottom: 0.5em;
color: #a8a8a8;
.uptime-poor {
color: #f44336 !important; /* <90% - Red */
}
.status-info-box strong {
color: #ecebeb;
.uptime-none {
color: #888 !important; /* No data - Gray */
}
@media screen and (max-width: 1400px) {
@@ -1549,4 +1657,19 @@ tr {
flex-direction: column;
gap: 0.5em;
}
.overall-status-content {
flex-direction: column;
text-align: center;
}
.overall-status-indicator {
flex-direction: column;
text-align: center;
}
.overall-status-metrics {
width: 100%;
justify-content: center;
}
}

View File

@@ -43,6 +43,9 @@ function updateStatusDisplay(data) {
updateServiceCard(service);
});
// Update overall status
updateOverallStatus(data.services);
// Re-enable refresh button
const refreshBtn = document.getElementById('refreshBtn');
if (refreshBtn) {
@@ -109,24 +112,29 @@ function updateServiceCard(service) {
if (uptimeDisplay && service.uptime) {
const uptimeHTML = [];
if (service.uptime['24h'] !== null) {
uptimeHTML.push(`24h: <strong>${service.uptime['24h']}%</strong>`);
}
if (service.uptime['7d'] !== null) {
uptimeHTML.push(`7d: <strong>${service.uptime['7d']}%</strong>`);
}
if (service.uptime['30d'] !== null) {
uptimeHTML.push(`30d: <strong>${service.uptime['30d']}%</strong>`);
}
if (service.uptime.all_time !== null) {
uptimeHTML.push(`All: <strong>${service.uptime.all_time}%</strong>`);
}
// Helper function to get color class based on uptime percentage
const getUptimeClass = (value) => {
if (value === null) return 'uptime-none';
if (value >= 99) return 'uptime-excellent';
if (value >= 95) return 'uptime-good';
if (value >= 90) return 'uptime-fair';
return 'uptime-poor';
};
if (uptimeHTML.length > 0) {
uptimeDisplay.innerHTML = uptimeHTML.join(' | ');
} else {
uptimeDisplay.textContent = 'No data yet';
}
// Helper function to format uptime value
const formatUptime = (value, label) => {
const display = value !== null ? `${value}%` : '--';
const colorClass = getUptimeClass(value);
return `${label}: <strong class="${colorClass}">${display}</strong>`;
};
// Add all uptime metrics
uptimeHTML.push(formatUptime(service.uptime['24h'], '24h'));
uptimeHTML.push(formatUptime(service.uptime['7d'], '7d'));
uptimeHTML.push(formatUptime(service.uptime['30d'], '30d'));
uptimeHTML.push(formatUptime(service.uptime.all_time, 'All'));
uptimeDisplay.innerHTML = uptimeHTML.join(' | ');
}
// Update total checks
@@ -135,6 +143,68 @@ function updateServiceCard(service) {
}
}
/**
* Update overall status bar
*/
function updateOverallStatus(services) {
const overallBar = document.getElementById('overallStatus');
const icon = overallBar.querySelector('.overall-status-icon');
const title = overallBar.querySelector('.overall-status-title');
const subtitle = overallBar.querySelector('.overall-status-subtitle');
const onlineCount = document.getElementById('onlineCount');
const totalCount = document.getElementById('totalCount');
// Count service statuses
const total = services.length;
const online = services.filter(s => s.status === 'online').length;
const degraded = services.filter(s => s.status === 'degraded' || s.status === 'timeout').length;
const offline = services.filter(s => s.status === 'offline').length;
// Update counts
onlineCount.textContent = online;
totalCount.textContent = total;
// Remove all status classes
overallBar.classList.remove('all-operational', 'partial-outage', 'major-outage');
icon.classList.remove('operational', 'partial', 'major', 'loading');
// Determine overall status
if (online === total) {
// All systems operational
overallBar.classList.add('all-operational');
icon.classList.add('operational');
icon.textContent = '✓';
title.textContent = 'All Systems Operational';
subtitle.textContent = `All ${total} services are running normally`;
} else if (offline >= Math.ceil(total / 2)) {
// Major outage (50% or more offline)
overallBar.classList.add('major-outage');
icon.classList.add('major');
icon.textContent = '✕';
title.textContent = 'Major Outage';
subtitle.textContent = `${offline} service${offline !== 1 ? 's' : ''} offline, ${degraded} degraded`;
} else if (offline > 0 || degraded > 0) {
// Partial outage
overallBar.classList.add('partial-outage');
icon.classList.add('partial');
icon.textContent = '⚠';
title.textContent = 'Partial Outage';
if (offline > 0 && degraded > 0) {
subtitle.textContent = `${offline} offline, ${degraded} degraded`;
} else if (offline > 0) {
subtitle.textContent = `${offline} service${offline !== 1 ? 's' : ''} offline`;
} else {
subtitle.textContent = `${degraded} service${degraded !== 1 ? 's' : ''} degraded`;
}
} else {
// Unknown state
icon.classList.add('loading');
icon.textContent = '◐';
title.textContent = 'Status Unknown';
subtitle.textContent = 'Waiting for service data';
}
}
/**
* Show error message
*/

View File

@@ -1,145 +0,0 @@
{
"last_check": "2026-02-11T14:53:09.045018",
"services": {
"main": {
"name": "asimonson.com",
"url": "https://asimonson.com",
"status": "online",
"response_time": 170,
"status_code": 200,
"last_online": "2026-02-11T14:53:08.089141",
"checks": [
{
"timestamp": "2026-02-11T14:45:35.008804",
"status": "online",
"response_time": 171,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:51:02.673733",
"status": "online",
"response_time": 138,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:53:08.089141",
"status": "online",
"response_time": 170,
"status_code": 200
}
]
},
"files": {
"name": "files.asimonson.com",
"url": "https://files.asimonson.com",
"status": "online",
"response_time": 215,
"status_code": 200,
"last_online": "2026-02-11T14:53:08.259522",
"checks": [
{
"timestamp": "2026-02-11T14:45:35.180195",
"status": "online",
"response_time": 285,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:51:02.812769",
"status": "online",
"response_time": 259,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:53:08.259522",
"status": "online",
"response_time": 215,
"status_code": 200
}
]
},
"git": {
"name": "git.asimonson.com",
"url": "https://git.asimonson.com",
"status": "online",
"response_time": 145,
"status_code": 200,
"last_online": "2026-02-11T14:53:08.475376",
"checks": [
{
"timestamp": "2026-02-11T14:45:35.465748",
"status": "online",
"response_time": 297,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:51:03.072293",
"status": "online",
"response_time": 293,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:53:08.475376",
"status": "online",
"response_time": 145,
"status_code": 200
}
]
},
"pass": {
"name": "pass.asimonson.com",
"url": "https://pass.asimonson.com",
"status": "online",
"response_time": 160,
"status_code": 200,
"last_online": "2026-02-11T14:53:08.621016",
"checks": [
{
"timestamp": "2026-02-11T14:45:35.763775",
"status": "online",
"response_time": 253,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:51:03.365544",
"status": "online",
"response_time": 228,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:53:08.621016",
"status": "online",
"response_time": 160,
"status_code": 200
}
]
},
"ssh": {
"name": "ssh.asimonson.com",
"url": "https://ssh.asimonson.com",
"status": "online",
"response_time": 263,
"status_code": 200,
"last_online": "2026-02-11T14:53:08.781704",
"checks": [
{
"timestamp": "2026-02-11T14:45:36.017180",
"status": "online",
"response_time": 378,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:51:03.594307",
"status": "online",
"response_time": 411,
"status_code": 200
},
{
"timestamp": "2026-02-11T14:53:08.781704",
"status": "online",
"response_time": 263,
"status_code": 200
}
]
}
}
}