mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-12-26 13:29:05 +01:00
Add running/total job count to home
This commit is contained in:
parent
19b2b6c2a9
commit
62e776ef7d
@ -96,6 +96,47 @@ func (r *JobRepository) Stop(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountJobs returns the number of jobs for the specified user (if a non-admin user is found in that context) and state.
|
||||||
|
// The counts are grouped by cluster.
|
||||||
|
func (r *JobRepository) CountJobs(ctx context.Context, state *schema.JobState) (map[string]int, error) {
|
||||||
|
// q := sq.Select("count(*)").From("job")
|
||||||
|
// if cluster != nil {
|
||||||
|
// q = q.Where("job.cluster = ?", cluster)
|
||||||
|
// }
|
||||||
|
// if state != nil {
|
||||||
|
// q = q.Where("job.job_state = ?", string(*state))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// err = q.RunWith(r.DB).QueryRow().Scan(&count)
|
||||||
|
// return
|
||||||
|
|
||||||
|
q := sq.Select("job.cluster, count(*)").From("job").GroupBy("job.cluster")
|
||||||
|
if state != nil {
|
||||||
|
q = q.Where("job.job_state = ?", string(*state))
|
||||||
|
}
|
||||||
|
if user := auth.GetUser(ctx); user != nil && !user.HasRole(auth.RoleAdmin) {
|
||||||
|
q = q.Where("job.user = ?", user.Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
counts := map[string]int{}
|
||||||
|
rows, err := q.RunWith(r.DB).Query()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var cluster string
|
||||||
|
var count int
|
||||||
|
if err := rows.Scan(&cluster, &count); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
counts[cluster] = count
|
||||||
|
}
|
||||||
|
|
||||||
|
return counts, nil
|
||||||
|
}
|
||||||
|
|
||||||
// func (r *JobRepository) Query(
|
// func (r *JobRepository) Query(
|
||||||
// filters []*model.JobFilter,
|
// filters []*model.JobFilter,
|
||||||
// page *model.PageRequest,
|
// page *model.PageRequest,
|
||||||
|
40
server.go
40
server.go
@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/ClusterCockpit/cc-backend/log"
|
"github.com/ClusterCockpit/cc-backend/log"
|
||||||
"github.com/ClusterCockpit/cc-backend/metricdata"
|
"github.com/ClusterCockpit/cc-backend/metricdata"
|
||||||
"github.com/ClusterCockpit/cc-backend/repository"
|
"github.com/ClusterCockpit/cc-backend/repository"
|
||||||
|
"github.com/ClusterCockpit/cc-backend/schema"
|
||||||
"github.com/ClusterCockpit/cc-backend/templates"
|
"github.com/ClusterCockpit/cc-backend/templates"
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
@ -121,6 +122,38 @@ var programConfig ProgramConfig = ProgramConfig{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupHomeRoute(i InfoType, r *http.Request) InfoType {
|
||||||
|
type cluster struct {
|
||||||
|
Name string
|
||||||
|
RunningJobs int
|
||||||
|
TotalJobs int
|
||||||
|
}
|
||||||
|
|
||||||
|
state := schema.JobStateRunning
|
||||||
|
runningJobs, err := jobRepo.CountJobs(r.Context(), &state)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to count jobs: %s", err.Error())
|
||||||
|
runningJobs = map[string]int{}
|
||||||
|
}
|
||||||
|
totalJobs, err := jobRepo.CountJobs(r.Context(), nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to count jobs: %s", err.Error())
|
||||||
|
totalJobs = map[string]int{}
|
||||||
|
}
|
||||||
|
|
||||||
|
clusters := make([]cluster, 0)
|
||||||
|
for _, c := range config.Clusters {
|
||||||
|
clusters = append(clusters, cluster{
|
||||||
|
Name: c.Name,
|
||||||
|
RunningJobs: runningJobs[c.Name],
|
||||||
|
TotalJobs: totalJobs[c.Name],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
i["clusters"] = clusters
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
func setupJobRoute(i InfoType, r *http.Request) InfoType {
|
func setupJobRoute(i InfoType, r *http.Request) InfoType {
|
||||||
i["id"] = mux.Vars(r)["id"]
|
i["id"] = mux.Vars(r)["id"]
|
||||||
return i
|
return i
|
||||||
@ -189,7 +222,7 @@ func setupTaglistRoute(i InfoType, r *http.Request) InfoType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var routes []Route = []Route{
|
var routes []Route = []Route{
|
||||||
{"/", "home.tmpl", "ClusterCockpit", false, func(i InfoType, r *http.Request) InfoType { i["clusters"] = config.Clusters; return i }},
|
{"/", "home.tmpl", "ClusterCockpit", false, setupHomeRoute},
|
||||||
{"/monitoring/jobs/", "monitoring/jobs.tmpl", "Jobs - ClusterCockpit", true, func(i InfoType, r *http.Request) InfoType { return i }},
|
{"/monitoring/jobs/", "monitoring/jobs.tmpl", "Jobs - ClusterCockpit", true, func(i InfoType, r *http.Request) InfoType { return i }},
|
||||||
{"/monitoring/job/{id:[0-9]+}", "monitoring/job.tmpl", "Job <ID> - ClusterCockpit", false, setupJobRoute},
|
{"/monitoring/job/{id:[0-9]+}", "monitoring/job.tmpl", "Job <ID> - ClusterCockpit", false, setupJobRoute},
|
||||||
{"/monitoring/users/", "monitoring/list.tmpl", "Users - ClusterCockpit", true, func(i InfoType, r *http.Request) InfoType { i["listType"] = "USER"; return i }},
|
{"/monitoring/users/", "monitoring/list.tmpl", "Users - ClusterCockpit", true, func(i InfoType, r *http.Request) InfoType { i["listType"] = "USER"; return i }},
|
||||||
@ -454,7 +487,10 @@ func main() {
|
|||||||
handlers.AllowedMethods([]string{"GET", "POST", "HEAD", "OPTIONS"}),
|
handlers.AllowedMethods([]string{"GET", "POST", "HEAD", "OPTIONS"}),
|
||||||
handlers.AllowedOrigins([]string{"*"})))
|
handlers.AllowedOrigins([]string{"*"})))
|
||||||
handler := handlers.CustomLoggingHandler(log.InfoWriter, r, func(w io.Writer, params handlers.LogFormatterParams) {
|
handler := handlers.CustomLoggingHandler(log.InfoWriter, r, func(w io.Writer, params handlers.LogFormatterParams) {
|
||||||
log.Finfof(w, "%s %s (Response: %d, Size: %d)", params.Request.Method, params.URL.RequestURI(), params.StatusCode, params.Size)
|
log.Finfof(w, "%s %s (status: %d, size: %d, duration: %dms)",
|
||||||
|
params.Request.Method, params.URL.RequestURI(),
|
||||||
|
params.StatusCode, params.Size,
|
||||||
|
time.Since(params.TimeStamp).Milliseconds())
|
||||||
})
|
})
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
@ -6,19 +6,36 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
|
<th>Running Jobs</th>
|
||||||
|
<th>Total Jobs</th>
|
||||||
<th>Jobs</th>
|
<th>Jobs</th>
|
||||||
<th>System View</th>
|
{{if .User.IsAdmin}}
|
||||||
<th>Analysis View</th>
|
<th>System View</th>
|
||||||
|
<th>Analysis View</th>
|
||||||
|
{{end}}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Infos.clusters}}
|
{{if .User.IsAdmin}}
|
||||||
<tr>
|
{{range .Infos.clusters}}
|
||||||
<td>{{.Name}}</td>
|
<tr>
|
||||||
<td><a href="/monitoring/jobs/?cluster={{.Name}}">Jobs</a></td>
|
<td>{{.Name}}</td>
|
||||||
<td><a href="/monitoring/systems/{{.Name}}">System View</a></td>
|
<td>{{.RunningJobs}}</td>
|
||||||
<td><a href="/monitoring/analysis/{{.Name}}">Analysis View</a></td>
|
<td>{{.TotalJobs}}</td>
|
||||||
</tr>
|
<td><a href="/monitoring/jobs/?cluster={{.Name}}">Jobs</a></td>
|
||||||
|
<td><a href="/monitoring/systems/{{.Name}}">System View</a></td>
|
||||||
|
<td><a href="/monitoring/analysis/{{.Name}}">Analysis View</a></td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
{{else}}
|
||||||
|
{{range .Infos.clusters}}
|
||||||
|
<tr>
|
||||||
|
<td>{{.Name}}</td>
|
||||||
|
<td>{{.RunningJobs}}</td>
|
||||||
|
<td>{{.TotalJobs}}</td>
|
||||||
|
<td><a href="/monitoring/jobs/?cluster={{.Name}}">Jobs</a></td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
Loading…
Reference in New Issue
Block a user