feat(docker): Busiest Containers shows bars of the last hours beside each figure, scaled to the row's peak with a floor (#5214)
The fill bars were a share of the host's capacity, a sliver on hosts with 80 cores. Each figure now sits beside 24 bars of the last 6 hours (1h/24h per widget), each row scaled to its own peak but never below 1 core or 1 GiB (configurable per widget), so a 0.05-core container reads flat and a bar's height means real load. One grouped date_bin query feeds them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+36
-1
@@ -201,7 +201,7 @@ WIDGET_REGISTRY: dict[str, dict] = {
|
||||
"docker_resources": {
|
||||
"key": "docker_resources",
|
||||
"label": "Docker — Busiest containers",
|
||||
"description": "The containers using the most CPU (cores, 5-minute average) and their memory",
|
||||
"description": "The containers using the most CPU and memory, with bars of the last few hours",
|
||||
"hx_url": "/plugins/docker/widget/resources",
|
||||
"detail_url": "/plugins/docker/",
|
||||
"plugin": "docker",
|
||||
@@ -218,6 +218,41 @@ WIDGET_REGISTRY: dict[str, dict] = {
|
||||
{"value": 20, "label": "20 containers"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"key": "hours",
|
||||
"label": "Bars cover",
|
||||
"type": "select",
|
||||
"default": 6,
|
||||
"options": [
|
||||
{"value": 1, "label": "Last hour"},
|
||||
{"value": 6, "label": "Last 6 hours"},
|
||||
{"value": 24, "label": "Last 24 hours"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"key": "cpu_floor",
|
||||
"label": "CPU bars scale to at least",
|
||||
"type": "select",
|
||||
"default": 1.0, # a float: the add form keeps fractions
|
||||
"options": [
|
||||
{"value": 0.5, "label": "0.5 cores"},
|
||||
{"value": 1.0, "label": "1 core"},
|
||||
{"value": 2.0, "label": "2 cores"},
|
||||
{"value": 4.0, "label": "4 cores"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"key": "mem_floor",
|
||||
"label": "Memory bars scale to at least",
|
||||
"type": "select",
|
||||
"default": 1.0, # GiB
|
||||
"options": [
|
||||
{"value": 0.25, "label": "256 MiB"},
|
||||
{"value": 1.0, "label": "1 GiB"},
|
||||
{"value": 4.0, "label": "4 GiB"},
|
||||
{"value": 16.0, "label": "16 GiB"},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"snmp_devices": {
|
||||
|
||||
@@ -409,7 +409,15 @@ body.dash-editing .widget-drawer { transform:translateY(0); }
|
||||
tone: the bar never stands without the figure it measures. */
|
||||
.w-meter { background:linear-gradient(90deg, color-mix(in srgb, currentColor 20%, transparent) var(--pct, 0%), transparent var(--pct, 0%)); border-radius:3px; }
|
||||
.w-note { font-size:0.7rem; color:var(--text-dim); margin-top:0.3rem; }
|
||||
@container (max-width: 26rem) { .w-wide-only { display:none; } }
|
||||
.w-table col.w-barcol { width:9.5rem; }
|
||||
/* Bars of a figure's recent past, inline before it (Busiest Containers, #5214):
|
||||
the row's tone, faint, with the newest bar solid. A gap is a slice with no
|
||||
samples. Heights are set per bar as a % of the row's roof. */
|
||||
.w-bars { display:inline-flex; align-items:flex-end; gap:1px; height:0.95rem; width:4.3rem; margin-right:0.45rem; vertical-align:-0.15rem; }
|
||||
.w-bars i { flex:1; min-height:1px; background:currentColor; opacity:0.4; border-radius:1px 1px 0 0; }
|
||||
.w-bars i:last-child { opacity:1; }
|
||||
.w-bars i.gap { background:none; }
|
||||
@container (max-width: 26rem) { .w-wide-only { display:none; } .w-table col.w-barcol { width:5.5rem; } }
|
||||
|
||||
|
||||
/* Time range selector */
|
||||
|
||||
Reference in New Issue
Block a user