mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2026-03-20 23:07:29 +01:00
146 lines
3.7 KiB
Go
146 lines
3.7 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 graph
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/ClusterCockpit/cc-backend/internal/config"
|
|
"github.com/ClusterCockpit/cc-backend/internal/graph/model"
|
|
"github.com/ClusterCockpit/cc-backend/internal/metricdispatch"
|
|
"github.com/ClusterCockpit/cc-backend/internal/repository"
|
|
"github.com/ClusterCockpit/cc-backend/pkg/archive"
|
|
)
|
|
|
|
// resolveResolutionFromPolicy reads the user's resample policy preference and
|
|
// computes a resolution based on job duration and metric frequency. Returns nil
|
|
// if the user has no policy set.
|
|
func resolveResolutionFromPolicy(ctx context.Context, duration int64, cluster string, metrics []string) *int {
|
|
user := repository.GetUserFromContext(ctx)
|
|
if user == nil {
|
|
return nil
|
|
}
|
|
|
|
conf, err := repository.GetUserCfgRepo().GetUIConfig(user)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
policyVal, ok := conf["plotConfiguration_resamplePolicy"]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
policyStr, ok := policyVal.(string)
|
|
if !ok || policyStr == "" {
|
|
return nil
|
|
}
|
|
|
|
policy := metricdispatch.ResamplePolicy(policyStr)
|
|
targetPoints := metricdispatch.TargetPointsForPolicy(policy)
|
|
if targetPoints == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Find the smallest metric frequency across the requested metrics
|
|
frequency := smallestFrequency(cluster, metrics)
|
|
if frequency <= 0 {
|
|
return nil
|
|
}
|
|
|
|
res := metricdispatch.ComputeResolution(duration, int64(frequency), targetPoints)
|
|
return &res
|
|
}
|
|
|
|
// resolveResampleAlgo returns the resampling algorithm name to use, checking
|
|
// the explicit GraphQL parameter first, then the user's preference.
|
|
func resolveResampleAlgo(ctx context.Context, resampleAlgo *model.ResampleAlgo) string {
|
|
if resampleAlgo != nil {
|
|
return strings.ToLower(resampleAlgo.String())
|
|
}
|
|
|
|
user := repository.GetUserFromContext(ctx)
|
|
if user == nil {
|
|
return ""
|
|
}
|
|
|
|
conf, err := repository.GetUserCfgRepo().GetUIConfig(user)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
algoVal, ok := conf["plotConfiguration_resampleAlgo"]
|
|
if ok {
|
|
if algoStr, ok := algoVal.(string); ok && algoStr != "" {
|
|
return algoStr
|
|
}
|
|
}
|
|
|
|
// Fall back to global default algo
|
|
if config.Keys.EnableResampling != nil && config.Keys.EnableResampling.DefaultAlgo != "" {
|
|
return config.Keys.EnableResampling.DefaultAlgo
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// resolveResolutionFromDefaultPolicy computes a resolution using the global
|
|
// default policy from config. Returns nil if no policy is configured.
|
|
func resolveResolutionFromDefaultPolicy(duration int64, cluster string, metrics []string) *int {
|
|
cfg := config.Keys.EnableResampling
|
|
if cfg == nil {
|
|
return nil
|
|
}
|
|
|
|
policyStr := cfg.DefaultPolicy
|
|
if policyStr == "" {
|
|
policyStr = "medium"
|
|
}
|
|
|
|
policy := metricdispatch.ResamplePolicy(policyStr)
|
|
targetPoints := metricdispatch.TargetPointsForPolicy(policy)
|
|
if targetPoints == 0 {
|
|
return nil
|
|
}
|
|
|
|
frequency := smallestFrequency(cluster, metrics)
|
|
if frequency <= 0 {
|
|
return nil
|
|
}
|
|
|
|
res := metricdispatch.ComputeResolution(duration, int64(frequency), targetPoints)
|
|
return &res
|
|
}
|
|
|
|
// smallestFrequency returns the smallest metric timestep (in seconds) among the
|
|
// requested metrics for the given cluster. Falls back to 0 if nothing is found.
|
|
func smallestFrequency(cluster string, metrics []string) int {
|
|
cl := archive.GetCluster(cluster)
|
|
if cl == nil {
|
|
return 0
|
|
}
|
|
|
|
minFreq := 0
|
|
for _, mc := range cl.MetricConfig {
|
|
if len(metrics) > 0 {
|
|
found := false
|
|
for _, m := range metrics {
|
|
if mc.Name == m {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
continue
|
|
}
|
|
}
|
|
if minFreq == 0 || mc.Timestep < minFreq {
|
|
minFreq = mc.Timestep
|
|
}
|
|
}
|
|
|
|
return minFreq
|
|
}
|