add table to compareview, remove debug data view

This commit is contained in:
Christoph Kluge 2025-05-08 15:21:05 +02:00
parent c119eeb468
commit 9ebc49dd1c
5 changed files with 136 additions and 25 deletions

View File

@ -171,7 +171,8 @@ type ScopedStats {
} }
type JobStats { type JobStats {
jobId: Int! id: Int!
jobId: String!
startTime: Int! startTime: Int!
duration: Int! duration: Int!
cluster: String! cluster: String!

View File

@ -173,6 +173,7 @@ type ComplexityRoot struct {
JobStats struct { JobStats struct {
Cluster func(childComplexity int) int Cluster func(childComplexity int) int
Duration func(childComplexity int) int Duration func(childComplexity int) int
ID func(childComplexity int) int
JobID func(childComplexity int) int JobID func(childComplexity int) int
NumAccelerators func(childComplexity int) int NumAccelerators func(childComplexity int) int
NumHWThreads func(childComplexity int) int NumHWThreads func(childComplexity int) int
@ -961,6 +962,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.JobStats.Duration(childComplexity), true return e.complexity.JobStats.Duration(childComplexity), true
case "JobStats.id":
if e.complexity.JobStats.ID == nil {
break
}
return e.complexity.JobStats.ID(childComplexity), true
case "JobStats.jobId": case "JobStats.jobId":
if e.complexity.JobStats.JobID == nil { if e.complexity.JobStats.JobID == nil {
break break
@ -2336,7 +2344,8 @@ type ScopedStats {
} }
type JobStats { type JobStats {
jobId: Int! id: Int!
jobId: String!
startTime: Int! startTime: Int!
duration: Int! duration: Int!
cluster: String! cluster: String!
@ -7419,6 +7428,50 @@ func (ec *executionContext) fieldContext_JobResultList_hasNextPage(_ context.Con
return fc, nil return fc, nil
} }
func (ec *executionContext) _JobStats_id(ctx context.Context, field graphql.CollectedField, obj *model.JobStats) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_JobStats_id(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) (any, error) {
ctx = rctx // use context from middleware stack in children
return obj.ID, 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.(int)
fc.Result = res
return ec.marshalNInt2int(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_JobStats_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "JobStats",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Int does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _JobStats_jobId(ctx context.Context, field graphql.CollectedField, obj *model.JobStats) (ret graphql.Marshaler) { func (ec *executionContext) _JobStats_jobId(ctx context.Context, field graphql.CollectedField, obj *model.JobStats) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_JobStats_jobId(ctx, field) fc, err := ec.fieldContext_JobStats_jobId(ctx, field)
if err != nil { if err != nil {
@ -7445,9 +7498,9 @@ func (ec *executionContext) _JobStats_jobId(ctx context.Context, field graphql.C
} }
return graphql.Null return graphql.Null
} }
res := resTmp.(int) res := resTmp.(string)
fc.Result = res fc.Result = res
return ec.marshalNInt2int(ctx, field.Selections, res) return ec.marshalNString2string(ctx, field.Selections, res)
} }
func (ec *executionContext) fieldContext_JobStats_jobId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { func (ec *executionContext) fieldContext_JobStats_jobId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@ -7457,7 +7510,7 @@ func (ec *executionContext) fieldContext_JobStats_jobId(_ context.Context, field
IsMethod: false, IsMethod: false,
IsResolver: false, IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Int does not have child fields") return nil, errors.New("field of type String does not have child fields")
}, },
} }
return fc, nil return fc, nil
@ -11560,6 +11613,8 @@ func (ec *executionContext) fieldContext_Query_jobsMetricStats(ctx context.Conte
IsResolver: true, IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name { switch field.Name {
case "id":
return ec.fieldContext_JobStats_id(ctx, field)
case "jobId": case "jobId":
return ec.fieldContext_JobStats_jobId(ctx, field) return ec.fieldContext_JobStats_jobId(ctx, field)
case "startTime": case "startTime":
@ -17901,6 +17956,11 @@ func (ec *executionContext) _JobStats(ctx context.Context, sel ast.SelectionSet,
switch field.Name { switch field.Name {
case "__typename": case "__typename":
out.Values[i] = graphql.MarshalString("JobStats") out.Values[i] = graphql.MarshalString("JobStats")
case "id":
out.Values[i] = ec._JobStats_id(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "jobId": case "jobId":
out.Values[i] = ec._JobStats_jobId(ctx, field, obj) out.Values[i] = ec._JobStats_jobId(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {

View File

@ -97,7 +97,8 @@ type JobResultList struct {
} }
type JobStats struct { type JobStats struct {
JobID int `json:"jobId"` ID int `json:"id"`
JobID string `json:"jobId"`
StartTime int `json:"startTime"` StartTime int `json:"startTime"`
Duration int `json:"duration"` Duration int `json:"duration"`
Cluster string `json:"cluster"` Cluster string `json:"cluster"`

View File

@ -618,7 +618,8 @@ func (r *queryResolver) JobsMetricStats(ctx context.Context, filter []*model.Job
numThreadsInt := int(job.NumHWThreads) numThreadsInt := int(job.NumHWThreads)
numAccsInt := int(job.NumAcc) numAccsInt := int(job.NumAcc)
res = append(res, &model.JobStats{ res = append(res, &model.JobStats{
JobID: int(job.JobID), ID: int(job.ID),
JobID: strconv.Itoa(int(job.JobID)),
StartTime: int(job.StartTime.Unix()), StartTime: int(job.StartTime.Unix()),
Duration: int(job.Duration), Duration: int(job.Duration),
Cluster: job.Cluster, Cluster: job.Cluster,

View File

@ -22,7 +22,7 @@
getContextClient, getContextClient,
// mutationStore, // mutationStore,
} from "@urql/svelte"; } from "@urql/svelte";
import { Row, Col, Card, Spinner } from "@sveltestrap/sveltestrap"; import { Row, Col, Card, Spinner, Table, Input, InputGroup, InputGroupText, Icon } from "@sveltestrap/sveltestrap";
import { formatTime } from "./units.js"; import { formatTime } from "./units.js";
import Comparogram from "./plots/Comparogram.svelte"; import Comparogram from "./plots/Comparogram.svelte";
@ -42,6 +42,7 @@
let comparePlotData = {}; let comparePlotData = {};
let jobIds = []; let jobIds = [];
let jobClusters = []; let jobClusters = [];
let tableJobIDFilter = "";
/*uPlot*/ /*uPlot*/
let plotSync = uPlot.sync("compareJobsView"); let plotSync = uPlot.sync("compareJobsView");
@ -52,6 +53,7 @@
const compareQuery = gql` const compareQuery = gql`
query ($filter: [JobFilter!]!, $metrics: [String!]!) { query ($filter: [JobFilter!]!, $metrics: [String!]!) {
jobsMetricStats(filter: $filter, metrics: $metrics) { jobsMetricStats(filter: $filter, metrics: $metrics) {
id
jobId jobId
startTime startTime
duration duration
@ -234,21 +236,67 @@
</Row> </Row>
{/each} {/each}
{/key} {/key}
<hr/><hr/> <hr/>
{#each $compareData.data.jobsMetricStats as job, jindex (job.jobId)} <Card>
<Row> <Table hover>
<Col><b>{jindex}: <i>{job.jobId}</i></b></Col> <thead>
<Col><i>{new Date(job.startTime * 1000).toISOString()}</i></Col> <!-- Header Row 1 -->
<Col><i>{formatTime(job.duration)}</i></Col> <tr>
{#each job.stats as stat (stat.name)} <th>Index</th>
<Col><b>{stat.name}</b></Col> <th style="width:10%">JobID</th>
<Col>Min {stat.data.min}</Col> <th>Cluster</th>
<Col>Avg {stat.data.avg}</Col> <th>StartTime</th>
<Col>Max {stat.data.max}</Col> <th>Duration</th>
{/each} <th colspan="3">Resources</th>
</Row> {#each metrics as metric}
<hr/> <th colspan="3">{metric}</th>
{:else} {/each}
<div> No jobs found </div> </tr>
{/each} <!-- Header Row 2: Fields -->
<tr>
<th/>
<th style="width:10%">
<InputGroup>
<InputGroupText>
<Icon name="search"></Icon>
</InputGroupText>
<Input type="text" bind:value={tableJobIDFilter}/>
</InputGroup>
</th>
<th/>
<th/>
<th/>
{#each ["Nodes", "Threads", "Accs"] as res}
<th>{res}</th>
{/each}
{#each metrics as metric}
{#each ["min", "avg", "max"] as stat}
<th>{stat}</th>
{/each}
{/each}
</tr>
</thead>
<tbody>
{#each $compareData.data.jobsMetricStats.filter((j) => j.jobId.includes(tableJobIDFilter)) as job, jindex (job.jobId)}
<tr>
<td>{jindex}</td>
<td><a href="/monitoring/job/{job.id}" target="_blank">{job.jobId}</a></td>
<td>{job.cluster} ({job.subCluster})</td>
<td>{new Date(job.startTime * 1000).toISOString()}</td>
<td>{formatTime(job.duration)}</td>
<td>{job.numNodes}</td>
<td>{job.numHWThreads}</td>
<td>{job.numAccelerators}</td>
{#each metrics as metric}
<td>{job.stats.find((s) => s.name == metric).data.min}</td>
<td>{job.stats.find((s) => s.name == metric).data.avg}</td>
<td>{job.stats.find((s) => s.name == metric).data.max}</td>
{/each}
</tr>
{:else}
<tr> No jobs found </tr>
{/each}
</tbody>
</Table>
</Card>
{/if} {/if}