mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-12-27 05:49:04 +01:00
start working on non-node-scoped metrics in node/system view
This commit is contained in:
parent
84431585f9
commit
29a25dbaff
@ -156,13 +156,8 @@ type ComplexityRoot struct {
|
|||||||
UpdateConfiguration func(childComplexity int, name string, value string) int
|
UpdateConfiguration func(childComplexity int, name string, value string) int
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeMetric struct {
|
|
||||||
Data func(childComplexity int) int
|
|
||||||
Name func(childComplexity int) int
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeMetrics struct {
|
NodeMetrics struct {
|
||||||
ID func(childComplexity int) int
|
Host func(childComplexity int) int
|
||||||
Metrics func(childComplexity int) int
|
Metrics func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +180,7 @@ type ComplexityRoot struct {
|
|||||||
Jobs func(childComplexity int, filter []*model.JobFilter, page *model.PageRequest, order *model.OrderByInput) int
|
Jobs func(childComplexity int, filter []*model.JobFilter, page *model.PageRequest, order *model.OrderByInput) int
|
||||||
JobsFootprints func(childComplexity int, filter []*model.JobFilter, metrics []string) int
|
JobsFootprints func(childComplexity int, filter []*model.JobFilter, metrics []string) int
|
||||||
JobsStatistics func(childComplexity int, filter []*model.JobFilter, groupBy *model.Aggregate) int
|
JobsStatistics func(childComplexity int, filter []*model.JobFilter, groupBy *model.Aggregate) int
|
||||||
NodeMetrics func(childComplexity int, cluster string, nodes []string, metrics []string, from time.Time, to time.Time) int
|
NodeMetrics func(childComplexity int, cluster string, partition string, nodes []string, scopes []string, metrics []string, from time.Time, to time.Time) int
|
||||||
RooflineHeatmap func(childComplexity int, filter []*model.JobFilter, rows int, cols int, minX float64, minY float64, maxX float64, maxY float64) int
|
RooflineHeatmap func(childComplexity int, filter []*model.JobFilter, rows int, cols int, minX float64, minY float64, maxX float64, maxY float64) int
|
||||||
Tags func(childComplexity int) int
|
Tags func(childComplexity int) int
|
||||||
}
|
}
|
||||||
@ -250,7 +245,7 @@ type QueryResolver interface {
|
|||||||
Jobs(ctx context.Context, filter []*model.JobFilter, page *model.PageRequest, order *model.OrderByInput) (*model.JobResultList, error)
|
Jobs(ctx context.Context, filter []*model.JobFilter, page *model.PageRequest, order *model.OrderByInput) (*model.JobResultList, error)
|
||||||
JobsStatistics(ctx context.Context, filter []*model.JobFilter, groupBy *model.Aggregate) ([]*model.JobsStatistics, error)
|
JobsStatistics(ctx context.Context, filter []*model.JobFilter, groupBy *model.Aggregate) ([]*model.JobsStatistics, error)
|
||||||
RooflineHeatmap(ctx context.Context, filter []*model.JobFilter, rows int, cols int, minX float64, minY float64, maxX float64, maxY float64) ([][]float64, error)
|
RooflineHeatmap(ctx context.Context, filter []*model.JobFilter, rows int, cols int, minX float64, minY float64, maxX float64, maxY float64) ([][]float64, error)
|
||||||
NodeMetrics(ctx context.Context, cluster string, nodes []string, metrics []string, from time.Time, to time.Time) ([]*model.NodeMetrics, error)
|
NodeMetrics(ctx context.Context, cluster string, partition string, nodes []string, scopes []string, metrics []string, from time.Time, to time.Time) ([]*model.NodeMetrics, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type executableSchema struct {
|
type executableSchema struct {
|
||||||
@ -769,26 +764,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Mutation.UpdateConfiguration(childComplexity, args["name"].(string), args["value"].(string)), true
|
return e.complexity.Mutation.UpdateConfiguration(childComplexity, args["name"].(string), args["value"].(string)), true
|
||||||
|
|
||||||
case "NodeMetric.data":
|
case "NodeMetrics.host":
|
||||||
if e.complexity.NodeMetric.Data == nil {
|
if e.complexity.NodeMetrics.Host == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.complexity.NodeMetric.Data(childComplexity), true
|
return e.complexity.NodeMetrics.Host(childComplexity), true
|
||||||
|
|
||||||
case "NodeMetric.name":
|
|
||||||
if e.complexity.NodeMetric.Name == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.complexity.NodeMetric.Name(childComplexity), true
|
|
||||||
|
|
||||||
case "NodeMetrics.id":
|
|
||||||
if e.complexity.NodeMetrics.ID == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.complexity.NodeMetrics.ID(childComplexity), true
|
|
||||||
|
|
||||||
case "NodeMetrics.metrics":
|
case "NodeMetrics.metrics":
|
||||||
if e.complexity.NodeMetrics.Metrics == nil {
|
if e.complexity.NodeMetrics.Metrics == nil {
|
||||||
@ -937,7 +918,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.complexity.Query.NodeMetrics(childComplexity, args["cluster"].(string), args["nodes"].([]string), args["metrics"].([]string), args["from"].(time.Time), args["to"].(time.Time)), true
|
return e.complexity.Query.NodeMetrics(childComplexity, args["cluster"].(string), args["partition"].(string), args["nodes"].([]string), args["scopes"].([]string), args["metrics"].([]string), args["from"].(time.Time), args["to"].(time.Time)), true
|
||||||
|
|
||||||
case "Query.rooflineHeatmap":
|
case "Query.rooflineHeatmap":
|
||||||
if e.complexity.Query.RooflineHeatmap == nil {
|
if e.complexity.Query.RooflineHeatmap == nil {
|
||||||
@ -1299,14 +1280,9 @@ type MetricFootprints {
|
|||||||
|
|
||||||
enum Aggregate { USER, PROJECT, CLUSTER }
|
enum Aggregate { USER, PROJECT, CLUSTER }
|
||||||
|
|
||||||
type NodeMetric {
|
|
||||||
name: String!
|
|
||||||
data: [NullableFloat!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type NodeMetrics {
|
type NodeMetrics {
|
||||||
id: String!
|
host: String!
|
||||||
metrics: [NodeMetric!]!
|
metrics: [JobMetricWithName!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
@ -1322,7 +1298,7 @@ type Query {
|
|||||||
|
|
||||||
rooflineHeatmap(filter: [JobFilter!]!, rows: Int!, cols: Int!, minX: Float!, minY: Float!, maxX: Float!, maxY: Float!): [[Float!]!]!
|
rooflineHeatmap(filter: [JobFilter!]!, rows: Int!, cols: Int!, minX: Float!, minY: Float!, maxX: Float!, maxY: Float!): [[Float!]!]!
|
||||||
|
|
||||||
nodeMetrics(cluster: ID!, nodes: [String!], metrics: [String!], from: Time!, to: Time!): [NodeMetrics!]!
|
nodeMetrics(cluster: String!, partition: String!, nodes: [String!], scopes: [String!], metrics: [String!], from: Time!, to: Time!): [NodeMetrics!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
@ -1681,48 +1657,66 @@ func (ec *executionContext) field_Query_nodeMetrics_args(ctx context.Context, ra
|
|||||||
var arg0 string
|
var arg0 string
|
||||||
if tmp, ok := rawArgs["cluster"]; ok {
|
if tmp, ok := rawArgs["cluster"]; ok {
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("cluster"))
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("cluster"))
|
||||||
arg0, err = ec.unmarshalNID2string(ctx, tmp)
|
arg0, err = ec.unmarshalNString2string(ctx, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args["cluster"] = arg0
|
args["cluster"] = arg0
|
||||||
var arg1 []string
|
var arg1 string
|
||||||
if tmp, ok := rawArgs["nodes"]; ok {
|
if tmp, ok := rawArgs["partition"]; ok {
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nodes"))
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("partition"))
|
||||||
arg1, err = ec.unmarshalOString2ᚕstringᚄ(ctx, tmp)
|
arg1, err = ec.unmarshalNString2string(ctx, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args["nodes"] = arg1
|
args["partition"] = arg1
|
||||||
var arg2 []string
|
var arg2 []string
|
||||||
if tmp, ok := rawArgs["metrics"]; ok {
|
if tmp, ok := rawArgs["nodes"]; ok {
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("metrics"))
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nodes"))
|
||||||
arg2, err = ec.unmarshalOString2ᚕstringᚄ(ctx, tmp)
|
arg2, err = ec.unmarshalOString2ᚕstringᚄ(ctx, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args["metrics"] = arg2
|
args["nodes"] = arg2
|
||||||
var arg3 time.Time
|
var arg3 []string
|
||||||
|
if tmp, ok := rawArgs["scopes"]; ok {
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("scopes"))
|
||||||
|
arg3, err = ec.unmarshalOString2ᚕstringᚄ(ctx, tmp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args["scopes"] = arg3
|
||||||
|
var arg4 []string
|
||||||
|
if tmp, ok := rawArgs["metrics"]; ok {
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("metrics"))
|
||||||
|
arg4, err = ec.unmarshalOString2ᚕstringᚄ(ctx, tmp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args["metrics"] = arg4
|
||||||
|
var arg5 time.Time
|
||||||
if tmp, ok := rawArgs["from"]; ok {
|
if tmp, ok := rawArgs["from"]; ok {
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("from"))
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("from"))
|
||||||
arg3, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp)
|
arg5, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args["from"] = arg3
|
args["from"] = arg5
|
||||||
var arg4 time.Time
|
var arg6 time.Time
|
||||||
if tmp, ok := rawArgs["to"]; ok {
|
if tmp, ok := rawArgs["to"]; ok {
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("to"))
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("to"))
|
||||||
arg4, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp)
|
arg6, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args["to"] = arg4
|
args["to"] = arg6
|
||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4230,77 +4224,7 @@ func (ec *executionContext) _Mutation_updateConfiguration(ctx context.Context, f
|
|||||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _NodeMetric_name(ctx context.Context, field graphql.CollectedField, obj *model.NodeMetric) (ret graphql.Marshaler) {
|
func (ec *executionContext) _NodeMetrics_host(ctx context.Context, field graphql.CollectedField, obj *model.NodeMetrics) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
ret = graphql.Null
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
fc := &graphql.FieldContext{
|
|
||||||
Object: "NodeMetric",
|
|
||||||
Field: field,
|
|
||||||
Args: nil,
|
|
||||||
IsMethod: false,
|
|
||||||
IsResolver: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
|
||||||
ctx = rctx // use context from middleware stack in children
|
|
||||||
return obj.Name, 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) _NodeMetric_data(ctx context.Context, field graphql.CollectedField, obj *model.NodeMetric) (ret graphql.Marshaler) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
ret = graphql.Null
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
fc := &graphql.FieldContext{
|
|
||||||
Object: "NodeMetric",
|
|
||||||
Field: field,
|
|
||||||
Args: nil,
|
|
||||||
IsMethod: false,
|
|
||||||
IsResolver: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
|
||||||
ctx = rctx // use context from middleware stack in children
|
|
||||||
return obj.Data, 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.([]schema.Float)
|
|
||||||
fc.Result = res
|
|
||||||
return ec.marshalNNullableFloat2ᚕgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋschemaᚐFloatᚄ(ctx, field.Selections, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) _NodeMetrics_id(ctx context.Context, field graphql.CollectedField, obj *model.NodeMetrics) (ret graphql.Marshaler) {
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
@ -4318,7 +4242,7 @@ func (ec *executionContext) _NodeMetrics_id(ctx context.Context, field graphql.C
|
|||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
ctx = rctx // use context from middleware stack in children
|
ctx = rctx // use context from middleware stack in children
|
||||||
return obj.ID, nil
|
return obj.Host, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec.Error(ctx, err)
|
ec.Error(ctx, err)
|
||||||
@ -4365,9 +4289,9 @@ func (ec *executionContext) _NodeMetrics_metrics(ctx context.Context, field grap
|
|||||||
}
|
}
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
res := resTmp.([]*model.NodeMetric)
|
res := resTmp.([]*model.JobMetricWithName)
|
||||||
fc.Result = res
|
fc.Result = res
|
||||||
return ec.marshalNNodeMetric2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋgraphᚋmodelᚐNodeMetricᚄ(ctx, field.Selections, res)
|
return ec.marshalNJobMetricWithName2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋgraphᚋmodelᚐJobMetricWithNameᚄ(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Partition_name(ctx context.Context, field graphql.CollectedField, obj *model.Partition) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Partition_name(ctx context.Context, field graphql.CollectedField, obj *model.Partition) (ret graphql.Marshaler) {
|
||||||
@ -5029,7 +4953,7 @@ func (ec *executionContext) _Query_nodeMetrics(ctx context.Context, field graphq
|
|||||||
fc.Args = args
|
fc.Args = args
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
ctx = rctx // use context from middleware stack in children
|
ctx = rctx // use context from middleware stack in children
|
||||||
return ec.resolvers.Query().NodeMetrics(rctx, args["cluster"].(string), args["nodes"].([]string), args["metrics"].([]string), args["from"].(time.Time), args["to"].(time.Time))
|
return ec.resolvers.Query().NodeMetrics(rctx, args["cluster"].(string), args["partition"].(string), args["nodes"].([]string), args["scopes"].([]string), args["metrics"].([]string), args["from"].(time.Time), args["to"].(time.Time))
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec.Error(ctx, err)
|
ec.Error(ctx, err)
|
||||||
@ -7928,38 +7852,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodeMetricImplementors = []string{"NodeMetric"}
|
|
||||||
|
|
||||||
func (ec *executionContext) _NodeMetric(ctx context.Context, sel ast.SelectionSet, obj *model.NodeMetric) graphql.Marshaler {
|
|
||||||
fields := graphql.CollectFields(ec.OperationContext, sel, nodeMetricImplementors)
|
|
||||||
|
|
||||||
out := graphql.NewFieldSet(fields)
|
|
||||||
var invalids uint32
|
|
||||||
for i, field := range fields {
|
|
||||||
switch field.Name {
|
|
||||||
case "__typename":
|
|
||||||
out.Values[i] = graphql.MarshalString("NodeMetric")
|
|
||||||
case "name":
|
|
||||||
out.Values[i] = ec._NodeMetric_name(ctx, field, obj)
|
|
||||||
if out.Values[i] == graphql.Null {
|
|
||||||
invalids++
|
|
||||||
}
|
|
||||||
case "data":
|
|
||||||
out.Values[i] = ec._NodeMetric_data(ctx, field, obj)
|
|
||||||
if out.Values[i] == graphql.Null {
|
|
||||||
invalids++
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic("unknown field " + strconv.Quote(field.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out.Dispatch()
|
|
||||||
if invalids > 0 {
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
var nodeMetricsImplementors = []string{"NodeMetrics"}
|
var nodeMetricsImplementors = []string{"NodeMetrics"}
|
||||||
|
|
||||||
func (ec *executionContext) _NodeMetrics(ctx context.Context, sel ast.SelectionSet, obj *model.NodeMetrics) graphql.Marshaler {
|
func (ec *executionContext) _NodeMetrics(ctx context.Context, sel ast.SelectionSet, obj *model.NodeMetrics) graphql.Marshaler {
|
||||||
@ -7971,8 +7863,8 @@ func (ec *executionContext) _NodeMetrics(ctx context.Context, sel ast.SelectionS
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "__typename":
|
case "__typename":
|
||||||
out.Values[i] = graphql.MarshalString("NodeMetrics")
|
out.Values[i] = graphql.MarshalString("NodeMetrics")
|
||||||
case "id":
|
case "host":
|
||||||
out.Values[i] = ec._NodeMetrics_id(ctx, field, obj)
|
out.Values[i] = ec._NodeMetrics_host(ctx, field, obj)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
invalids++
|
invalids++
|
||||||
}
|
}
|
||||||
@ -9310,53 +9202,6 @@ func (ec *executionContext) marshalNMetricScope2githubᚗcomᚋClusterCockpitᚋ
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) marshalNNodeMetric2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋgraphᚋmodelᚐNodeMetricᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NodeMetric) graphql.Marshaler {
|
|
||||||
ret := make(graphql.Array, len(v))
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
isLen1 := len(v) == 1
|
|
||||||
if !isLen1 {
|
|
||||||
wg.Add(len(v))
|
|
||||||
}
|
|
||||||
for i := range v {
|
|
||||||
i := i
|
|
||||||
fc := &graphql.FieldContext{
|
|
||||||
Index: &i,
|
|
||||||
Result: &v[i],
|
|
||||||
}
|
|
||||||
ctx := graphql.WithFieldContext(ctx, fc)
|
|
||||||
f := func(i int) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
ret = nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if !isLen1 {
|
|
||||||
defer wg.Done()
|
|
||||||
}
|
|
||||||
ret[i] = ec.marshalNNodeMetric2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋgraphᚋmodelᚐNodeMetric(ctx, sel, v[i])
|
|
||||||
}
|
|
||||||
if isLen1 {
|
|
||||||
f(i)
|
|
||||||
} else {
|
|
||||||
go f(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) marshalNNodeMetric2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋgraphᚋmodelᚐNodeMetric(ctx context.Context, sel ast.SelectionSet, v *model.NodeMetric) graphql.Marshaler {
|
|
||||||
if v == nil {
|
|
||||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
|
||||||
ec.Errorf(ctx, "must not be null")
|
|
||||||
}
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
return ec._NodeMetric(ctx, sel, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) marshalNNodeMetrics2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋgraphᚋmodelᚐNodeMetricsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NodeMetrics) graphql.Marshaler {
|
func (ec *executionContext) marshalNNodeMetrics2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋgraphᚋmodelᚐNodeMetricsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NodeMetrics) graphql.Marshaler {
|
||||||
ret := make(graphql.Array, len(v))
|
ret := make(graphql.Array, len(v))
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
type Cluster struct {
|
type Cluster struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
MetricConfig []*MetricConfig `json:"metricConfig"`
|
MetricConfig []*MetricConfig `json:"metricConfig"`
|
||||||
@ -76,3 +78,15 @@ func (topo *Topology) GetCoresFromHWThreads(hwthreads []int) (cores []int, exclu
|
|||||||
|
|
||||||
return cores, exclusive
|
return cores, exclusive
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (topo *Topology) GetAcceleratorIDs() ([]int, error) {
|
||||||
|
accels := make([]int, 0)
|
||||||
|
for _, accel := range topo.Accelerators {
|
||||||
|
id, err := strconv.Atoi(accel.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
accels = append(accels, id)
|
||||||
|
}
|
||||||
|
return accels, nil
|
||||||
|
}
|
||||||
|
@ -101,14 +101,9 @@ type MetricFootprints struct {
|
|||||||
Footprints []schema.Float `json:"footprints"`
|
Footprints []schema.Float `json:"footprints"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeMetric struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Data []schema.Float `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type NodeMetrics struct {
|
type NodeMetrics struct {
|
||||||
ID string `json:"id"`
|
Host string `json:"host"`
|
||||||
Metrics []*NodeMetric `json:"metrics"`
|
Metrics []*JobMetricWithName `json:"metrics"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrderByInput struct {
|
type OrderByInput struct {
|
||||||
|
@ -121,14 +121,9 @@ type MetricFootprints {
|
|||||||
|
|
||||||
enum Aggregate { USER, PROJECT, CLUSTER }
|
enum Aggregate { USER, PROJECT, CLUSTER }
|
||||||
|
|
||||||
type NodeMetric {
|
|
||||||
name: String!
|
|
||||||
data: [NullableFloat!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type NodeMetrics {
|
type NodeMetrics {
|
||||||
id: String!
|
host: String!
|
||||||
metrics: [NodeMetric!]!
|
metrics: [JobMetricWithName!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
@ -144,7 +139,7 @@ type Query {
|
|||||||
|
|
||||||
rooflineHeatmap(filter: [JobFilter!]!, rows: Int!, cols: Int!, minX: Float!, minY: Float!, maxX: Float!, maxY: Float!): [[Float!]!]!
|
rooflineHeatmap(filter: [JobFilter!]!, rows: Int!, cols: Int!, minX: Float!, minY: Float!, maxX: Float!, maxY: Float!): [[Float!]!]!
|
||||||
|
|
||||||
nodeMetrics(cluster: ID!, nodes: [String!], metrics: [String!], from: Time!, to: Time!): [NodeMetrics!]!
|
nodeMetrics(cluster: String!, partition: String!, nodes: [String!], scopes: [String!], metrics: [String!], from: Time!, to: Time!): [NodeMetrics!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
@ -207,34 +207,13 @@ func (r *queryResolver) RooflineHeatmap(ctx context.Context, filter []*model.Job
|
|||||||
return r.rooflineHeatmap(ctx, filter, rows, cols, minX, minY, maxX, maxY)
|
return r.rooflineHeatmap(ctx, filter, rows, cols, minX, minY, maxX, maxY)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) NodeMetrics(ctx context.Context, cluster string, nodes []string, metrics []string, from time.Time, to time.Time) ([]*model.NodeMetrics, error) {
|
func (r *queryResolver) NodeMetrics(ctx context.Context, cluster string, partition string, nodes []string, scopes []string, metrics []string, from time.Time, to time.Time) ([]*model.NodeMetrics, error) {
|
||||||
user := auth.GetUser(ctx)
|
user := auth.GetUser(ctx)
|
||||||
if user != nil && !user.HasRole(auth.RoleAdmin) {
|
if user != nil && !user.HasRole(auth.RoleAdmin) {
|
||||||
return nil, errors.New("you need to be an administrator for this query")
|
return nil, errors.New("you need to be an administrator for this query")
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := metricdata.LoadNodeData(cluster, metrics, nodes, from.Unix(), to.Unix(), ctx)
|
return nil, nil
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
res := make([]*model.NodeMetrics, 0, len(data))
|
|
||||||
for node, metrics := range data {
|
|
||||||
nodeMetrics := make([]*model.NodeMetric, 0, len(metrics))
|
|
||||||
for metric, data := range metrics {
|
|
||||||
nodeMetrics = append(nodeMetrics, &model.NodeMetric{
|
|
||||||
Name: metric,
|
|
||||||
Data: data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
res = append(res, &model.NodeMetrics{
|
|
||||||
ID: node,
|
|
||||||
Metrics: nodeMetrics,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Job returns generated.JobResolver implementation.
|
// Job returns generated.JobResolver implementation.
|
||||||
|
@ -449,11 +449,12 @@ func (ccms *CCMetricStore) LoadStats(job *schema.Job, metrics []string, ctx cont
|
|||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ccms *CCMetricStore) LoadNodeData(clusterId string, metrics, nodes []string, from, to int64, ctx context.Context) (map[string]map[string][]schema.Float, error) {
|
// TODO: Support sub-node-scope metrics! For this, the partition of a node needs to be known!
|
||||||
|
func (ccms *CCMetricStore) LoadNodeData(cluster, partition string, metrics, nodes []string, scopes []schema.MetricScope, from, to time.Time, ctx context.Context) (map[string]map[string][]*schema.JobMetric, error) {
|
||||||
req := ApiQueryRequest{
|
req := ApiQueryRequest{
|
||||||
Cluster: clusterId,
|
Cluster: cluster,
|
||||||
From: from,
|
From: from.Unix(),
|
||||||
To: to,
|
To: to.Unix(),
|
||||||
WithStats: false,
|
WithStats: false,
|
||||||
WithData: true,
|
WithData: true,
|
||||||
}
|
}
|
||||||
@ -476,21 +477,34 @@ func (ccms *CCMetricStore) LoadNodeData(clusterId string, metrics, nodes []strin
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make(map[string]map[string][]schema.Float)
|
_ = resBody
|
||||||
|
data := make(map[string]map[string][]*schema.JobMetric)
|
||||||
for i, res := range resBody {
|
for i, res := range resBody {
|
||||||
query := req.Queries[i]
|
query := req.Queries[i]
|
||||||
|
metric := ccms.toLocalName(query.Metric)
|
||||||
qdata := res[0]
|
qdata := res[0]
|
||||||
if qdata.Error != nil {
|
if qdata.Error != nil {
|
||||||
return nil, fmt.Errorf("fetching %s for node %s failed: %s", query.Metric, query.Hostname, *qdata.Error)
|
return nil, fmt.Errorf("fetching %s for node %s failed: %s", query.Metric, query.Hostname, *qdata.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
nodedata, ok := data[query.Hostname]
|
hostdata, ok := data[query.Hostname]
|
||||||
if !ok {
|
if !ok {
|
||||||
nodedata = make(map[string][]schema.Float)
|
hostdata = make(map[string][]*schema.JobMetric)
|
||||||
data[query.Hostname] = nodedata
|
data[query.Hostname] = hostdata
|
||||||
}
|
}
|
||||||
|
|
||||||
nodedata[ccms.toLocalName(query.Metric)] = qdata.Data
|
mc := config.GetMetricConfig(cluster, metric)
|
||||||
|
hostdata[query.Metric] = append(hostdata[query.Metric], &schema.JobMetric{
|
||||||
|
Unit: mc.Unit,
|
||||||
|
Scope: schema.MetricScopeNode,
|
||||||
|
Timestep: mc.Timestep,
|
||||||
|
Series: []schema.Series{
|
||||||
|
{
|
||||||
|
Hostname: query.Hostname,
|
||||||
|
Data: qdata.Data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
|
@ -21,8 +21,8 @@ type MetricDataRepository interface {
|
|||||||
// Return a map of metrics to a map of nodes to the metric statistics of the job. node scope assumed for now.
|
// Return a map of metrics to a map of nodes to the metric statistics of the job. node scope assumed for now.
|
||||||
LoadStats(job *schema.Job, metrics []string, ctx context.Context) (map[string]map[string]schema.MetricStatistics, error)
|
LoadStats(job *schema.Job, metrics []string, ctx context.Context) (map[string]map[string]schema.MetricStatistics, error)
|
||||||
|
|
||||||
// Return a map of nodes to a map of metrics to the data for the requested time.
|
// Return a map of hosts to a map of metrics at the requested scopes for that node.
|
||||||
LoadNodeData(clusterId string, metrics, nodes []string, from, to int64, ctx context.Context) (map[string]map[string][]schema.Float, error)
|
LoadNodeData(cluster, partition string, metrics, nodes []string, scopes []schema.MetricScope, from, to time.Time, ctx context.Context) (map[string]map[string][]*schema.JobMetric, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var metricDataRepos map[string]MetricDataRepository = map[string]MetricDataRepository{}
|
var metricDataRepos map[string]MetricDataRepository = map[string]MetricDataRepository{}
|
||||||
@ -152,26 +152,26 @@ func LoadAverages(job *schema.Job, metrics []string, data [][]schema.Float, ctx
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for the node/system view. Returns a map of nodes to a map of metrics (at node scope).
|
// Used for the node/system view. Returns a map of nodes to a map of metrics.
|
||||||
func LoadNodeData(clusterId string, metrics, nodes []string, from, to int64, ctx context.Context) (map[string]map[string][]schema.Float, error) {
|
func LoadNodeData(cluster, partition string, metrics, nodes []string, scopes []schema.MetricScope, from, to time.Time, ctx context.Context) (map[string]map[string][]*schema.JobMetric, error) {
|
||||||
repo, ok := metricDataRepos[clusterId]
|
repo, ok := metricDataRepos[cluster]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("no metric data repository configured for '%s'", clusterId)
|
return nil, fmt.Errorf("no metric data repository configured for '%s'", cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
if metrics == nil {
|
if metrics == nil {
|
||||||
for _, m := range config.GetClusterConfig(clusterId).MetricConfig {
|
for _, m := range config.GetClusterConfig(cluster).MetricConfig {
|
||||||
metrics = append(metrics, m.Name)
|
metrics = append(metrics, m.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := repo.LoadNodeData(clusterId, metrics, nodes, from, to, ctx)
|
data, err := repo.LoadNodeData(cluster, partition, metrics, nodes, scopes, from, to, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if data == nil {
|
if data == nil {
|
||||||
return nil, fmt.Errorf("the metric data repository for '%s' does not support this query", clusterId)
|
return nil, fmt.Errorf("the metric data repository for '%s' does not support this query", cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
|
@ -2,6 +2,7 @@ package metricdata
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ClusterCockpit/cc-backend/schema"
|
"github.com/ClusterCockpit/cc-backend/schema"
|
||||||
)
|
)
|
||||||
@ -31,6 +32,6 @@ func (tmdr *TestMetricDataRepository) LoadStats(job *schema.Job, metrics []strin
|
|||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tmdr *TestMetricDataRepository) LoadNodeData(clusterId string, metrics, nodes []string, from, to int64, ctx context.Context) (map[string]map[string][]schema.Float, error) {
|
func (tmdr *TestMetricDataRepository) LoadNodeData(cluster, partition string, metrics, nodes []string, scopes []schema.MetricScope, from, to time.Time, ctx context.Context) (map[string]map[string][]*schema.JobMetric, error) {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user