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:
@@ -40,7 +40,7 @@ async def rollup_plugin_metrics(
|
||||
"""Roll up + prune plugin_metrics. Returns a counts dict for logging.
|
||||
|
||||
1. Aggregate plugin_metrics older than the (hour-aligned) raw window into
|
||||
plugin_metrics_hourly (avg/max per source/resource/metric/hour), upserting
|
||||
plugin_metrics_hourly (avg/max/p95 per source/resource/metric/hour), upserting
|
||||
so a re-run is idempotent, then delete those raw rows.
|
||||
2. Prune rolled-up rows older than the rollup window.
|
||||
"""
|
||||
@@ -67,6 +67,7 @@ async def rollup_plugin_metrics(
|
||||
hour.label("bucket"),
|
||||
func.avg(PluginMetric.value).label("value_avg"),
|
||||
func.max(PluginMetric.value).label("value_max"),
|
||||
func.percentile_cont(0.95).within_group(PluginMetric.value).label("value_p95"),
|
||||
func.count().label("sample_count"),
|
||||
)
|
||||
.where(PluginMetric.recorded_at < raw_cutoff)
|
||||
@@ -78,17 +79,19 @@ async def rollup_plugin_metrics(
|
||||
for r in (await session.execute(agg)).all():
|
||||
avg_v = float(r.value_avg or 0.0)
|
||||
max_v = float(r.value_max or 0.0)
|
||||
p95_v = float(r.value_p95) if r.value_p95 is not None else avg_v
|
||||
cnt = int(r.sample_count or 0)
|
||||
await session.execute(
|
||||
pg_insert(PluginMetricHourly)
|
||||
.values(
|
||||
source_module=r.source_module, resource_name=r.resource_name,
|
||||
metric_name=r.metric_name, bucket=r.bucket,
|
||||
value_avg=avg_v, value_max=max_v, sample_count=cnt,
|
||||
value_avg=avg_v, value_max=max_v, value_p95=p95_v, sample_count=cnt,
|
||||
)
|
||||
.on_conflict_do_update(
|
||||
constraint="uq_plugin_metrics_hourly_bucket",
|
||||
set_={"value_avg": avg_v, "value_max": max_v, "sample_count": cnt},
|
||||
set_={"value_avg": avg_v, "value_max": max_v, "value_p95": p95_v,
|
||||
"sample_count": cnt},
|
||||
)
|
||||
)
|
||||
rolled += 1
|
||||
|
||||
Reference in New Issue
Block a user