Host CPU, memory and load per core, container CPU and memory, and every monitor's response time learn a normal per hour (milestone 513, System 182). A reading past its fixed cutoff but within its normal reads healthy and says what is usual at this hour; one well out of it keeps its grade and is a metric anomaly. Disk, a monitor down and an agent offline keep their cutoffs. - Each normal's floor, the smallest departure that counts, is a setting: Settings -> Thresholds -> Normals (norms.floor.*). Defaults: host CPU 10 points, host memory 5, load per core 10, container CPU 10 points of one core, container memory 5, monitor response 100 ms; Traefik's 2-point 4xx and 50 ms p95 floors move there from constants. learn_normal takes a floor function (floor_setting) read at each pass. - learn_normal(parts=False): a host learns, its cores don't. - Ingest records load_pct (load_1m / cores x 100), the figure pages grade. - Shared grading: anomalies.against / graded, worst_reading(normals=), hosts' host_grades, docker usage(thresholds=, norms=), monitors' latency_grade. Applied to host vitals, the Hosts widget, MCP overview, Docker usage, and the monitor list, widget and page. - The monitor and container pages list their anomalies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
29 lines
1.6 KiB
HTML
29 lines
1.6 KiB
HTML
{#- A container's CPU and memory as service.usage() describes them (#5209).
|
|
|
|
Docker counts CPU per core (100% = one core busy), so CPU reads as cores,
|
|
toned by its share of the host's CPUs when the host's core count is known.
|
|
Memory reads in bytes, against a limit only when one is actually set;
|
|
mem_pct is then a share of that limit, otherwise of the host's memory.
|
|
Each is toned by usage()'s grade when it has one: within the container's
|
|
own normal for the hour reads healthy, and says what is usual (#5742). -#}
|
|
|
|
{% macro cores(n) -%}
|
|
{{ "%.2f"|format(n) if n < 1 else "%.1f"|format(n) }} {{ "core" if n == 1 else "cores" }}
|
|
{%- endmacro %}
|
|
|
|
{% macro cpu(u) -%}
|
|
{%- if u.cores is none -%}<span class="tone-dim">—</span>
|
|
{%- else -%}
|
|
<span class="tone-{{ u.cpu_grade or status_class(u.cpu_share, 'cpu') }}"
|
|
title="Docker counts CPU per core: {{ '%.0f'|format(u.cores * 100) }}% of one core{% if u.cpus %}, {{ '%.1f'|format(u.cpu_share) }}% of this host's {{ u.cpus }} core{{ 's' if u.cpus != 1 }}{% endif %}{% if u.cpu_usual %}; {{ u.cpu_usual }}{% endif %}">{{ cores(u.cores) }}</span>
|
|
{%- endif -%}
|
|
{%- endmacro %}
|
|
|
|
{% macro mem(u) -%}
|
|
{%- if u.mem_bytes is none -%}<span class="tone-dim">—</span>
|
|
{%- else -%}
|
|
<span class="tone-{{ u.mem_grade or (status_class(u.mem_pct, 'mem') if u.mem_of else 'dim') }}"
|
|
title="{% if u.mem_pct is not none and u.mem_of %}{{ '%.1f'|format(u.mem_pct) }}% of {{ u.mem_of }}{% if u.mem_usual %}, {{ u.mem_usual }}{% endif %}{% else %}No memory limit set{% endif %}">{{ u.mem_bytes|bytes }}{% if u.mem_limit %} / {{ u.mem_limit|bytes }}{% endif %}</span>
|
|
{%- endif -%}
|
|
{%- endmacro %}
|