cmd/coordinator: add more information to queues UI

This change adds the branch and how long an item has been in the queue.

Change-Id: I05e7c466119c04c68ed4ef3882f23c5fb1ce0c3d
Reviewed-on: https://go-review.googlesource.com/c/build/+/420754
Run-TryBot: Jenny Rakoczy <jenny@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Jenny Rakoczy <jenny@golang.org>
This commit is contained in:
Alex Rakoczy 2022-07-28 16:09:37 -04:00 коммит произвёл Gopher Robot
Родитель b196ddadc4
Коммит fdd64c3913
6 изменённых файлов: 162 добавлений и 9 удалений

Просмотреть файл

@ -284,6 +284,7 @@ func (st *buildStatus) onceInitHelpersFunc() {
IsTry: st.isTry(),
CommitTime: st.commitTime(),
Branch: st.branch(),
Repo: st.RepoOrGo(),
User: st.AuthorEmail,
}
st.helpers = getBuildlets(st.ctx, st.conf.NumTestHelpers(st.isTry()), schedTmpl, st)
@ -379,6 +380,7 @@ func (st *buildStatus) getBuildlet() (buildlet.Client, error) {
IsTry: st.trySet != nil,
BuilderRev: st.BuilderRev,
CommitTime: st.commitTime(),
Repo: st.RepoOrGo(),
Branch: st.branch(),
User: st.AuthorEmail,
}
@ -701,6 +703,7 @@ func (st *buildStatus) crossCompileMakeAndSnapshot(config *dashboard.CrossCompil
IsTry: st.trySet != nil,
BuilderRev: st.BuilderRev,
CommitTime: st.commitTime(),
Repo: st.RepoOrGo(),
Branch: st.branch(),
User: st.AuthorEmail,
})

Просмотреть файл

@ -13,6 +13,7 @@ import (
"html/template"
"log"
"net/http"
"time"
"golang.org/x/build/internal/coordinator/pool"
"golang.org/x/build/internal/coordinator/pool/queue"
@ -21,7 +22,10 @@ import (
//go:embed templates/queues.html
var queuesTemplateStr string
var queuesTemplate = template.Must(baseTmpl.New("queues.html").Parse(queuesTemplateStr))
var queuesTemplate = template.Must(baseTmpl.New("queues.html").Funcs(map[string]interface{}{
"timeSince": timeSince,
"humanDuration": humanDuration,
}).Parse(queuesTemplateStr))
type QueuesResponse struct {
Queues map[string]*queue.QuotaStats
@ -41,3 +45,94 @@ func handleQueues(w http.ResponseWriter, _ *http.Request) {
log.Printf("handleQueues: %v", err)
}
}
func timeSince(t time.Time) time.Duration {
return time.Since(t)
}
// humanDuration is largely time.Duration's formatting, but modified
// to imprecisely format days, even though days may vary in length
// due to daylight savings time. Sub-second durations are
// represented as 0s.
func humanDuration(d time.Duration) string {
var buf [32]byte
w := len(buf)
u := uint64(d)
neg := d < 0
if neg {
u = -u
}
w--
buf[w] = 's'
_, u = fmtFrac(buf[:w], u, 9)
// u is now integer seconds
w = fmtInt(buf[:w], u%60)
u /= 60
// u is now integer minutes
if u > 0 {
w--
buf[w] = 'm'
w = fmtInt(buf[:w], u%60)
u /= 60
// u is now integer hours
if u > 0 {
w--
buf[w] = 'h'
w = fmtInt(buf[:w], u%24)
u /= 24
if u > 0 {
w--
buf[w] = 'd'
w = fmtInt(buf[:w], u)
}
}
}
if neg {
w--
buf[w] = '-'
}
return string(buf[w:])
}
// fmtFrac is identical to fmtFrac in the time package.
func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) {
// Omit trailing zeros up to and including decimal point.
w := len(buf)
print := false
for i := 0; i < prec; i++ {
digit := v % 10
print = print || digit != 0
if print {
w--
buf[w] = byte(digit) + '0'
}
v /= 10
}
if print {
w--
buf[w] = '.'
}
return w, v
}
// fmtFrac is identical to fmtInt in the time package.
func fmtInt(buf []byte, v uint64) int {
w := len(buf)
if v == 0 {
w--
buf[w] = '0'
} else {
for v > 0 {
w--
buf[w] = byte(v%10) + '0'
v /= 10
}
}
return w
}

Просмотреть файл

@ -0,0 +1,49 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16 && (linux || darwin)
// +build go1.16
// +build linux darwin
package main
import (
"testing"
"time"
)
func TestHumanDuration(t *testing.T) {
cases := []struct {
desc string
duration string
want string
}{
{
desc: "format days",
duration: "99h2m1s",
want: "4d3h2m1s",
},
{
desc: "handle tiny durations",
duration: "1ns",
want: "0s",
},
{
desc: "handle seconds",
duration: "3s",
want: "3s",
},
}
for _, c := range cases {
t.Run(c.duration, func(t *testing.T) {
d, err := time.ParseDuration(c.duration)
if err != nil {
t.Fatalf("time.ParseDuration(%q) = %q, %q, wanted no error", c.duration, d, err)
}
if got := humanDuration(d); got != c.want {
t.Errorf("humanDuration(%v) = %q, wanted %q", d, got, c.want)
}
})
}
}

Просмотреть файл

@ -197,5 +197,5 @@ table.Build tbody tr.commit:hover {
border: 0.0625rem solid #d6d6d6;
border-radius: 0.1875rem;
margin: 1rem;
width: 31rem;
width: 44rem;
}

Просмотреть файл

@ -25,9 +25,11 @@
<thead>
<tr>
<th class="QueueStats-queueTableHeader">Name</th>
<th class="QueueStats-queueTableHeader">Branch</th>
<th class="QueueStats-queueTableHeader">Cost</th>
<th class="QueueStats-queueTableHeader">Type/Priority</th>
<th class="QueueStats-queueTableHeader">Priority</th>
<th class="QueueStats-queueTableHeader">User</th>
<th class="QueueStats-queueTableHeader">Waiting</th>
</tr>
</thead>
<tbody>
@ -35,7 +37,10 @@
<tr class="QueueStats-queueTableRow">
{{$build := $item.Build}}
<td class="QueueStats-queueTableColumn">
{{$item.Build.HostType}}
{{$item.Build.Name}}
</td>
<td class="QueueStats-queueTableColumn">
{{printf "%s/%s" $item.Build.Repo $item.Build.Branch}}
</td>
<td class="QueueStats-queueTableColumn">
{{$item.Cost}}
@ -50,18 +55,18 @@
{{else}}
Post-submit
{{end}}
/
{{$build.Priority}}
({{$build.Priority}})
</td>
<td class="QueueStats-queueTableColumn">
{{$build.User}}
</td>
<td class="QueueStats-queueTableColumn">
{{humanDuration (timeSince $build.RequestTime)}}
</td>
</tr>
{{else}}
<tr class="QueueStats-queueTableRow">
<td class="QueueStats-queueTableColumn" colspan="4">
Queue empty.
</td>
<td class="QueueStats-queueTableColumn" colspan="6">Queue empty.</td>
</tr>
{{end}}
</tbody>

Просмотреть файл

@ -32,6 +32,7 @@ type SchedItem struct {
IsGomote bool
IsTry bool
IsHelper bool
Repo string
Branch string
// CommitTime is the latest commit date of the relevant repos