diff --git a/api/schema.graphqls b/api/schema.graphqls
index 8a43a54..aa6aea2 100644
--- a/api/schema.graphqls
+++ b/api/schema.graphqls
@@ -28,6 +28,11 @@ type Job {
resources: [Resource!]!
concurrentJobs: JobLinkResultList
+ memUsedMax: Float
+ flopsAnyAvg: Float
+ memBwAvg: Float
+ loadAvg: Float
+
metaData: Any
userData: User
}
diff --git a/internal/graph/generated/generated.go b/internal/graph/generated/generated.go
index 12d829a..d84f043 100644
--- a/internal/graph/generated/generated.go
+++ b/internal/graph/generated/generated.go
@@ -90,8 +90,12 @@ type ComplexityRoot struct {
ConcurrentJobs func(childComplexity int) int
Duration func(childComplexity int) int
Exclusive func(childComplexity int) int
+ FlopsAnyAvg func(childComplexity int) int
ID func(childComplexity int) int
JobID func(childComplexity int) int
+ LoadAvg func(childComplexity int) int
+ MemBwAvg func(childComplexity int) int
+ MemUsedMax func(childComplexity int) int
MetaData func(childComplexity int) int
MonitoringStatus func(childComplexity int) int
NumAcc func(childComplexity int) int
@@ -319,6 +323,7 @@ type JobResolver interface {
Tags(ctx context.Context, obj *schema.Job) ([]*schema.Tag, error)
ConcurrentJobs(ctx context.Context, obj *schema.Job) (*model.JobLinkResultList, error)
+
MetaData(ctx context.Context, obj *schema.Job) (interface{}, error)
UserData(ctx context.Context, obj *schema.Job) (*model.User, error)
}
@@ -505,6 +510,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Job.Exclusive(childComplexity), true
+ case "Job.flopsAnyAvg":
+ if e.complexity.Job.FlopsAnyAvg == nil {
+ break
+ }
+
+ return e.complexity.Job.FlopsAnyAvg(childComplexity), true
+
case "Job.id":
if e.complexity.Job.ID == nil {
break
@@ -519,6 +531,27 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Job.JobID(childComplexity), true
+ case "Job.loadAvg":
+ if e.complexity.Job.LoadAvg == nil {
+ break
+ }
+
+ return e.complexity.Job.LoadAvg(childComplexity), true
+
+ case "Job.memBwAvg":
+ if e.complexity.Job.MemBwAvg == nil {
+ break
+ }
+
+ return e.complexity.Job.MemBwAvg(childComplexity), true
+
+ case "Job.memUsedMax":
+ if e.complexity.Job.MemUsedMax == nil {
+ break
+ }
+
+ return e.complexity.Job.MemUsedMax(childComplexity), true
+
case "Job.metaData":
if e.complexity.Job.MetaData == nil {
break
@@ -1704,6 +1737,11 @@ type Job {
resources: [Resource!]!
concurrentJobs: JobLinkResultList
+ memUsedMax: Float
+ flopsAnyAvg: Float
+ memBwAvg: Float
+ loadAvg: Float
+
metaData: Any
userData: User
}
@@ -4153,6 +4191,170 @@ func (ec *executionContext) fieldContext_Job_concurrentJobs(ctx context.Context,
return fc, nil
}
+func (ec *executionContext) _Job_memUsedMax(ctx context.Context, field graphql.CollectedField, obj *schema.Job) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Job_memUsedMax(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.MemUsedMax, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(float64)
+ fc.Result = res
+ return ec.marshalOFloat2float64(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Job_memUsedMax(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Job",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Float does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _Job_flopsAnyAvg(ctx context.Context, field graphql.CollectedField, obj *schema.Job) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Job_flopsAnyAvg(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.FlopsAnyAvg, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(float64)
+ fc.Result = res
+ return ec.marshalOFloat2float64(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Job_flopsAnyAvg(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Job",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Float does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _Job_memBwAvg(ctx context.Context, field graphql.CollectedField, obj *schema.Job) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Job_memBwAvg(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.MemBwAvg, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(float64)
+ fc.Result = res
+ return ec.marshalOFloat2float64(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Job_memBwAvg(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Job",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Float does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _Job_loadAvg(ctx context.Context, field graphql.CollectedField, obj *schema.Job) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Job_loadAvg(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.LoadAvg, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(float64)
+ fc.Result = res
+ return ec.marshalOFloat2float64(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Job_loadAvg(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Job",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Float does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
func (ec *executionContext) _Job_metaData(ctx context.Context, field graphql.CollectedField, obj *schema.Job) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Job_metaData(ctx, field)
if err != nil {
@@ -4877,6 +5079,14 @@ func (ec *executionContext) fieldContext_JobResultList_items(ctx context.Context
return ec.fieldContext_Job_resources(ctx, field)
case "concurrentJobs":
return ec.fieldContext_Job_concurrentJobs(ctx, field)
+ case "memUsedMax":
+ return ec.fieldContext_Job_memUsedMax(ctx, field)
+ case "flopsAnyAvg":
+ return ec.fieldContext_Job_flopsAnyAvg(ctx, field)
+ case "memBwAvg":
+ return ec.fieldContext_Job_memBwAvg(ctx, field)
+ case "loadAvg":
+ return ec.fieldContext_Job_loadAvg(ctx, field)
case "metaData":
return ec.fieldContext_Job_metaData(ctx, field)
case "userData":
@@ -7609,6 +7819,14 @@ func (ec *executionContext) fieldContext_Query_job(ctx context.Context, field gr
return ec.fieldContext_Job_resources(ctx, field)
case "concurrentJobs":
return ec.fieldContext_Job_concurrentJobs(ctx, field)
+ case "memUsedMax":
+ return ec.fieldContext_Job_memUsedMax(ctx, field)
+ case "flopsAnyAvg":
+ return ec.fieldContext_Job_flopsAnyAvg(ctx, field)
+ case "memBwAvg":
+ return ec.fieldContext_Job_memBwAvg(ctx, field)
+ case "loadAvg":
+ return ec.fieldContext_Job_loadAvg(ctx, field)
case "metaData":
return ec.fieldContext_Job_metaData(ctx, field)
case "userData":
@@ -12963,6 +13181,14 @@ func (ec *executionContext) _Job(ctx context.Context, sel ast.SelectionSet, obj
}
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
+ case "memUsedMax":
+ out.Values[i] = ec._Job_memUsedMax(ctx, field, obj)
+ case "flopsAnyAvg":
+ out.Values[i] = ec._Job_flopsAnyAvg(ctx, field, obj)
+ case "memBwAvg":
+ out.Values[i] = ec._Job_memBwAvg(ctx, field, obj)
+ case "loadAvg":
+ out.Values[i] = ec._Job_loadAvg(ctx, field, obj)
case "metaData":
field := field
diff --git a/internal/repository/job.go b/internal/repository/job.go
index 76834d1..e1a997a 100644
--- a/internal/repository/job.go
+++ b/internal/repository/job.go
@@ -60,7 +60,7 @@ func GetJobRepository() *JobRepository {
var jobColumns []string = []string{
"job.id", "job.job_id", "job.user", "job.project", "job.cluster", "job.subcluster", "job.start_time", "job.partition", "job.array_job_id",
"job.num_nodes", "job.num_hwthreads", "job.num_acc", "job.exclusive", "job.monitoring_status", "job.smt", "job.job_state",
- "job.duration", "job.walltime", "job.resources", // "job.meta_data",
+ "job.duration", "job.walltime", "job.resources", "job.mem_used_max", "job.flops_any_avg", "job.mem_bw_avg", "job.load_avg", // "job.meta_data",
}
func scanJob(row interface{ Scan(...interface{}) error }) (*schema.Job, error) {
@@ -68,7 +68,7 @@ func scanJob(row interface{ Scan(...interface{}) error }) (*schema.Job, error) {
if err := row.Scan(
&job.ID, &job.JobID, &job.User, &job.Project, &job.Cluster, &job.SubCluster, &job.StartTimeUnix, &job.Partition, &job.ArrayJobId,
&job.NumNodes, &job.NumHWThreads, &job.NumAcc, &job.Exclusive, &job.MonitoringStatus, &job.SMT, &job.State,
- &job.Duration, &job.Walltime, &job.RawResources /*&job.RawMetaData*/); err != nil {
+ &job.Duration, &job.Walltime, &job.RawResources, &job.MemUsedMax, &job.FlopsAnyAvg, &job.MemBwAvg, &job.LoadAvg /*&job.RawMetaData*/); err != nil {
log.Warnf("Error while scanning rows (Job): %v", err)
return nil, err
}
@@ -483,6 +483,7 @@ func (r *JobRepository) MarkArchived(
case "mem_bw":
stmt = stmt.Set("mem_bw_avg", stats.Avg)
case "load":
+ stmt = stmt.Set("load_avg", stats.Avg)
case "cpu_load":
stmt = stmt.Set("load_avg", stats.Avg)
case "net_bw":
diff --git a/pkg/schema/job.go b/pkg/schema/job.go
index ed3a8b6..90bf2cb 100644
--- a/pkg/schema/job.go
+++ b/pkg/schema/job.go
@@ -54,10 +54,10 @@ type Job struct {
BaseJob
StartTimeUnix int64 `json:"-" db:"start_time" example:"1649723812"` // Start epoch time stamp in seconds
StartTime time.Time `json:"startTime"` // Start time as 'time.Time' data type
- MemUsedMax float64 `json:"-" db:"mem_used_max"` // MemUsedMax as Float64
- FlopsAnyAvg float64 `json:"-" db:"flops_any_avg"` // FlopsAnyAvg as Float64
- MemBwAvg float64 `json:"-" db:"mem_bw_avg"` // MemBwAvg as Float64
- LoadAvg float64 `json:"-" db:"load_avg"` // LoadAvg as Float64
+ MemUsedMax float64 `json:"memUsedMax" db:"mem_used_max"` // MemUsedMax as Float64
+ FlopsAnyAvg float64 `json:"flopsAnyAvg" db:"flops_any_avg"` // FlopsAnyAvg as Float64
+ MemBwAvg float64 `json:"memBwAvg" db:"mem_bw_avg"` // MemBwAvg as Float64
+ LoadAvg float64 `json:"loadAvg" db:"load_avg"` // LoadAvg as Float64
NetBwAvg float64 `json:"-" db:"net_bw_avg"` // NetBwAvg as Float64
NetDataVolTotal float64 `json:"-" db:"net_data_vol_total"` // NetDataVolTotal as Float64
FileBwAvg float64 `json:"-" db:"file_bw_avg"` // FileBwAvg as Float64
diff --git a/web/frontend/package-lock.json b/web/frontend/package-lock.json
index f209306..8874caf 100644
--- a/web/frontend/package-lock.json
+++ b/web/frontend/package-lock.json
@@ -13,7 +13,9 @@
"@urql/svelte": "^4.0.1",
"chart.js": "^4.3.3",
"date-fns": "^2.30.0",
+ "date-fns": "^2.30.0",
"graphql": "^16.6.0",
+ "mathjs": "^12.0.0",
"svelte-chartjs": "^3.1.2",
"sveltestrap": "^5.11.1",
"uplot": "^1.6.24",
@@ -102,6 +104,9 @@
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
"node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.20",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
+ "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
"version": "0.3.20",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
"integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
@@ -151,6 +156,9 @@
}
},
"node_modules/@rollup/plugin-node-resolve": {
+ "version": "15.2.3",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz",
+ "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==",
"version": "15.2.3",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz",
"integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==",
@@ -168,6 +176,7 @@
},
"peerDependencies": {
"rollup": "^2.78.0||^3.0.0||^4.0.0"
+ "rollup": "^2.78.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
@@ -176,18 +185,23 @@
}
},
"node_modules/@rollup/plugin-replace": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.5.tgz",
+ "integrity": "sha512-rYO4fOi8lMaTg/z5Jb+hKnrHHVn8j2lwkqwyS4kTRhKyWOLf2wST2sWXr4WzWiTcoHTp2sTjqUbqIj2E39slKQ==",
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.5.tgz",
"integrity": "sha512-rYO4fOi8lMaTg/z5Jb+hKnrHHVn8j2lwkqwyS4kTRhKyWOLf2wST2sWXr4WzWiTcoHTp2sTjqUbqIj2E39slKQ==",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"magic-string": "^0.30.3"
+ "magic-string": "^0.30.3"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
@@ -206,7 +220,21 @@
"node": ">=12"
}
},
+ "node_modules/@rollup/plugin-replace/node_modules/magic-string": {
+ "version": "0.30.5",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
+ "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@rollup/plugin-terser": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
+ "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
@@ -221,6 +249,7 @@
},
"peerDependencies": {
"rollup": "^2.0.0||^3.0.0||^4.0.0"
+ "rollup": "^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
@@ -242,6 +271,7 @@
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
@@ -259,6 +289,9 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
},
"node_modules/@types/resolve": {
"version": "1.20.2",
@@ -288,6 +321,9 @@
}
},
"node_modules/acorn": {
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
+ "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
"version": "8.11.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
"integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
@@ -355,6 +391,18 @@
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
"dev": true
},
+ "node_modules/complex.js": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz",
+ "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://www.patreon.com/infusion"
+ }
+ },
"node_modules/date-fns": {
"version": "2.30.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
@@ -370,6 +418,11 @@
"url": "https://opencollective.com/date-fns"
}
},
+ "node_modules/decimal.js": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
+ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
+ },
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
@@ -379,11 +432,28 @@
"node": ">=0.10.0"
}
},
+ "node_modules/escape-latex": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
+ "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw=="
+ },
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
+ "node_modules/fraction.js": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.4.tgz",
+ "integrity": "sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -412,6 +482,13 @@
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
"node_modules/glob": {
"version": "8.1.0",
@@ -433,6 +510,9 @@
}
},
"node_modules/graphql": {
+ "version": "16.8.1",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz",
+ "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==",
"version": "16.8.1",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz",
"integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==",
@@ -440,6 +520,10 @@
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
},
+ "node_modules/hasown": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
+ "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
"node_modules/hasown": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
@@ -447,9 +531,11 @@
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
+ "function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
+ "node": ">= 0.4"
}
},
"node_modules/inflight": {
@@ -484,12 +570,16 @@
}
},
"node_modules/is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
"integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
"dev": true,
"dependencies": {
"hasown": "^2.0.0"
+ "hasown": "^2.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -510,11 +600,17 @@
"@types/estree": "*"
}
},
+ "node_modules/javascript-natural-sort": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
+ "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="
+ },
"node_modules/magic-string": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz",
"integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==",
"dev": true,
+ "dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.13"
},
@@ -522,6 +618,28 @@
"node": ">=12"
}
},
+ "node_modules/mathjs": {
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-12.0.0.tgz",
+ "integrity": "sha512-Oz3swPplNPe7taoP6WrkKhQzhDE2SwvOgLzu8H3EN+hEadw2GjEJUm6Xl+hrioHoB8g2BYb3gfw1glSzhdBKYw==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2",
+ "complex.js": "^2.1.1",
+ "decimal.js": "^10.4.3",
+ "escape-latex": "^1.2.0",
+ "fraction.js": "4.3.4",
+ "javascript-natural-sort": "^0.7.1",
+ "seedrandom": "^3.0.5",
+ "tiny-emitter": "^2.1.0",
+ "typed-function": "^4.1.1"
+ },
+ "bin": {
+ "mathjs": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/minimatch": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
@@ -574,7 +692,15 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
"integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
},
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
+ },
"node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
@@ -601,6 +727,9 @@
}
},
"node_modules/rollup": {
+ "version": "3.29.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
+ "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
"version": "3.29.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
"integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
@@ -617,6 +746,9 @@
}
},
"node_modules/rollup-plugin-css-only": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-4.5.2.tgz",
+ "integrity": "sha512-7rj9+jB17Pz8LNcPgtMUb16JcgD8lxQMK9HcGfAVhMK3na/WXes3oGIo5QsrQQVqtgAU6q6KnQNXJrYunaUIQQ==",
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-4.5.2.tgz",
"integrity": "sha512-7rj9+jB17Pz8LNcPgtMUb16JcgD8lxQMK9HcGfAVhMK3na/WXes3oGIo5QsrQQVqtgAU6q6KnQNXJrYunaUIQQ==",
@@ -629,6 +761,7 @@
},
"peerDependencies": {
"rollup": "<5"
+ "rollup": "<5"
}
},
"node_modules/rollup-plugin-svelte": {
@@ -681,6 +814,11 @@
}
]
},
+ "node_modules/seedrandom": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
+ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
+ },
"node_modules/serialize-javascript": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
@@ -691,6 +829,9 @@
}
},
"node_modules/smob": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz",
+ "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==",
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz",
"integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==",
@@ -745,6 +886,9 @@
}
},
"node_modules/sveltestrap": {
+ "version": "5.11.2",
+ "resolved": "https://registry.npmjs.org/sveltestrap/-/sveltestrap-5.11.2.tgz",
+ "integrity": "sha512-fkLqIUh2QHBoom7v6kHI85grLeOqplmvtnTiA5Ck2gchzpVmwXWaWpf8qWhCFxfDuMhJBPlWbJvtSmwpDEowrg==",
"version": "5.11.2",
"resolved": "https://registry.npmjs.org/sveltestrap/-/sveltestrap-5.11.2.tgz",
"integrity": "sha512-fkLqIUh2QHBoom7v6kHI85grLeOqplmvtnTiA5Ck2gchzpVmwXWaWpf8qWhCFxfDuMhJBPlWbJvtSmwpDEowrg==",
@@ -773,10 +917,26 @@
"node": ">=10"
}
},
+ "node_modules/tiny-emitter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+ "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+ },
+ "node_modules/typed-function": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.1.tgz",
+ "integrity": "sha512-Pq1DVubcvibmm8bYcMowjVnnMwPVMeh0DIdA8ad8NZY2sJgapANJmiigSUwlt+EgXxpfIv8MWrQXTIzkfYZLYQ==",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/uplot": {
"version": "1.6.27",
"resolved": "https://registry.npmjs.org/uplot/-/uplot-1.6.27.tgz",
"integrity": "sha512-78U4ss5YeU65kQkOC/QAKiyII+4uo+TYUJJKvuxRzeSpk/s5sjpY1TL0agkmhHBBShpvLtmbHIEiM7+C5lBULg=="
+ "version": "1.6.27",
+ "resolved": "https://registry.npmjs.org/uplot/-/uplot-1.6.27.tgz",
+ "integrity": "sha512-78U4ss5YeU65kQkOC/QAKiyII+4uo+TYUJJKvuxRzeSpk/s5sjpY1TL0agkmhHBBShpvLtmbHIEiM7+C5lBULg=="
},
"node_modules/wonka": {
"version": "6.3.4",
diff --git a/web/frontend/package.json b/web/frontend/package.json
index 725f69a..cc84e1a 100644
--- a/web/frontend/package.json
+++ b/web/frontend/package.json
@@ -22,6 +22,7 @@
"chart.js": "^4.3.3",
"date-fns": "^2.30.0",
"graphql": "^16.6.0",
+ "mathjs": "^12.0.0",
"svelte-chartjs": "^3.1.2",
"sveltestrap": "^5.11.1",
"uplot": "^1.6.24",
diff --git a/web/frontend/src/Job.root.svelte b/web/frontend/src/Job.root.svelte
index 8369726..42cfee8 100644
--- a/web/frontend/src/Job.root.svelte
+++ b/web/frontend/src/Job.root.svelte
@@ -27,6 +27,7 @@
import TagManagement from "./TagManagement.svelte";
import MetricSelection from "./MetricSelection.svelte";
import StatsTable from "./StatsTable.svelte";
+ import JobFootprint from "./JobFootprint.svelte";
import { getContext } from "svelte";
export let dbid;
@@ -46,7 +47,8 @@
resources { hostname, hwthreads, accelerators },
metaData,
userData { name, email },
- concurrentJobs { items { id, jobId }, count, listQuery }
+ concurrentJobs { items { id, jobId }, count, listQuery },
+ flopsAnyAvg, memBwAvg, loadAvg
}
`);
@@ -134,7 +136,9 @@
let plots = {},
jobTags,
- statsTable;
+ statsTable,
+ jobFootprint;
+
$: document.title = $initq.fetching
? "Loading..."
: $initq.error
@@ -202,6 +206,17 @@