#5691 "Generic Prometheus dashboard widget: pick a target and a template", step 3 of milestone 508 "Prometheus widget templates". - /plugins/prometheus/widget draws one target with one template in widget shape: the verdict (led by "isn't answering" when the target is down), then each block with problems first, figures beside a share bar or the last 24h of bars, and the healthy rest folding to "+N more healthy" past six. A missing target or template, or one that no longer checks, says so. - library.py: bundled templates from plugins/prometheus/widgets/*.yaml, the picker's target and template lists, and the default title. - widgets/fabled_archives.yaml: the first bundled template, against the series Archives reports (refined in #5693). - Dashboard: a widget setting may take `options_from` (read when the picker opens) with an `empty` sentence; `default_title`; a Details link may name settings ("/plugins/prometheus/targets/{target}"). Prometheus is grouped with the integrations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
71 lines
3.5 KiB
HTML
71 lines
3.5 KiB
HTML
{# prometheus/widget.html — the Prometheus dashboard widget (#5691): one
|
|
target drawn by one template (template_view.render). A verdict naming the
|
|
worst thing, then each block: its problems first with why, figures in their
|
|
units beside a bar or the last day's bars, and the healthy rest packed after,
|
|
past REST rows as "+N more healthy". #}
|
|
{% from "_macros.html" import status_dot %}
|
|
{% set REST = 6 %}
|
|
{% set dot = {"crit": "crit", "warn": "warn", "ok": "ok", "dim": "paused"} %}
|
|
{% set tone = {"crit": "tone-crit", "warn": "tone-warn", "ok": "tone-ok", "dim": "tone-dim"} %}
|
|
{% macro shown(v) -%}
|
|
{%- if v.moment %}{{ v.moment|ago }}{% elif v.text %}{{ v.text }}{% else %}—{% endif -%}
|
|
{%- endmacro %}
|
|
{% if problem %}
|
|
<div class="w-verdict tone-warn">{{ problem }}</div>
|
|
{% else %}
|
|
{% set down = target.reach in ("down", "stale") %}
|
|
<div class="w-verdict {{ 'tone-crit' if target.reach == 'down' else tone[view.tone] }}">
|
|
{%- if target.reach == "down" %}{{ target.name }} isn't answering{% elif down %}{{ target.name }} isn't being scraped{% endif %}
|
|
{%- if down %}{% if target.ok_at %}; these values are from {{ target.ok_at|ago }}{% endif %}. {% endif -%}
|
|
{{ view.verdict }}
|
|
</div>
|
|
{% for b in view.blocks %}
|
|
<div class="w-section">{{ b.title }}</div>
|
|
{% if b.note %}
|
|
<div class="w-note tone-warn">{{ b.note }}</div>
|
|
{% elif b.kind == "info" %}
|
|
<div class="w-note">{% for r in b.rows %}{{ r.name }}{% if not loop.last %}; {% endif %}{% endfor %}</div>
|
|
{% elif b.kind == "table" %}
|
|
<table class="w-table">
|
|
<thead><tr><th></th>{% for c in b.columns %}<th>{{ c }}</th>{% endfor %}</tr></thead>
|
|
<tbody>
|
|
{% for r in b.rows %}
|
|
<tr><td class="w-name" title="{{ r.name }}">{{ r.name }}</td>{% for c in r.cells %}<td>{{ shown(c) }}</td>{% endfor %}</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
{% set problems = b.rows | selectattr("tone", "in", ["crit", "warn"]) | list %}
|
|
{% set rest = b.rows | rejectattr("tone", "in", ["crit", "warn"]) | list %}
|
|
{% set listed = problems + rest[:REST] %}
|
|
<table class="w-table">
|
|
{% if b.columns %}<thead><tr><th></th><th>Now</th>{% for c in b.columns %}<th class="w-wide-only">{{ c }}</th>{% endfor %}</tr></thead>{% endif %}
|
|
<tbody>
|
|
{% for r in listed %}
|
|
<tr>
|
|
<td class="w-name" title="{{ r.name }}">
|
|
{{- status_dot(dot[r.tone]) -}}
|
|
{{ r.name }}
|
|
{%- if r.why %}<span class="w-sub {{ tone[r.tone] }}">{{ r.why }}</span>{% endif %}
|
|
</td>
|
|
<td class="{{ tone[r.tone] if r.tone in ('crit', 'warn') }}">
|
|
{%- if r.history %}<span class="w-bars w-wide-only" aria-hidden="true" title="The last {{ spark_hours }}h, scaled to its own peak">
|
|
{%- for h in r.history %}<i style="height:{{ [h, 4]|max }}%"></i>{% endfor -%}
|
|
</span>{% endif -%}
|
|
{{ shown(r) }}
|
|
{%- if r.bar is not none %}<div class="meter w-wide-only" title="{{ (r.bar * 100)|round|int }}%"><div class="meter-fill meter-{{ r.tone if r.tone in ('crit', 'warn') else 'ok' }}" style="width:{{ (r.bar * 100)|round(1) }}%"></div></div>{% endif -%}
|
|
</td>
|
|
{% for c in r.cells %}<td class="w-wide-only">{{ shown(c) }}</td>{% endfor %}
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% if rest|length > REST %}<div class="w-more">+{{ rest|length - REST }} more healthy</div>{% endif %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
<div class="w-note">
|
|
{%- if session.user_id %}<a href="/plugins/prometheus/targets/{{ target.id }}">{{ target.name }}</a>{% else %}{{ target.name }}{% endif %}
|
|
{%- if target.scraped_at %}, scraped {{ target.scraped_at|ago }}{% endif %}.
|
|
</div>
|
|
{% endif %}
|