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
+76
View File
@@ -100,6 +100,7 @@ type ComplexityRoot struct {
Footprint func(childComplexity int) int
Name func(childComplexity int) int
Scope func(childComplexity int) int
Tooltip func(childComplexity int) int
Unit func(childComplexity int) int
}
@@ -219,6 +220,7 @@ type ComplexityRoot struct {
Scope func(childComplexity int) int
SubClusters func(childComplexity int) int
Timestep func(childComplexity int) int
Tooltip func(childComplexity int) int
Unit func(childComplexity int) int
}
@@ -698,6 +700,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.ComplexityRoot.GlobalMetricListItem.Scope(childComplexity), true
case "GlobalMetricListItem.tooltip":
if e.ComplexityRoot.GlobalMetricListItem.Tooltip == nil {
break
}
return e.ComplexityRoot.GlobalMetricListItem.Tooltip(childComplexity), true
case "GlobalMetricListItem.unit":
if e.ComplexityRoot.GlobalMetricListItem.Unit == nil {
break
@@ -1225,6 +1233,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.ComplexityRoot.MetricConfig.Timestep(childComplexity), true
case "MetricConfig.tooltip":
if e.ComplexityRoot.MetricConfig.Tooltip == nil {
break
}
return e.ComplexityRoot.MetricConfig.Tooltip(childComplexity), true
case "MetricConfig.unit":
if e.ComplexityRoot.MetricConfig.Unit == nil {
break
@@ -2426,6 +2440,7 @@ type MetricConfig {
alert: Float!
lowerIsBetter: Boolean
subClusters: [SubClusterConfig!]!
tooltip: String
}
type Tag {
@@ -2589,6 +2604,7 @@ type GlobalMetricListItem {
unit: Unit!
scope: MetricScope!
footprint: String
tooltip: String
availability: [ClusterSupport!]!
}
@@ -2973,6 +2989,8 @@ func (ec *executionContext) childFields_GlobalMetricListItem(ctx context.Context
return ec.fieldContext_GlobalMetricListItem_scope(ctx, field)
case "footprint":
return ec.fieldContext_GlobalMetricListItem_footprint(ctx, field)
case "tooltip":
return ec.fieldContext_GlobalMetricListItem_tooltip(ctx, field)
case "availability":
return ec.fieldContext_GlobalMetricListItem_availability(ctx, field)
}
@@ -3203,6 +3221,8 @@ func (ec *executionContext) childFields_MetricConfig(ctx context.Context, field
return ec.fieldContext_MetricConfig_lowerIsBetter(ctx, field)
case "subClusters":
return ec.fieldContext_MetricConfig_subClusters(ctx, field)
case "tooltip":
return ec.fieldContext_MetricConfig_tooltip(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type MetricConfig", field.Name)
}
@@ -5187,6 +5207,29 @@ func (ec *executionContext) fieldContext_GlobalMetricListItem_footprint(_ contex
return graphql.NewScalarFieldContext("GlobalMetricListItem", field, false, false, errors.New("field of type String does not have child fields"))
}
func (ec *executionContext) _GlobalMetricListItem_tooltip(ctx context.Context, field graphql.CollectedField, obj *schema.GlobalMetricListItem) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return ec.fieldContext_GlobalMetricListItem_tooltip(ctx, field)
},
func(ctx context.Context) (any, error) {
return obj.Tooltip, nil
},
nil,
func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler {
return ec.marshalOString2string(ctx, selections, v)
},
true,
false,
)
}
func (ec *executionContext) fieldContext_GlobalMetricListItem_tooltip(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
return graphql.NewScalarFieldContext("GlobalMetricListItem", field, false, false, errors.New("field of type String does not have child fields"))
}
func (ec *executionContext) _GlobalMetricListItem_availability(ctx context.Context, field graphql.CollectedField, obj *schema.GlobalMetricListItem) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -7377,6 +7420,29 @@ func (ec *executionContext) fieldContext_MetricConfig_subClusters(_ context.Cont
return fc, nil
}
func (ec *executionContext) _MetricConfig_tooltip(ctx context.Context, field graphql.CollectedField, obj *schema.MetricConfig) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return ec.fieldContext_MetricConfig_tooltip(ctx, field)
},
func(ctx context.Context) (any, error) {
return obj.Tooltip, nil
},
nil,
func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler {
return ec.marshalOString2string(ctx, selections, v)
},
true,
false,
)
}
func (ec *executionContext) fieldContext_MetricConfig_tooltip(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
return graphql.NewScalarFieldContext("MetricConfig", field, false, false, errors.New("field of type String does not have child fields"))
}
func (ec *executionContext) _MetricFootprints_metric(ctx context.Context, field graphql.CollectedField, obj *model.MetricFootprints) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -13311,6 +13377,11 @@ func (ec *executionContext) _GlobalMetricListItem(ctx context.Context, sel ast.S
if out.Values[i] == graphql.RequiredNull {
out.Invalids++
}
case "tooltip":
out.Values[i] = ec._GlobalMetricListItem_tooltip(ctx, field, obj)
if out.Values[i] == graphql.RequiredNull {
out.Invalids++
}
case "availability":
out.Values[i] = ec._GlobalMetricListItem_availability(ctx, field, obj)
if out.Values[i] == graphql.Null {
@@ -14340,6 +14411,11 @@ func (ec *executionContext) _MetricConfig(ctx context.Context, sel ast.Selection
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "tooltip":
out.Values[i] = ec._MetricConfig_tooltip(ctx, field, obj)
if out.Values[i] == graphql.RequiredNull {
out.Invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
+3 -3
View File
@@ -528,7 +528,7 @@ func (r *queryResolver) JobMetrics(ctx context.Context, id string, metrics []str
}
res := []*model.JobMetricWithName{}
for name, md := range data {
for name, md := range data.Metrics {
for scope, metric := range md {
res = append(res, &model.JobMetricWithName{
Name: name,
@@ -581,7 +581,7 @@ func (r *queryResolver) ScopedJobStats(ctx context.Context, id string, metrics [
}
res := make([]*model.NamedStatsWithScope, 0)
for name, scoped := range data {
for name, scoped := range data.Metrics {
for scope, stats := range scoped {
mdlStats := make([]*model.ScopedStats, 0)
@@ -939,7 +939,7 @@ func (r *queryResolver) NodeMetricsList(ctx context.Context, cluster string, sub
cclog.Warnf("error in nodeMetrics resolver: %s", err)
}
for metric, scopedMetrics := range data[hostname] {
for metric, scopedMetrics := range data[hostname].Metrics {
for scope, scopedMetric := range scopedMetrics {
host.Metrics = append(host.Metrics, &model.JobMetricWithName{
Name: metric,
+1 -1
View File
@@ -61,7 +61,7 @@ func (r *queryResolver) rooflineHeatmap(
return nil, err
}
flops_, membw_ := jobdata["flops_any"], jobdata["mem_bw"]
flops_, membw_ := jobdata.Metrics["flops_any"], jobdata.Metrics["mem_bw"]
if flops_ == nil && membw_ == nil {
cclog.Warnf("rooflineHeatmap(): 'flops_any' or 'mem_bw' missing for job %d", *job.ID)
continue