diff --git a/api/schema.graphqls b/api/schema.graphqls index cad8d2f..21a9ad2 100644 --- a/api/schema.graphqls +++ b/api/schema.graphqls @@ -288,6 +288,7 @@ type HistoPoint { type MetricHistoPoints { metric: String! + unit: String! data: [MetricHistoPoint!] } diff --git a/internal/graph/generated/generated.go b/internal/graph/generated/generated.go index 4f76ee8..f3d4f8a 100644 --- a/internal/graph/generated/generated.go +++ b/internal/graph/generated/generated.go @@ -189,6 +189,7 @@ type ComplexityRoot struct { MetricHistoPoints struct { Data func(childComplexity int) int Metric func(childComplexity int) int + Unit func(childComplexity int) int } MetricStatistics struct { @@ -987,6 +988,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.MetricHistoPoints.Metric(childComplexity), true + case "MetricHistoPoints.unit": + if e.complexity.MetricHistoPoints.Unit == nil { + break + } + + return e.complexity.MetricHistoPoints.Unit(childComplexity), true + case "MetricStatistics.avg": if e.complexity.MetricStatistics.Avg == nil { break @@ -1956,6 +1964,7 @@ type HistoPoint { type MetricHistoPoints { metric: String! + unit: String! data: [MetricHistoPoint!] } @@ -5771,6 +5780,8 @@ func (ec *executionContext) fieldContext_JobsStatistics_histMetrics(ctx context. switch field.Name { case "metric": return ec.fieldContext_MetricHistoPoints_metric(ctx, field) + case "unit": + return ec.fieldContext_MetricHistoPoints_unit(ctx, field) case "data": return ec.fieldContext_MetricHistoPoints_data(ctx, field) } @@ -6545,6 +6556,50 @@ func (ec *executionContext) fieldContext_MetricHistoPoints_metric(ctx context.Co return fc, nil } +func (ec *executionContext) _MetricHistoPoints_unit(ctx context.Context, field graphql.CollectedField, obj *model.MetricHistoPoints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_MetricHistoPoints_unit(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Unit, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_MetricHistoPoints_unit(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "MetricHistoPoints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _MetricHistoPoints_data(ctx context.Context, field graphql.CollectedField, obj *model.MetricHistoPoints) (ret graphql.Marshaler) { fc, err := ec.fieldContext_MetricHistoPoints_data(ctx, field) if err != nil { @@ -13546,6 +13601,11 @@ func (ec *executionContext) _MetricHistoPoints(ctx context.Context, sel ast.Sele if out.Values[i] == graphql.Null { out.Invalids++ } + case "unit": + out.Values[i] = ec._MetricHistoPoints_unit(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "data": out.Values[i] = ec._MetricHistoPoints_data(ctx, field, obj) default: diff --git a/internal/graph/model/models_gen.go b/internal/graph/model/models_gen.go index be26ffd..eb35bda 100644 --- a/internal/graph/model/models_gen.go +++ b/internal/graph/model/models_gen.go @@ -118,6 +118,7 @@ type MetricHistoPoint struct { type MetricHistoPoints struct { Metric string `json:"metric"` + Unit string `json:"unit"` Data []*MetricHistoPoint `json:"data,omitempty"` } diff --git a/internal/repository/stats.go b/internal/repository/stats.go index b3910fe..bd870a4 100644 --- a/internal/repository/stats.go +++ b/internal/repository/stats.go @@ -536,11 +536,13 @@ func (r *JobRepository) jobsMetricStatisticsHistogram( // Get specific Peak or largest Peak var metricConfig *schema.MetricConfig var peak float64 = 0.0 + var unit string = "" for _, f := range filters { if f.Cluster != nil { metricConfig = archive.GetMetricConfig(*f.Cluster.Eq, metric) peak = metricConfig.Peak + unit = metricConfig.Unit.Prefix + metricConfig.Unit.Base log.Debugf("Cluster %s filter found with peak %f for %s", *f.Cluster.Eq, peak, metric) } } @@ -552,6 +554,9 @@ func (r *JobRepository) jobsMetricStatisticsHistogram( if m.Peak > peak { peak = m.Peak } + if unit == "" { + unit = m.Unit.Prefix + m.Unit.Base + } } } } @@ -602,7 +607,7 @@ func (r *JobRepository) jobsMetricStatisticsHistogram( points = append(points, &point) } - result := model.MetricHistoPoints{Metric: metric, Data: points} + result := model.MetricHistoPoints{Metric: metric, Unit: unit, Data: points} log.Debugf("Timer jobsStatisticsHistogram %s", time.Since(start)) return &result, nil diff --git a/web/frontend/src/User.root.svelte b/web/frontend/src/User.root.svelte index c5d85b1..23ebb16 100644 --- a/web/frontend/src/User.root.svelte +++ b/web/frontend/src/User.root.svelte @@ -16,7 +16,6 @@ const { query: initq } = init() const ccconfig = getContext('cc-config') - // const metricConfig = getContext('metrics') export let user export let filterPresets @@ -42,7 +41,7 @@ totalCoreHours histDuration { count, value } histNumNodes { count, value } - histMetrics { metric, data { min, max, count, bin } } + histMetrics { metric, unit, data { min, max, count, bin } } }}`, variables: { jobFilters, metricsInHistograms} }) @@ -185,21 +184,18 @@ + renderFor="user" + items={$stats.data.jobsStatistics[0].histMetrics} + itemsPerRow={3}> - {item} - - + title="Distribution of '{item.metric}'" + xlabel={`${item.metric} bin maximum [${item.unit}]`} + xunit={item.unit} + ylabel="Count" + yunit="Jobs"/> {/key} diff --git a/web/frontend/src/utils.js b/web/frontend/src/utils.js index da1878a..17f4ceb 100644 --- a/web/frontend/src/utils.js +++ b/web/frontend/src/utils.js @@ -318,9 +318,14 @@ export function checkMetricDisabled(m, c, s) { //[m]etric, [c]luster, [s]ubclust export function convert2uplot(canvasData) { // initial use: Canvas Histogram Data to Uplot let uplotData = [[],[]] // [X, Y1, Y2, ...] - canvasData.forEach( pair => { - uplotData[0].push(pair.value) - uplotData[1].push(pair.count) + canvasData.forEach( cd => { + if (cd.bin) { // MetricHisto Datafromat + uplotData[0].push(cd.max) + uplotData[1].push(cd.count) + } else { // Default + uplotData[0].push(cd.value) + uplotData[1].push(cd.count) + } }) return uplotData }