feat(syslog): pattern alerts: telling phrases counted per source each minute for alert rules, storage-trouble presets (#6001)
A pattern (phrases, a severity, a source, a window) is counted every minute into plugin_metrics as lines_matching_<key> per added source, zero included, so an ordinary alert rule fires on a match and clears once the window passes. Each count reads only the lines stored since the last, by line id; a new or changed pattern reads its window once. Patterns page with ready-made storage-trouble presets and "Alert on it", which opens the rule form aimed at the count. Source names are kept unique, and a rename moves its counts and the rules on them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -423,9 +423,14 @@ async def _cover_choices(db, source: str, rule: AlertRule | None = None) -> dict
|
||||
@alerts_bp.get("/rules/new")
|
||||
@require_role(UserRole.operator)
|
||||
async def new_rule():
|
||||
first_source = alert_svc.source_modules()[0]
|
||||
"""The rule form, empty, or aimed at a series when a page links here with
|
||||
source_module, resource_name and metric_name (a syslog pattern's count)."""
|
||||
sources = alert_svc.source_modules()
|
||||
asked = request.args.get("source_module", "")
|
||||
first_source = asked if asked in sources else sources[0]
|
||||
async with current_app.db_sessionmaker() as db:
|
||||
ctx = {**await _cover_choices(db, first_source), **await _target(db, first_source)}
|
||||
ctx = {**await _cover_choices(db, first_source),
|
||||
**(await _target_from_args(db) if asked == first_source else await _target(db, first_source))}
|
||||
return await render_template(
|
||||
"alerts/rules_form.html",
|
||||
rule=None, **ctx,
|
||||
|
||||
@@ -203,6 +203,9 @@ ACTIONS = {
|
||||
"syslog.source_removed": "removed syslog source",
|
||||
"syslog.source_ignored": "ignored syslog sender",
|
||||
"syslog.source_offered": "offered again syslog sender",
|
||||
"syslog.pattern_added": "added syslog pattern",
|
||||
"syslog.pattern_updated": "changed syslog pattern",
|
||||
"syslog.pattern_removed": "removed syslog pattern",
|
||||
"backup.made": "sent a backup",
|
||||
"backup.failed": "tried to send a backup, which failed:",
|
||||
"backup.restored": "restored Steward from a backup",
|
||||
|
||||
@@ -28,6 +28,7 @@ KEPT: frozenset[str] = frozenset({
|
||||
"unifi_known_clients",
|
||||
# Syslog senders: which were added, under what name, and which ignored.
|
||||
"syslog_sources",
|
||||
"syslog_patterns",
|
||||
})
|
||||
|
||||
# Rows that are measurements, logs, history or in-flight work: left out.
|
||||
@@ -115,5 +116,5 @@ AREAS: tuple[tuple[str, tuple[str, ...]], ...] = (
|
||||
("Ansible", ("ansible_targets", "ansible_groups", "ansible_target_groups", "ansible_schedules")),
|
||||
("Dashboards", ("dashboards", "dashboard_widgets", "dashboard_share_tokens")),
|
||||
("Plugins", ("snmp_devices", "prometheus_targets", "prometheus_widget_templates",
|
||||
"unifi_known_clients", "syslog_sources")),
|
||||
"unifi_known_clients", "syslog_sources", "syslog_patterns")),
|
||||
)
|
||||
|
||||
@@ -376,7 +376,7 @@ SOURCES: dict[str, str] = {
|
||||
"icmp": "Ping monitors", "tcp": "TCP monitors", "dns": "DNS monitors",
|
||||
"http": "HTTP monitors", "steward": "Steward itself", "host_agent": "Host agent",
|
||||
"docker": "Docker containers", "traefik": "Traefik routers", "unifi": "UniFi",
|
||||
"snmp": "SNMP devices", "prometheus": "Prometheus targets",
|
||||
"snmp": "SNMP devices", "prometheus": "Prometheus targets", "syslog": "Syslog patterns",
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user