feat(metrics): each rolled-up hour keeps the level it held, its p95 (#5738)
plugin_metrics_hourly gains value_p95 beside value_avg and value_max. A two-minute backup spike raises the hour's peak and leaves its p95 low; an hour spent at that level raises both. Learned normals (milestone 513) need that difference to call a recurring spike usual without calling the same level held at another hour usual too. Hours rolled up before this keep a NULL p95 and read as their average. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
"""Each hour of the metric rollup keeps the level it held, its 95th percentile,
|
||||
beside its average and peak (#5738), so a learned normal can tell a brief
|
||||
spike (a high peak, a low p95) from a level the metric stayed at.
|
||||
|
||||
Revision ID: 0044_hourly_p95
|
||||
Revises: 0043_outbox_alert_words
|
||||
Create Date: 2026-10-14
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision: str = "0044_hourly_p95"
|
||||
down_revision: Union[str, None] = "0043_outbox_alert_words"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Hours rolled up before this have no p95 to recover (their raw samples
|
||||
# are gone), so they stay NULL and read as their average.
|
||||
op.add_column("plugin_metrics_hourly", sa.Column("value_p95", sa.Float, nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("plugin_metrics_hourly", "value_p95")
|
||||
Reference in New Issue
Block a user