369 lines
14 KiB
HTML
369 lines
14 KiB
HTML
{% macro gauge(label, pct, subtitle, value_text=None) %}
|
|
{% set p = pct if pct is not none else 0 %}
|
|
{% if p < 0 %}{% set p=0 %}{% endif %} {% if p> 100 %}{% set p = 100 %}{% endif %}
|
|
|
|
{% if p < 60 %} {% set col="#00ff88" %} {% set status="OK" %} {% elif p < 85 %} {% set col="#ffb86c" %} {% set
|
|
status="WARN" %} {% else %} {% set col="#ff5555" %} {% set status="CRIT" %} {% endif %} {% set txt=value_text if
|
|
value_text else (p|round(0)|int ~ "%" ) %} <div style="
|
|
border: 2px solid {{ col }};
|
|
background: rgba({{ '0, 255, 136' if p < 60 else ('255, 184, 108' if p < 85 else '255, 85, 85') }}, 0.05);
|
|
padding: 16px;
|
|
position: relative;
|
|
transition: all 0.3s ease;
|
|
">
|
|
<!-- Status indicator -->
|
|
<div style="
|
|
position: absolute;
|
|
top: 8px;
|
|
right: 8px;
|
|
font-size: 9px;
|
|
font-weight: 700;
|
|
letter-spacing: 1px;
|
|
color: {{ col }};
|
|
padding: 2px 6px;
|
|
border: 1px solid {{ col }};
|
|
background: rgba({{ '0, 255, 136' if p < 60 else ('255, 184, 108' if p < 85 else '255, 85, 85') }}, 0.1);
|
|
">
|
|
[{{ status }}]
|
|
</div>
|
|
|
|
<!-- Label -->
|
|
<div style="
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
letter-spacing: 2px;
|
|
color: #8b949e;
|
|
text-transform: uppercase;
|
|
margin-bottom: 8px;
|
|
">
|
|
> {{ label }}
|
|
</div>
|
|
|
|
<!-- Value -->
|
|
<div style="
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
color: {{ col }};
|
|
margin-bottom: 8px;
|
|
text-shadow: 0 0 10px rgba({{ '0, 255, 136' if p < 60 else ('255, 184, 108' if p < 85 else '255, 85, 85') }}, 0.5);
|
|
">
|
|
{{ txt }}
|
|
</div>
|
|
|
|
<!-- Subtitle -->
|
|
<div style="
|
|
font-size: 11px;
|
|
color: #8b949e;
|
|
margin-bottom: 12px;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
">
|
|
{{ subtitle }}
|
|
</div>
|
|
|
|
<!-- Progress bar -->
|
|
<div style="
|
|
height: 6px;
|
|
background: #30363d;
|
|
position: relative;
|
|
overflow: hidden;
|
|
">
|
|
<div style="
|
|
height: 100%;
|
|
width: {{ p }}%;
|
|
background: {{ col }};
|
|
box-shadow: 0 0 10px {{ col }};
|
|
transition: width 0.5s ease;
|
|
"></div>
|
|
</div>
|
|
|
|
<!-- ASCII bar representation -->
|
|
<div style="
|
|
font-size: 10px;
|
|
color: {{ col }};
|
|
margin-top: 8px;
|
|
font-family: 'JetBrains Mono', monospace;
|
|
letter-spacing: 0;
|
|
">
|
|
{% set blocks = (p / 5)|round(0)|int %}
|
|
{% set empty = 20 - blocks %}
|
|
[{% for i in range(blocks) %}█{% endfor %}{% for i in range(empty) %}░{% endfor %}]
|
|
</div>
|
|
</div>
|
|
{% endmacro %}
|
|
|
|
|
|
<h2>[ LIVE METRICS ]</h2>
|
|
<div
|
|
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin: 0 0 32px 0;">
|
|
{{ gauge("CPU", data.gauges.cpu_total_pct, "Sum of container CPU% (clamped)") }}
|
|
{{ gauge("RAM", data.gauges.ram_pct, "All containers vs host RAM", (data.gauges.ram_used_h ~ " / " ~
|
|
data.gauges.ram_total_h)) }}
|
|
{{ gauge("DOCKER_DISK", data.gauges.docker_images_pct, "Images used vs total store") }}
|
|
</div>
|
|
|
|
<h2>[ SYSTEM INFO ]</h2>
|
|
<div
|
|
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 0 0 32px 0;">
|
|
<div style="
|
|
border: 2px solid #30363d;
|
|
background: rgba(0, 217, 255, 0.02);
|
|
padding: 20px;
|
|
transition: all 0.3s ease;
|
|
" onmouseover="this.style.borderColor='#00d9ff'; this.style.boxShadow='0 0 20px rgba(0, 217, 255, 0.3)';"
|
|
onmouseout="this.style.borderColor='#30363d'; this.style.boxShadow='none';">
|
|
<div style="
|
|
color: #00d9ff;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
letter-spacing: 2px;
|
|
text-transform: uppercase;
|
|
margin-bottom: 12px;
|
|
">
|
|
[HOST]
|
|
</div>
|
|
<div style="font-size: 18px; font-weight: 700; color: #c9d1d9; margin-bottom: 8px;">
|
|
{{ data.system.name or "—" }}
|
|
</div>
|
|
<div style="color: #8b949e; font-size: 12px; line-height: 1.6;">
|
|
{{ data.system.operating_system }}<br>
|
|
Kernel: {{ data.system.kernel_version }}
|
|
</div>
|
|
</div>
|
|
|
|
<div style="
|
|
border: 2px solid #30363d;
|
|
background: rgba(0, 255, 136, 0.02);
|
|
padding: 20px;
|
|
transition: all 0.3s ease;
|
|
" onmouseover="this.style.borderColor='#00ff88'; this.style.boxShadow='0 0 20px rgba(0, 255, 136, 0.3)';"
|
|
onmouseout="this.style.borderColor='#30363d'; this.style.boxShadow='none';">
|
|
<div style="
|
|
color: #00ff88;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
letter-spacing: 2px;
|
|
text-transform: uppercase;
|
|
margin-bottom: 12px;
|
|
">
|
|
[COMPUTE]
|
|
</div>
|
|
<div style="font-size: 14px; font-weight: 600; color: #c9d1d9; margin-bottom: 6px;">
|
|
<span style="color: #00ff88; font-size: 20px; font-weight: 700;">{{ data.system.cpus or "—"
|
|
}}</span> CPUs
|
|
</div>
|
|
<div style="font-size: 14px; font-weight: 600; color: #c9d1d9;">
|
|
<span style="color: #00ff88; font-size: 20px; font-weight: 700;">{{ data.system.mem_total_h or "—"
|
|
}}</span> RAM
|
|
</div>
|
|
</div>
|
|
|
|
<div style="
|
|
border: 2px solid #30363d;
|
|
background: rgba(255, 184, 108, 0.02);
|
|
padding: 20px;
|
|
transition: all 0.3s ease;
|
|
" onmouseover="this.style.borderColor='#ffb86c'; this.style.boxShadow='0 0 20px rgba(255, 184, 108, 0.3)';"
|
|
onmouseout="this.style.borderColor='#30363d'; this.style.boxShadow='none';">
|
|
<div style="
|
|
color: #ffb86c;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
letter-spacing: 2px;
|
|
text-transform: uppercase;
|
|
margin-bottom: 12px;
|
|
">
|
|
[DOCKER]
|
|
</div>
|
|
<div style="font-size: 12px; color: #c9d1d9; margin-bottom: 6px; line-height: 1.7;">
|
|
Engine: <span style="color: #ffb86c; font-weight: 700;">{{ data.system.server_version or "—"
|
|
}}</span>
|
|
</div>
|
|
<div style="font-size: 12px; color: #c9d1d9; margin-bottom: 6px; line-height: 1.7;">
|
|
Images: <span style="color: #ffb86c; font-weight: 700;">{{ data.system.images or "—" }}</span>
|
|
</div>
|
|
<div style="font-size: 12px; color: #c9d1d9; line-height: 1.7;">
|
|
Containers: <span style="color: #00ff88; font-weight: 700;">{{ data.system.containers_running or "—"
|
|
}}</span> up / <span style="color: #8b949e; font-weight: 700;">{{ data.system.containers_stopped
|
|
or "—" }}</span> down
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h3>DOCKER DISK USAGE</h3>
|
|
<div style="overflow-x: auto; margin-bottom: 24px;">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>TYPE</th>
|
|
<th>TOTAL</th>
|
|
<th>ACTIVE</th>
|
|
<th>SIZE</th>
|
|
<th>RECLAIMABLE</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for typ, r in data.system.system_df.items() %}
|
|
<tr>
|
|
<td><span style="color: #00d9ff; font-weight: 700;">[{{ typ }}]</span></td>
|
|
<td>{{ r.total }}</td>
|
|
<td>{{ r.active }}</td>
|
|
<td>{{ r.size }}</td>
|
|
<td>{{ r.reclaimable }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div style="
|
|
font-size: 11px;
|
|
color: #8b949e;
|
|
margin-bottom: 32px;
|
|
font-weight: 500;
|
|
">
|
|
<span style="color: #00d9ff;">[TIMESTAMP]</span> {{ data.generated_at }}
|
|
</div>
|
|
|
|
{% if data.warnings %}
|
|
<div style="
|
|
margin: 24px 0;
|
|
padding: 16px 20px;
|
|
border: 2px solid #ffb86c;
|
|
background: rgba(255, 184, 108, 0.05);
|
|
position: relative;
|
|
">
|
|
<div style="
|
|
position: absolute;
|
|
top: -12px;
|
|
left: 16px;
|
|
background: #161b22;
|
|
padding: 0 8px;
|
|
color: #ffb86c;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
letter-spacing: 2px;
|
|
">
|
|
[!! WARNINGS !!]
|
|
</div>
|
|
<ul style="margin: 8px 0 0 0; padding-left: 24px; color: #ffb86c;">
|
|
{% for w in data.warnings %}
|
|
<li style="margin: 6px 0; font-size: 13px;">{{ w }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<h2>[ APPLICATIONS ]</h2>
|
|
<div style="overflow-x: auto; margin-bottom: 32px;">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>APP</th>
|
|
<th>URL</th>
|
|
<th>STATUS</th>
|
|
<th>CPU</th>
|
|
<th>RAM</th>
|
|
<th>RESTARTS</th>
|
|
<th>IMAGE</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for r in data.apps %}
|
|
<tr>
|
|
<td><span style="color: #00d9ff; font-weight: 700;">{{ r.app }}</span></td>
|
|
<td>
|
|
<a href="{{ r.url }}" style="
|
|
color: #00ff88;
|
|
text-decoration: none;
|
|
transition: all 0.2s ease;
|
|
" onmouseover="this.style.color='#00d9ff'; this.style.textShadow='0 0 10px rgba(0, 217, 255, 0.5)';"
|
|
onmouseout="this.style.color='#00ff88'; this.style.textShadow='none';">
|
|
{{ r.url }}
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<span style="
|
|
padding: 3px 8px;
|
|
background: rgba(0, 255, 136, 0.1);
|
|
color: #00ff88;
|
|
border: 1px solid #00ff88;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
letter-spacing: 1px;
|
|
">
|
|
{{ r.status }}
|
|
</span>
|
|
</td>
|
|
<td style="color: #00ff88; font-weight: 600;">{{ r.cpu or "—" }}</td>
|
|
<td style="font-size: 12px;">
|
|
{% if r.mem_used %}
|
|
{{ r.mem_used }} / {{ r.mem_limit }}
|
|
<span style="color: #00d9ff; font-weight: 700;">({{ r.mem_pct }})</span>
|
|
{% else %} — {% endif %}
|
|
</td>
|
|
<td style="
|
|
color: {% if r.restarts >= 3 %}#ff5555{% else %}#8b949e{% endif %};
|
|
font-weight: 700;
|
|
">
|
|
{{ r.restarts }}
|
|
</td>
|
|
<td style="color: #8b949e; font-size: 11px;">{{ r.image }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{% if data.infra %}
|
|
<h2>[ INFRASTRUCTURE ]</h2>
|
|
<div style="overflow-x: auto;">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>CONTAINER</th>
|
|
<th>STATUS</th>
|
|
<th>CPU</th>
|
|
<th>RAM</th>
|
|
<th>RESTARTS</th>
|
|
<th>IMAGE</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for r in data.infra %}
|
|
<tr>
|
|
<td><span style="color: #ffb86c; font-weight: 700;">{{ r.container }}</span></td>
|
|
<td>
|
|
<span style="
|
|
padding: 3px 8px;
|
|
background: rgba(0, 255, 136, 0.1);
|
|
color: #00ff88;
|
|
border: 1px solid #00ff88;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
letter-spacing: 1px;
|
|
">
|
|
{{ r.status }}
|
|
</span>
|
|
</td>
|
|
<td style="color: #00ff88; font-weight: 600;">{{ r.cpu or "—" }}</td>
|
|
<td style="font-size: 12px;">
|
|
{% if r.mem_used %}
|
|
{{ r.mem_used }} / {{ r.mem_limit }}
|
|
<span style="color: #00d9ff; font-weight: 700;">({{ r.mem_pct }})</span>
|
|
{% else %} — {% endif %}
|
|
</td>
|
|
<td style="
|
|
color: {% if r.restarts >= 3 %}#ff5555{% else %}#8b949e{% endif %};
|
|
font-weight: 700;
|
|
">
|
|
{{ r.restarts }}
|
|
</td>
|
|
<td style="color: #8b949e; font-size: 11px;">{{ r.image }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %} |