Files
FabledSteward/plugins/prometheus/models.py
T
bvandeusenandClaude Opus 5.5 4c9ed02652
CI / lint (push) Successful in 1s
CI / unit (push) Successful in 1m36s
CI / integration (push) Successful in 1m58s
CI / publish (push) Successful in 1m13s
feat(homeassistant): its page offers the metrics scrape under the same sign-in, so one user covers everything (#6744)
A Prometheus target's token_from names the plugin that supplies its token at each
scrape. Read its metrics makes the target; Use this sign-in moves one at that address
across, keeping its name, filters and history. A refusal stops the connection, so one
Try again or sign-in starts everything, and the sign-in is only sent to its own address.
A 404 says how to turn on Home Assistant's Prometheus integration, as Steward doesn't
change Home Assistant. Refused also joins the volatile columns a backup check ignores.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:06:55 -05:00

64 lines
3.5 KiB
Python

# 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, or `token_from` names the plugin whose
sign-in supplies it at each scrape (its metrics.scrape_token). 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. `refused` says its token was
refused, which stops the scraping until the target is saved or resumed.
"""
__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="")
token_from: Mapped[str | None] = mapped_column(String(50), nullable=True)
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)
refused: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
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:<id>", 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))