diff options
| author | Jonathan Amsterdam <jba@google.com> | 2021-11-19 11:55:24 -0500 |
|---|---|---|
| committer | Jonathan Amsterdam <jba@google.com> | 2021-11-19 19:35:43 +0000 |
| commit | b8b6586b3696b6b6a420168bd9ef801bd9f82bc2 (patch) | |
| tree | 1696426382ffea33adccd70a2fbfbd688458e202 | |
| parent | 099f52a6958764a8cad8bf5e8673ab5b5bda41d7 (diff) | |
| download | go-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>
| -rw-r--r-- | internal/frontend/server.go | 56 | ||||
| -rw-r--r-- | internal/memory/memory.go | 17 | ||||
| -rw-r--r-- | internal/memory/memory_test.go | 21 |
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) + } + } +} |
