# plugins/prometheus/models.py from __future__ import annotations from datetime import datetime, timezone from sqlalchemy import JSON, Boolean, DateTime, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column from steward.core.ids import time_ordered_id from steward.models.base import Base class PrometheusTarget(Base): """A /metrics endpoint Steward scrapes, edited on the Prometheus page. The bearer token is stored encrypted. keep and drop are lists of name patterns ("fabledarchives_*") an admin chooses: Steward does the filtering, the endpoint serves everything. The last_* columns are the newest scrape's outcome, written by the scraper, so a page can say why a target isn't answering without asking it. """ __tablename__ = "prometheus_targets" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=time_ordered_id) name: Mapped[str] = mapped_column(String(100), nullable=False, unique=True) url: Mapped[str] = mapped_column(String(500), nullable=False) token: Mapped[str] = mapped_column(Text, nullable=False, default="") verify_tls: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) interval_seconds: Mapped[int] = mapped_column(Integer, nullable=False, default=60) keep: Mapped[list] = mapped_column(JSON, nullable=False, default=list) drop: Mapped[list] = mapped_column(JSON, nullable=False, default=list) series_cap: Mapped[int] = mapped_column(Integer, nullable=False, default=1000) enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc)) last_scraped_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) last_ok_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) last_error: Mapped[str | None] = mapped_column(Text, nullable=True) last_kept: Mapped[int] = mapped_column(Integer, nullable=False, default=0) last_dropped: Mapped[int] = mapped_column(Integer, nullable=False, default=0) last_capped: Mapped[int] = mapped_column(Integer, nullable=False, default=0) class PrometheusWidgetTemplate(Base): """A widget template an admin wrote or copied in (#5692), beside the bundled ones in widgets/*.yaml. `text` is the YAML as written; `name` is its `name:`, kept here so the library lists and orders without reading every template. Only a template that passes the checker is saved. Its key in a widget's settings is "custom:", so renaming it keeps its widgets. """ __tablename__ = "prometheus_widget_templates" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=time_ordered_id) name: Mapped[str] = mapped_column(String(80), nullable=False, unique=True) text: Mapped[str] = mapped_column(Text, nullable=False) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc)) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc))