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  }