golang.org/x/build@v0.0.0-20240506185731-218518f32b70/cmd/coordinator/queues.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build linux || darwin 6 7 package main 8 9 import ( 10 _ "embed" 11 "html/template" 12 "log" 13 "net/http" 14 "time" 15 16 "golang.org/x/build/internal/coordinator/pool" 17 "golang.org/x/build/internal/coordinator/pool/queue" 18 ) 19 20 //go:embed templates/queues.html 21 var queuesTemplateStr string 22 23 var queuesTemplate = template.Must(baseTmpl.New("queues.html").Funcs(map[string]interface{}{ 24 "timeSince": timeSince, 25 "humanDuration": humanDuration, 26 }).Parse(queuesTemplateStr)) 27 28 type QueuesResponse struct { 29 Queues map[string]*queue.QuotaStats 30 } 31 32 func handleQueues(w http.ResponseWriter, _ *http.Request) { 33 resp := QueuesResponse{Queues: map[string]*queue.QuotaStats{}} 34 mergeStats := func(qs map[string]*queue.QuotaStats) { 35 for name, stats := range qs { 36 resp.Queues[name] = stats 37 } 38 } 39 mergeStats(pool.ReversePool().QuotaStats()) 40 mergeStats(pool.EC2BuildetPool().QuotaStats()) 41 mergeStats(pool.NewGCEConfiguration().BuildletPool().QuotaStats()) 42 if err := queuesTemplate.Execute(w, resp); err != nil { 43 log.Printf("handleQueues: %v", err) 44 } 45 } 46 47 func timeSince(t time.Time) time.Duration { 48 return time.Since(t) 49 } 50 51 // humanDuration is largely time.Duration's formatting, but modified 52 // to imprecisely format days, even though days may vary in length 53 // due to daylight savings time. Sub-second durations are 54 // represented as 0s. 55 func humanDuration(d time.Duration) string { 56 var buf [32]byte 57 w := len(buf) 58 59 u := uint64(d) 60 neg := d < 0 61 if neg { 62 u = -u 63 } 64 w-- 65 buf[w] = 's' 66 67 _, u = fmtFrac(buf[:w], u, 9) 68 69 // u is now integer seconds 70 w = fmtInt(buf[:w], u%60) 71 u /= 60 72 73 // u is now integer minutes 74 if u > 0 { 75 w-- 76 buf[w] = 'm' 77 w = fmtInt(buf[:w], u%60) 78 u /= 60 79 80 // u is now integer hours 81 if u > 0 { 82 w-- 83 buf[w] = 'h' 84 w = fmtInt(buf[:w], u%24) 85 u /= 24 86 if u > 0 { 87 w-- 88 buf[w] = 'd' 89 w = fmtInt(buf[:w], u) 90 } 91 } 92 } 93 94 if neg { 95 w-- 96 buf[w] = '-' 97 } 98 return string(buf[w:]) 99 } 100 101 // fmtFrac is identical to fmtFrac in the time package. 102 func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) { 103 // Omit trailing zeros up to and including decimal point. 104 w := len(buf) 105 print := false 106 for i := 0; i < prec; i++ { 107 digit := v % 10 108 print = print || digit != 0 109 if print { 110 w-- 111 buf[w] = byte(digit) + '0' 112 } 113 v /= 10 114 } 115 if print { 116 w-- 117 buf[w] = '.' 118 } 119 return w, v 120 } 121 122 // fmtInt is identical to fmtInt in the time package. 123 func fmtInt(buf []byte, v uint64) int { 124 w := len(buf) 125 if v == 0 { 126 w-- 127 buf[w] = '0' 128 } else { 129 for v > 0 { 130 w-- 131 buf[w] = byte(v%10) + '0' 132 v /= 10 133 } 134 } 135 return w 136 }