fix(prometheus, syslog): a target or pattern pauses with a Pause/Resume button, not an "on" tick box in its form (#6419)
CI / lint (push) Successful in 2s
CI / unit (push) Failing after 1m42s
CI / integration (push) Successful in 1m45s
CI / publish (push) Skipped

Monitors, schedules and maintenance plans already pause with a
Pause/Resume button and say "Paused" where they're listed. Prometheus
targets and syslog patterns only had a tick box inside the edit form,
so a target refused by its endpoint couldn't be stopped from its page.

- Both get a Pause/Resume button (target page and list; patterns list)
  posting to /toggle, recorded in the audit log, and a Paused badge.
- The forms lose the tick box. A new one starts running; an edit keeps
  whether it is paused.
- A target's "off" state is now "paused", in its pages and MCP tools.
  A resumed target reads "not scraped yet" until its next scrape, and its
  counter rates start over.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 17:48:31 -04:00
co-authored by Claude Opus 5.5
parent 0b787a0676
commit d20d78498e
15 changed files with 104 additions and 51 deletions
@@ -51,9 +51,6 @@
</div>
</div>
<div style="display:flex;gap:1.5rem;flex-wrap:wrap;margin-bottom:0.9rem;">
<label style="display:flex;gap:0.5rem;align-items:center;cursor:pointer;">
<input type="checkbox" name="enabled" value="on"{% if v.enabled %} checked{% endif %}> Scrape this target
</label>
<label style="display:flex;gap:0.5rem;align-items:center;cursor:pointer;">
<input type="checkbox" name="verify_tls" value="on"{% if v.verify_tls %} checked{% endif %}> Check its HTTPS certificate
</label>
@@ -23,13 +23,16 @@
{% if t.reach == 'up' %}{{ status_badge('up', 'Answering') }}
{% elif t.reach == 'down' %}{{ status_badge('down', 'Not answering') }}
{% elif t.reach == 'stale' %}{{ status_badge('stale', 'Not scraped') }}
{% elif t.reach == 'off' %}{{ status_badge('stale', 'Turned off') }}
{% elif t.reach == 'paused' %}{{ status_badge('paused') }}
{% else %}{{ status_badge('pending', 'Not scraped yet') }}{% endif %}
<h2 id="prom-{{ t.id }}" class="section-title" style="margin:0;"><a href="/plugins/prometheus/targets/{{ t.id }}">{{ t.name }}</a></h2>
<span class="field-hint mono" style="min-width:0;max-width:28rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" title="{{ t.url }}">{{ t.url }}</span>
<span class="page-actions" style="margin-left:auto;">
<a href="/plugins/prometheus/targets/{{ t.id }}" class="btn btn-sm btn-ghost">Series</a>
{% if admin %}<a href="/plugins/prometheus/targets/{{ t.id }}/edit" class="btn btn-sm btn-ghost">Edit</a>{% endif %}
{% if admin %}<a href="/plugins/prometheus/targets/{{ t.id }}/edit" class="btn btn-sm btn-ghost">Edit</a>
<form method="post" action="/plugins/prometheus/targets/{{ t.id }}/toggle">{{ csrf_field() }}
<button type="submit" class="btn btn-sm btn-ghost">{{ "Pause" if t.enabled else "Resume" }}</button>
</form>{% endif %}
</span>
</div>
@@ -38,7 +41,7 @@
<p class="field-hint" style="margin:0 0 0.6rem;">
{%- if t.ok_at %}Last answered {{ t.ok_at|ago }}.{% else %}It has never answered.{% endif %}
Tried {{ t.scraped_at|ago }}.</p>
{% elif t.reach in ('stale', 'off') %}
{% elif t.reach in ('stale', 'paused') %}
<p class="field-hint" style="margin:0 0 0.6rem;">{{ t.says }}{% if t.scraped_at %} Last scraped {{ t.scraped_at|ago }}.{% endif %}</p>
{% elif t.reach == 'pending' %}
<p class="field-hint" style="margin:0 0 0.6rem;">Not scraped yet: the first scrape runs within seconds of saving.</p>
@@ -12,7 +12,10 @@
{% block content %}
{% set admin = session.user_role == 'admin' %}
{% call page_header(target.name, target.url) %}
{% if admin %}<a href="/plugins/prometheus/targets/{{ target.id }}/edit" class="btn btn-sm btn-ghost">Edit</a>{% endif %}
{% if admin %}<a href="/plugins/prometheus/targets/{{ target.id }}/edit" class="btn btn-sm btn-ghost">Edit</a>
<form method="post" action="/plugins/prometheus/targets/{{ target.id }}/toggle">{{ csrf_field() }}
<button type="submit" class="btn btn-sm btn-ghost">{{ "Pause" if target.enabled else "Resume" }}</button>
</form>{% endif %}
{% endcall %}
<p class="page-verdict">
@@ -20,7 +23,7 @@
{% elif target.reach == 'down' %}{{ status_badge('down', 'Not answering') }} <span class="tone-crit">{{ target.says }}</span>
{% if target.ok_at %}Last answered {{ target.ok_at|ago }}; the values below are from then.{% else %}It has never answered.{% endif %}
{% elif target.reach == 'stale' %}{{ status_badge('stale', 'Not scraped') }} {{ target.says }}
{% elif target.reach == 'off' %}{{ status_badge('stale', 'Turned off') }} {{ target.says }}
{% elif target.reach == 'paused' %}{{ status_badge('paused') }} {{ target.says }}
{% else %}{{ status_badge('pending', 'Not scraped yet') }} The first scrape runs within seconds of saving.{% endif %}
</p>
{% if target.capped %}