diff --git a/cmd/coordinator/coordinator.go b/cmd/coordinator/coordinator.go
index 3d489f2c..6ec0bb02 100644
--- a/cmd/coordinator/coordinator.go
+++ b/cmd/coordinator/coordinator.go
@@ -2888,7 +2888,7 @@ func (s *span) done(err error) error {
s.end = t1
td := t1.Sub(s.start)
var text bytes.Buffer
- fmt.Fprintf(&text, "after %v", td)
+ fmt.Fprintf(&text, "after %s", friendlyDuration(td))
if err != nil {
fmt.Fprintf(&text, "; err=%v", err)
}
diff --git a/cmd/coordinator/gce.go b/cmd/coordinator/gce.go
index 7e6eeeec..aec1f9a7 100644
--- a/cmd/coordinator/gce.go
+++ b/cmd/coordinator/gce.go
@@ -349,7 +349,7 @@ func (p *gceBuildletPool) WriteHTMLStatus(w io.Writer) {
fmt.Fprintf(w, "
")
for i, inst := range active {
if i < show/2 || i >= len(active)-(show/2) {
- fmt.Fprintf(w, "- %v, %v
\n", inst.name, time.Since(inst.creation))
+ fmt.Fprintf(w, "- %v, %s
\n", inst.name, friendlyDuration(time.Since(inst.creation)))
} else if i == show/2 {
fmt.Fprintf(w, "- ... %d of %d total omitted ...
\n", len(active)-show, len(active))
}
diff --git a/cmd/coordinator/reverse.go b/cmd/coordinator/reverse.go
index 520c8826..1987149a 100644
--- a/cmd/coordinator/reverse.go
+++ b/cmd/coordinator/reverse.go
@@ -328,14 +328,14 @@ func (p *reverseBuildletPool) WriteHTMLStatus(w io.Writer) {
if b.inUse {
machStatus = "working"
}
- fmt.Fprintf(&buf, "- %s (%s) version %s, %s: connected %v, %s for %v
\n",
+ fmt.Fprintf(&buf, "- %s (%s) version %s, %s: connected %s, %s for %s
\n",
b.hostname,
b.conn.RemoteAddr(),
b.version,
b.hostType,
- time.Since(b.regTime),
+ friendlyDuration(time.Since(b.regTime)),
machStatus,
- time.Since(b.inUseTime))
+ friendlyDuration(time.Since(b.inUseTime)))
total[b.hostType]++
if b.inUse && !b.inHealthCheck {
inUse[b.hostType]++
diff --git a/cmd/coordinator/status.go b/cmd/coordinator/status.go
index 062faa1e..b4164e0b 100644
--- a/cmd/coordinator/status.go
+++ b/cmd/coordinator/status.go
@@ -116,6 +116,19 @@ func fdCount() int {
}
}
+func friendlyDuration(d time.Duration) string {
+ if d > 10*time.Second {
+ d2 := ((d + 50*time.Millisecond) / (100 * time.Millisecond)) * (100 * time.Millisecond)
+ return d2.String()
+ }
+ if d > time.Second {
+ d2 := ((d + 5*time.Millisecond) / (10 * time.Millisecond)) * (10 * time.Millisecond)
+ return d2.String()
+ }
+ d2 := ((d + 50*time.Microsecond) / (100 * time.Microsecond)) * (100 * time.Microsecond)
+ return d2.String()
+}
+
func diskFree() string {
out, _ := exec.Command("df", "-h").Output()
return string(out)
diff --git a/cmd/coordinator/status_test.go b/cmd/coordinator/status_test.go
new file mode 100644
index 00000000..b8b4c21b
--- /dev/null
+++ b/cmd/coordinator/status_test.go
@@ -0,0 +1,35 @@
+// Copyright 2017 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.
+
+package main
+
+import (
+ "testing"
+ "time"
+)
+
+var durationTests = []struct {
+ in time.Duration
+ want string
+}{
+ {10*time.Second + 555*time.Millisecond, "10.6s"},
+ {10*time.Second + 500*time.Millisecond, "10.5s"},
+ {10*time.Second + 499*time.Millisecond, "10.5s"},
+ {10*time.Second + 401*time.Millisecond, "10.4s"},
+ {9*time.Second + 401*time.Millisecond, "9.4s"},
+ {9*time.Second + 456*time.Millisecond, "9.46s"},
+ {9*time.Second + 445*time.Millisecond, "9.45s"},
+ {1 * time.Second, "1s"},
+ {859*time.Millisecond + 445*time.Microsecond, "859.4ms"},
+ {859*time.Millisecond + 460*time.Microsecond, "859.5ms"},
+}
+
+func TestFriendlyDuration(t *testing.T) {
+ for _, tt := range durationTests {
+ got := friendlyDuration(tt.in)
+ if got != tt.want {
+ t.Errorf("friendlyDuration(%v): got %s, want %s", tt.in, got, tt.want)
+ }
+ }
+}