Merge branch 'feat/565-add-metric-tooltip' into metric-store-tickets

Resolve conflicts in the generated GraphQL code by regenerating it against
the merged schema. cc-lib v2.13.0 adds Tooltip to schema.MetricConfig and
schema.GlobalMetricListItem, so gqlgen now binds the tooltip field directly
and the hand-written globalMetricListItem/metricConfig resolvers introduced
on the tooltip branch are no longer needed.

Also migrate to the cc-lib v2.13.0 metric container types, which changed
from bare maps to structs carrying array-valued metric groups:

  schema.JobData          map -> {Metrics, Groups}
  schema.ScopedJobStats   map -> {Metrics, Groups}
  job.Statistics          map -> schema.JobStatisticsSet{Metrics, Groups}

Callers index .Metrics, return the zero struct instead of nil, and
deepCopy/DecodeJobStats now also carry the Groups payload through.
archive.GetStatistics returns the full JobStatisticsSet so group
statistics survive the round trip.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-27 10:22:22 +02:00
co-authored by Claude Opus 5
35 changed files with 411 additions and 212 deletions
+2 -2
View File
@@ -107,7 +107,7 @@ type JobClassTagger struct {
// repo provides access to job database operations
repo JobRepository
// getStatistics retrieves job statistics for analysis
getStatistics func(job *schema.Job) (map[string]schema.JobStatistics, error)
getStatistics func(job *schema.Job) (schema.JobStatisticsSet, error)
// getMetricConfig retrieves metric configuration (limits) for a cluster
getMetricConfig func(cluster, subCluster string) map[string]*schema.Metric
}
@@ -361,7 +361,7 @@ func (t *JobClassTagger) Match(job *schema.Job) {
// add metrics to env
skipRule := false
for _, m := range ri.metrics {
stats, ok := jobStats[m]
stats, ok := jobStats.Metrics[m]
if !ok {
cclog.Debugf("job classification: missing metric '%s' for rule %s on job %d", m, tag, job.JobID)
skipRule = true
+6 -6
View File
@@ -64,10 +64,10 @@ func TestClassifyJobMatch(t *testing.T) {
parameters: make(map[string]any),
tagType: "jobClass",
repo: mockRepo,
getStatistics: func(job *schema.Job) (map[string]schema.JobStatistics, error) {
return map[string]schema.JobStatistics{
getStatistics: func(job *schema.Job) (schema.JobStatisticsSet, error) {
return schema.JobStatisticsSet{Metrics: map[string]schema.JobStatistics{
"flops_any": {Min: 0, Max: 200, Avg: 150},
}, nil
}}, nil
},
getMetricConfig: func(cluster, subCluster string) map[string]*schema.Metric {
return map[string]*schema.Metric{
@@ -120,10 +120,10 @@ func TestMatch_NoMatch(t *testing.T) {
parameters: make(map[string]any),
tagType: "jobClass",
repo: mockRepo,
getStatistics: func(job *schema.Job) (map[string]schema.JobStatistics, error) {
return map[string]schema.JobStatistics{
getStatistics: func(job *schema.Job) (schema.JobStatisticsSet, error) {
return schema.JobStatisticsSet{Metrics: map[string]schema.JobStatistics{
"flops_any": {Min: 0, Max: 50, Avg: 20}, // Avg 20 < 100
}, nil
}}, nil
},
getMetricConfig: func(cluster, subCluster string) map[string]*schema.Metric {
return map[string]*schema.Metric{