aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorJonathan Amsterdam <jba@google.com>2021-11-19 11:55:24 -0500
committerJonathan Amsterdam <jba@google.com>2021-11-19 19:35:43 +0000
commitb8b6586b3696b6b6a420168bd9ef801bd9f82bc2 (patch)
tree1696426382ffea33adccd70a2fbfbd688458e202 /internal
parent099f52a6958764a8cad8bf5e8673ab5b5bda41d7 (diff)
downloadgo-x-pkgsite-b8b6586b3696b6b6a420168bd9ef801bd9f82bc2.tar.xz
internal/frontend: add memory stats to debug handler
Also, change the path to "_debug" because there are stdlib packages at "debug". Change-Id: Id72c86a34e9cfec3d1f4a889af4549ba4119279e Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/365657 Trust: Jonathan Amsterdam <jba@google.com> Run-TryBot: Jonathan Amsterdam <jba@google.com> Reviewed-by: Jamal Carvalho <jamal@golang.org> TryBot-Result: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'internal')
-rw-r--r--internal/frontend/server.go56
-rw-r--r--internal/memory/memory.go17
-rw-r--r--internal/memory/memory_test.go21
3 files changed, 82 insertions, 12 deletions
diff --git a/internal/frontend/server.go b/internal/frontend/server.go
index 655d376d..78149a57 100644
--- a/internal/frontend/server.go
+++ b/internal/frontend/server.go
@@ -32,6 +32,7 @@ import (
"golang.org/x/pkgsite/internal/godoc/dochtml"
"golang.org/x/pkgsite/internal/licenses"
"golang.org/x/pkgsite/internal/log"
+ "golang.org/x/pkgsite/internal/memory"
"golang.org/x/pkgsite/internal/middleware"
"golang.org/x/pkgsite/internal/queue"
"golang.org/x/pkgsite/internal/static"
@@ -204,18 +205,51 @@ func (s *Server) installDebugHandlers(handle func(string, http.Handler)) {
})
}
- handle("/debug/pprof/", ifDebug(hpprof.Index))
- handle("/debug/pprof/cmdline", ifDebug(hpprof.Cmdline))
- handle("/debug/pprof/profile", ifDebug(hpprof.Profile))
- handle("/debug/pprof/symbol", ifDebug(hpprof.Symbol))
- handle("/debug/pprof/trace", ifDebug(hpprof.Trace))
+ handle("/_debug/pprof/", ifDebug(hpprof.Index))
+ handle("/_debug/pprof/cmdline", ifDebug(hpprof.Cmdline))
+ handle("/_debug/pprof/profile", ifDebug(hpprof.Profile))
+ handle("/_debug/pprof/symbol", ifDebug(hpprof.Symbol))
+ handle("/_debug/pprof/trace", ifDebug(hpprof.Trace))
+
+ handle("/_debug/info", ifDebug(func(w http.ResponseWriter, r *http.Request) {
+ row := func(a, b string) {
+ fmt.Fprintf(w, "<tr><td>%s</td> <td>%s</td></tr>\n", a, b)
+ }
+ memrow := func(s string, m uint64) {
+ fmt.Fprintf(w, "<tr><td>%s</td> <td align='right'>%s</td></tr>\n", s, memory.Format(m))
+ }
+
+ fmt.Fprintf(w, "<html><body style='font-family: sans-serif'>\n")
+
+ fmt.Fprintf(w, "<table>\n")
+ row("Service", os.Getenv("K_SERVICE"))
+ row("Config", os.Getenv("K_CONFIGURATION"))
+ row("Revision", s.versionID)
+ row("Instance", s.instanceID)
+ fmt.Fprintf(w, "</table>\n")
+
+ gm := memory.ReadRuntimeStats()
+ pm, err := memory.ReadProcessStats()
+ if err != nil {
+ http.Error(w, fmt.Sprintf("reading process stats: %v", err), http.StatusInternalServerError)
+ return
+ }
+ sm, err := memory.ReadSystemStats()
+ if err != nil {
+ http.Error(w, fmt.Sprintf("reading system stats: %v", err), http.StatusInternalServerError)
+ return
+ }
+ fmt.Fprintf(w, "<table>\n")
+ memrow("Go Alloc", gm.Alloc)
+ memrow("Go Sys", gm.Sys)
+ memrow("Process VSize", pm.VSize)
+ memrow("Process RSS", pm.RSS)
+ memrow("System Total", sm.Total)
+ memrow("System Used", sm.Used)
+ fmt.Fprintf(w, "</table>\n")
+
+ fmt.Fprintf(w, "</body></html>\n")
- handle("/debug/info", ifDebug(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "text/plain; charset=utf-8")
- fmt.Fprintf(w, "Service: %s\n", os.Getenv("K_SERVICE"))
- fmt.Fprintf(w, "Config: %s\n", os.Getenv("K_CONFIGURATION"))
- fmt.Fprintf(w, "Revision: %s\n", s.versionID)
- fmt.Fprintf(w, "Instance: %s\n", s.instanceID)
}))
}
diff --git a/internal/memory/memory.go b/internal/memory/memory.go
index 76638a9d..2cb1e616 100644
--- a/internal/memory/memory.go
+++ b/internal/memory/memory.go
@@ -188,3 +188,20 @@ func getCgroupStats() (map[string]uint64, error) {
}
return m, nil
}
+
+// Format formats a memory value for humans. It uses a B, K, M or G suffix and
+// rounds to two decimal places.
+func Format(m uint64) string {
+ const Ki = 1024
+
+ if m < Ki {
+ return fmt.Sprintf("%d B", m)
+ }
+ if m < Ki*Ki {
+ return fmt.Sprintf("%.2f K", float64(m)/Ki)
+ }
+ if m < Ki*Ki*Ki {
+ return fmt.Sprintf("%.2f M", float64(m)/(Ki*Ki))
+ }
+ return fmt.Sprintf("%.2f G", float64(m)/(Ki*Ki*Ki))
+}
diff --git a/internal/memory/memory_test.go b/internal/memory/memory_test.go
index 65604cae..af862713 100644
--- a/internal/memory/memory_test.go
+++ b/internal/memory/memory_test.go
@@ -8,7 +8,7 @@ import (
"testing"
)
-func Test(t *testing.T) {
+func TestRead(t *testing.T) {
_, err := ReadSystemStats()
if err != nil {
t.Fatal(err)
@@ -20,3 +20,22 @@ func Test(t *testing.T) {
// We can't really test ReadCgroupStats, because we may or may not be in a cgroup.
}
+
+func TestFormat(t *testing.T) {
+ for _, test := range []struct {
+ m uint64
+ want string
+ }{
+ {0, "0 B"},
+ {1022, "1022 B"},
+ {2500, "2.44 K"},
+ {4096, "4.00 K"},
+ {2_000_000, "1.91 M"},
+ {18_000_000_000, "16.76 G"},
+ } {
+ got := Format(test.m)
+ if got != test.want {
+ t.Errorf("%d: got %q, want %q", test.m, got, test.want)
+ }
+ }
+}