Files
cc-backend/internal/metricdispatch/resamplepolicy.go
T
moebiusbandandClaude Opus 5 d40390061d fix: unify resample policy target-points table
The policy -> target-points mapping existed twice with different values:
internal/config (300/600/1000) fed the resampler's MinimumRequiredPoints
threshold, while internal/metricdispatch (200/500/1000) fed the requested
resolution and the frontend target point count.

Because the threshold was larger than the target, the resampler refused to
downsample series whose length fell between the two numbers, silently
dropping the resolution the backend had asked for. With the medium policy
that covered every series between 500 and 600 points.

Move the table into internal/config as the single source of truth (import
direction rules out the reverse, since metricdispatch already imports
config) and keep the 200/500/1000 values, which already drove the requested
resolution. metricdispatch.TargetPointsForPolicy now delegates to it, so
MinimumRequiredPoints equals the target and resampling happens exactly when
a series exceeds it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 12:16:46 +02:00

48 lines
1.5 KiB
Go

// Copyright (C) NHR@FAU, University Erlangen-Nuremberg.
// All rights reserved. This file is part of cc-backend.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package metricdispatch
import (
"math"
"github.com/ClusterCockpit/cc-backend/internal/config"
)
type ResamplePolicy string
const (
ResamplePolicyLow ResamplePolicy = "low"
ResamplePolicyMedium ResamplePolicy = "medium"
ResamplePolicyHigh ResamplePolicy = "high"
)
// TargetPointsForPolicy returns the target number of data points for a given
// policy. The table lives in the config package so that the requested
// resolution and the resampler's MinimumRequiredPoints threshold can never
// diverge.
func TargetPointsForPolicy(policy ResamplePolicy) int {
return config.TargetPointsForPolicy(string(policy))
}
// ComputeResolution computes the resampling resolution in seconds for a given
// job duration, metric frequency, and target point count. Returns 0 if the
// total number of data points is already at or below targetPoints (no resampling needed).
func ComputeResolution(duration int64, frequency int64, targetPoints int) int {
if frequency <= 0 || targetPoints <= 0 || duration <= 0 {
return 0
}
totalPoints := duration / frequency
if totalPoints <= int64(targetPoints) {
return 0
}
targetRes := math.Ceil(float64(duration) / float64(targetPoints))
// Round up to nearest multiple of frequency
resolution := int(math.Ceil(targetRes/float64(frequency))) * int(frequency)
return resolution
}