Migration 0030 seeded plugin_metric_latest from the whole history: two index probes per distinct metric key. On the live instance that held the first boot for 7+ minutes with Steward down. The migration now only creates the table. Live sources fill it on their next sample, and backfill_latest runs after startup for resources that have history but no latest rows. Per resource it does one backward probe for the last sample, then takes the newest value per metric within the hour before it. Resources that already have rows are skipped, so later boots only walk the resource names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
34 lines
1.2 KiB
Python
34 lines
1.2 KiB
Python
"""The newest sample of each metric, kept beside plugin_metrics (#5208)
|
|
|
|
Revision ID: 0030_plugin_metric_latest
|
|
Revises: 0029_alert_no_data
|
|
Create Date: 2026-10-07
|
|
"""
|
|
from typing import Sequence, Union
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision: str = "0030_plugin_metric_latest"
|
|
down_revision: Union[str, None] = "0029_alert_no_data"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"plugin_metric_latest",
|
|
sa.Column("source_module", sa.String(64), primary_key=True),
|
|
sa.Column("resource_name", sa.String(255), primary_key=True),
|
|
sa.Column("metric_name", sa.String(128), primary_key=True),
|
|
sa.Column("value", sa.Float, nullable=False),
|
|
sa.Column("recorded_at", sa.DateTime(timezone=True), nullable=False),
|
|
)
|
|
# Not seeded here: a seed over the whole history held the first boot for
|
|
# minutes. Live sources fill it on their next sample, and
|
|
# metric_series.backfill_latest fills the quiet ones in the background
|
|
# after startup.
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_table("plugin_metric_latest")
|