Source code for kstlib.alerts.models
"""Data models for the alerts module.
This module defines the core data structures for alert messages, levels,
and delivery results.
Examples:
Creating an alert message::
from kstlib.alerts.models import AlertLevel, AlertMessage
alert = AlertMessage(
title="Server Down",
body="Production server api-1 is not responding",
level=AlertLevel.CRITICAL,
)
Checking alert results::
from kstlib.alerts.models import AlertResult
result = AlertResult(channel="slack", success=True, message_id="12345")
if result.success:
print(f"Alert delivered: {result.message_id}")
"""
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timezone
from enum import IntEnum
[docs]
class AlertLevel(IntEnum):
"""Severity level for alerts.
Values are ordered by severity (higher value = more severe).
Use these to filter which alerts go to which channels.
Attributes:
INFO: Informational messages (10).
SUCCESS: Positive confirmation messages (11).
WARNING: Warning conditions that need attention (20).
CRITICAL: Critical issues requiring immediate action (30).
Examples:
>>> AlertLevel.CRITICAL > AlertLevel.WARNING
True
>>> AlertLevel.INFO.name
'INFO'
>>> int(AlertLevel.WARNING)
20
>>> AlertLevel.SUCCESS > AlertLevel.INFO
True
>>> AlertLevel.SUCCESS < AlertLevel.WARNING
True
"""
INFO = 10
SUCCESS = 11
WARNING = 20
CRITICAL = 30
[docs]
@dataclass(frozen=True, slots=True)
class AlertMessage:
"""An alert message to be sent via one or more channels.
Attributes:
title: Short summary of the alert (max 150 chars for Slack).
body: Detailed message content (max 3000 chars for Slack).
level: Severity level of the alert.
timestamp: If True, prefix title with send datetime.
Examples:
>>> msg = AlertMessage(title="Disk Full", body="Server disk at 95%")
>>> msg.level
<AlertLevel.INFO: 10>
>>> msg = AlertMessage(
... title="DB Connection Failed",
... body="Cannot connect to primary database",
... level=AlertLevel.CRITICAL,
... )
>>> msg.level.name
'CRITICAL'
>>> msg = AlertMessage(
... title="Alert",
... body="With timestamp",
... timestamp=True,
... )
>>> ":::" in msg.formatted_title
True
"""
title: str
body: str
level: AlertLevel = AlertLevel.INFO
timestamp: bool = False
@property
def formatted_title(self) -> str:
"""Return title with optional timestamp prefix.
If timestamp is True, prefixes the title with current datetime
in format "YYYY-MM-DD HH:MM:SS ::: ".
Returns:
Title string, optionally prefixed with timestamp.
Examples:
>>> msg = AlertMessage(title="Test", body="Body", timestamp=False)
>>> msg.formatted_title
'Test'
>>> msg = AlertMessage(title="Test", body="Body", timestamp=True)
>>> "Test" in msg.formatted_title
True
"""
if self.timestamp:
now = datetime.now(timezone.utc).astimezone().strftime("%Y-%m-%d %H:%M:%S")
return f"{now} ::: {self.title}"
return self.title
[docs]
@dataclass(frozen=True, slots=True)
class AlertResult:
"""Result of sending an alert to a channel.
Attributes:
channel: Name of the channel that processed this alert.
success: Whether the alert was delivered successfully.
message_id: ID assigned by the channel (if available).
error: Error message if delivery failed.
Examples:
>>> result = AlertResult(channel="slack", success=True, message_id="msg123")
>>> result.success
True
>>> result = AlertResult(channel="email", success=False, error="SMTP timeout")
>>> result.error
'SMTP timeout'
"""
channel: str
success: bool
message_id: str | None = None
error: str | None = None
__all__ = ["AlertLevel", "AlertMessage", "AlertResult"]