8aad2ab43d
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
100 lines
4.3 KiB
Python
100 lines
4.3 KiB
Python
from __future__ import annotations
|
|
import enum
|
|
import uuid
|
|
from datetime import datetime, timezone
|
|
from sqlalchemy import Boolean, DateTime, Enum, Float, ForeignKey, Integer, String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
from .base import Base
|
|
|
|
|
|
class AlertOperator(str, enum.Enum):
|
|
gt = ">"
|
|
lt = "<"
|
|
gte = ">="
|
|
lte = "<="
|
|
eq = "=="
|
|
ne = "!="
|
|
|
|
|
|
class AlertStateEnum(str, enum.Enum):
|
|
inactive = "inactive"
|
|
pending = "pending"
|
|
firing = "firing"
|
|
acknowledged = "acknowledged"
|
|
resolved = "resolved"
|
|
|
|
|
|
class AlertRule(Base):
|
|
__tablename__ = "alert_rules"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
|
name: Mapped[str] = mapped_column(String(128), nullable=False)
|
|
source_module: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
resource_name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
metric_name: Mapped[str] = mapped_column(String(128), nullable=False)
|
|
operator: Mapped[AlertOperator] = mapped_column(Enum(AlertOperator), nullable=False)
|
|
threshold: Mapped[float] = mapped_column(Float, nullable=False)
|
|
consecutive_failures_required: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
|
|
enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
|
|
created_by: Mapped[str] = mapped_column(String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc)
|
|
)
|
|
|
|
|
|
class AlertState(Base):
|
|
__tablename__ = "alert_states"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
|
rule_id: Mapped[str] = mapped_column(
|
|
String(36), ForeignKey("alert_rules.id", ondelete="CASCADE"), nullable=False, unique=True
|
|
)
|
|
state: Mapped[AlertStateEnum] = mapped_column(
|
|
Enum(AlertStateEnum), nullable=False, default=AlertStateEnum.inactive
|
|
)
|
|
consecutive_failure_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
last_transition_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc)
|
|
)
|
|
acknowledged_by: Mapped[str | None] = mapped_column(
|
|
String(36), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
|
|
)
|
|
acknowledged_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
|
|
|
|
class MaintenanceWindow(Base):
|
|
__tablename__ = "maintenance_windows"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
|
name: Mapped[str] = mapped_column(String(128), nullable=False)
|
|
start_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
|
|
end_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
|
|
# Scope — null means "all". scope_resource requires scope_source to be set.
|
|
scope_source: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
|
scope_resource: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
created_by: Mapped[str] = mapped_column(
|
|
String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False
|
|
)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc)
|
|
)
|
|
|
|
|
|
class AlertEvent(Base):
|
|
__tablename__ = "alert_events"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
|
rule_id: Mapped[str] = mapped_column(
|
|
String(36), ForeignKey("alert_rules.id", ondelete="CASCADE"), nullable=False
|
|
)
|
|
from_state: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
to_state: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
metric_value: Mapped[float] = mapped_column(Float, nullable=False)
|
|
transitioned_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc)
|
|
)
|
|
email_sent: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
|
email_error: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
webhook_sent: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
|
webhook_error: Mapped[str | None] = mapped_column(Text, nullable=True)
|