Add group_alerts setting for per-run summary notifications
Allow choosing between one alert per item (default) and one grouped summary alert per run when any items need attention via general.group_alerts.
This commit is contained in:
parent
73b6d38113
commit
674d0df703
4 changed files with 27 additions and 1 deletions
|
|
@ -59,6 +59,7 @@ There are two config files. Both are ignored by git, so your values stay on your
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `general.realert_hours` | `12` | Hours before an open item is alerted again. `0` turns repeats off. |
|
| `general.realert_hours` | `12` | Hours before an open item is alerted again. `0` turns repeats off. |
|
||||||
| `general.notify_cleared` | `true` | Send a message when an item is cleared. |
|
| `general.notify_cleared` | `true` | Send a message when an item is cleared. |
|
||||||
|
| `general.group_alerts` | `false` | `false`: one alert per item. `true`: one summary alert per run when anything needs attention. |
|
||||||
| `general.request_timeout` | `15` | Seconds to wait for each HTTP request. |
|
| `general.request_timeout` | `15` | Seconds to wait for each HTTP request. |
|
||||||
| `general.state_file` | `state.db` | Where the alert history is stored. |
|
| `general.state_file` | `state.db` | Where the alert history is stored. |
|
||||||
| `general.notifiers` | `["fluxer"]` | Notifiers to use. |
|
| `general.notifiers` | `["fluxer"]` | Notifiers to use. |
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ realert_hours = 12
|
||||||
# Send a message when an item is no longer open (cleared in the admin UI).
|
# Send a message when an item is no longer open (cleared in the admin UI).
|
||||||
notify_cleared = true
|
notify_cleared = true
|
||||||
|
|
||||||
|
# Send one alert per item (false) or one summary alert per run when anything needs attention (true).
|
||||||
|
group_alerts = false
|
||||||
|
|
||||||
# Timeout in seconds for each request to the Fluxer API or webhook.
|
# Timeout in seconds for each request to the Fluxer API or webhook.
|
||||||
request_timeout = 15
|
request_timeout = 15
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ class Settings:
|
||||||
request_timeout: float
|
request_timeout: float
|
||||||
realert: timedelta | None
|
realert: timedelta | None
|
||||||
notify_cleared: bool
|
notify_cleared: bool
|
||||||
|
group_alerts: bool
|
||||||
state_file: Path
|
state_file: Path
|
||||||
notifiers: tuple[str, ...]
|
notifiers: tuple[str, ...]
|
||||||
fluxer_webhook_url: str | None
|
fluxer_webhook_url: str | None
|
||||||
|
|
@ -90,6 +91,7 @@ def load_settings(config_path: Path) -> Settings:
|
||||||
request_timeout=float(general.get("request_timeout", 15)),
|
request_timeout=float(general.get("request_timeout", 15)),
|
||||||
realert=timedelta(hours=realert_hours) if realert_hours > 0 else None,
|
realert=timedelta(hours=realert_hours) if realert_hours > 0 else None,
|
||||||
notify_cleared=bool(general.get("notify_cleared", True)),
|
notify_cleared=bool(general.get("notify_cleared", True)),
|
||||||
|
group_alerts=bool(general.get("group_alerts", False)),
|
||||||
state_file=PROJECT_ROOT / str(general.get("state_file", "state.db")),
|
state_file=PROJECT_ROOT / str(general.get("state_file", "state.db")),
|
||||||
notifiers=notifiers,
|
notifiers=notifiers,
|
||||||
fluxer_webhook_url=fluxer_webhook_url,
|
fluxer_webhook_url=fluxer_webhook_url,
|
||||||
|
|
|
||||||
22
runner.py
22
runner.py
|
|
@ -30,6 +30,23 @@ def _to_message(notice: Notice, admin_ui_url: str) -> Message:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _group_messages(notices: list[Notice], admin_ui_url: str) -> list[Message]:
|
||||||
|
if not notices:
|
||||||
|
return []
|
||||||
|
lines: list[str] = []
|
||||||
|
urgent = False
|
||||||
|
for notice in notices:
|
||||||
|
label = KIND_PREFIX[notice.kind]
|
||||||
|
detail = notice.detail.replace("\n", " / ")
|
||||||
|
lines.append(f"{label}: {notice.title} - {detail}")
|
||||||
|
urgent = urgent or notice.urgent
|
||||||
|
title = f"Admin alerts: {len(notices)} item{'s' if len(notices) != 1 else ''} need attention"
|
||||||
|
body = "\n".join(lines)
|
||||||
|
if len(body) > 4000:
|
||||||
|
body = body[:3997] + "..."
|
||||||
|
return [Message(title=title, body=body, link=admin_ui_url, urgent=urgent)]
|
||||||
|
|
||||||
|
|
||||||
def run(settings: Settings, dry_run: bool = False) -> int:
|
def run(settings: Settings, dry_run: bool = False) -> int:
|
||||||
api = FluxerAPI(settings.api_url, settings.api_key, settings.request_timeout)
|
api = FluxerAPI(settings.api_url, settings.api_key, settings.request_timeout)
|
||||||
now = datetime.now(timezone.utc)
|
now = datetime.now(timezone.utc)
|
||||||
|
|
@ -57,7 +74,10 @@ def run(settings: Settings, dry_run: bool = False) -> int:
|
||||||
try:
|
try:
|
||||||
known = store.load()
|
known = store.load()
|
||||||
plan = decide(now, seen, known, checked, settings.realert, settings.notify_cleared)
|
plan = decide(now, seen, known, checked, settings.realert, settings.notify_cleared)
|
||||||
messages = [_to_message(n, settings.admin_ui_url) for n in plan.notices]
|
if settings.group_alerts:
|
||||||
|
messages = _group_messages(plan.notices, settings.admin_ui_url)
|
||||||
|
else:
|
||||||
|
messages = [_to_message(n, settings.admin_ui_url) for n in plan.notices]
|
||||||
|
|
||||||
if dry_run:
|
if dry_run:
|
||||||
for message in messages:
|
for message in messages:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue