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>
75 lines
4.2 KiB
HTML
75 lines
4.2 KiB
HTML
{# plugins/syslog/templates/syslog/patterns.html — telling phrases counted in
|
|
each source's lines every minute, so an alert rule can watch them (#6001). #}
|
|
{% extends "base.html" %}
|
|
{% from "_macros.html" import crumbs, page_header, empty_state, status_badge %}
|
|
{% block title %}Patterns — Syslog — Steward{% endblock %}
|
|
{% block breadcrumb %}{{ crumbs([("Syslog", "/plugins/syslog/"), ("Patterns", "")]) }}{% endblock %}
|
|
{% block content %}
|
|
{% set admin = session.user_role == 'admin' %}
|
|
{% set can_alert = session.user_role in ('admin', 'operator') %}
|
|
{{ page_header("Patterns", (patterns|length ~ " pattern" ~ ("s" if patterns|length != 1 else "")) if patterns else none) }}
|
|
|
|
<section class="card" aria-labelledby="syslog-patterns">
|
|
<div class="host-health-head">
|
|
<h2 id="syslog-patterns" class="section-title" style="margin:0;">Counted</h2>
|
|
{% if admin %}<span class="page-actions" style="margin-left:auto;"><a href="/plugins/syslog/patterns/new" class="btn btn-sm">New pattern</a></span>{% endif %}
|
|
</div>
|
|
<p class="field-hint" style="margin:0 0 0.75rem;">Each minute, every added source's lines matching a pattern in its window are counted. Alert on a count over 0 to hear of the first match; the alert clears once the window has passed it.</p>
|
|
{% if not patterns %}
|
|
{{ empty_state("No patterns yet. Add one of the ready-made ones below, or write your own.") }}
|
|
{% else %}
|
|
<table class="table" style="width:100%;font-size:0.82rem;">
|
|
<thead><tr><th>Pattern</th><th>Matches</th><th>Window</th><th>Count now</th>{% if can_alert %}<th></th>{% endif %}</tr></thead>
|
|
<tbody>
|
|
{% for p in patterns %}
|
|
<tr>
|
|
<td>{{ p.name }}{% if not p.enabled %} {{ status_badge('paused') }}{% endif %}<div class="field-hint mono">{{ p.metric }}</div></td>
|
|
<td>
|
|
{% if p.phrases %}<span class="mono" title="{{ p.phrases|join('\n') }}">{{ p.phrases[:3]|join(" · ") }}{% if p.phrases|length > 3 %} · +{{ p.phrases|length - 3 }} more{% endif %}</span>{% endif %}
|
|
{% if p.severity %}<div class="field-hint">{{ p.severity }} and worse</div>{% endif %}
|
|
{% if p.scope %}<div class="field-hint">from {{ p.scope }} only</div>{% endif %}
|
|
</td>
|
|
<td>{{ p.window }} min</td>
|
|
<td>
|
|
{% if not p.counts %}<span class="field-hint">No added source</span>
|
|
{% else %}{% for c in p.counts %}<div><span class="{{ 'tone-crit' if c.value }}">{{ "—" if c.value is none else c.value }}</span> <span class="field-hint">{{ c.source }}</span></div>{% endfor %}{% endif %}
|
|
</td>
|
|
{% if can_alert %}
|
|
<td style="white-space:nowrap;">
|
|
{% if p.alert_resource %}<a class="btn btn-sm btn-ghost" href="/alerts/rules/new?source_module=syslog&resource_name={{ p.alert_resource|urlencode }}&metric_name={{ p.metric|urlencode }}">Alert on it</a>{% endif %}
|
|
{% if admin %}<a class="btn btn-sm btn-ghost" href="/plugins/syslog/patterns/{{ p.id }}/edit">Edit</a>
|
|
<form method="post" action="/plugins/syslog/patterns/{{ p.id }}/toggle" style="display:inline;margin:0;">{{ csrf_field() }}
|
|
<button type="submit" class="btn btn-sm btn-ghost">{{ "Pause" if p.enabled else "Resume" }}</button>
|
|
</form>{% endif %}
|
|
</td>
|
|
{% endif %}
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
</section>
|
|
|
|
{% if admin and presets %}
|
|
<section class="card" aria-labelledby="syslog-presets">
|
|
<h2 id="syslog-presets" class="section-title">Ready-made</h2>
|
|
<p class="field-hint" style="margin:0 0 0.75rem;">How NAS and Linux kernels word storage trouble. Add one, then change its phrases if your devices word it differently.</p>
|
|
<table class="table" style="width:100%;font-size:0.82rem;">
|
|
<tbody>
|
|
{% for p in presets %}
|
|
<tr>
|
|
<td>{{ p.name }}<div class="field-hint">{{ p.about }}</div></td>
|
|
<td class="mono">{{ p.phrases|join(" · ") if p.phrases else "err, crit, alert or emerg" }}</td>
|
|
<td style="white-space:nowrap;">
|
|
<form method="post" action="/plugins/syslog/patterns/preset/{{ p.key }}" style="margin:0;">{{ csrf_field() }}
|
|
<button type="submit" class="btn btn-sm">Add</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
{% endif %}
|
|
{% endblock %}
|