From 426d1652541548bb66f5152b135f4ad4575e1c96 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Mon, 21 Mar 2016 22:39:06 -0600 Subject: [PATCH] expvar: Allow no args; publish number of goroutines --- caddy/setup/expvar.go | 25 ++++++++++++++++++++++--- caddy/setup/expvar_test.go | 15 +++++++++------ dist/CHANGES.txt | 1 + 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/caddy/setup/expvar.go b/caddy/setup/expvar.go index 7393a0a64..4d9c353de 100644 --- a/caddy/setup/expvar.go +++ b/caddy/setup/expvar.go @@ -1,7 +1,9 @@ package setup import ( - _ "expvar" + stdexpvar "expvar" + "runtime" + "sync" "github.com/mholt/caddy/middleware" "github.com/mholt/caddy/middleware/expvar" @@ -14,6 +16,9 @@ func ExpVar(c *Controller) (middleware.Middleware, error) { return nil, err } + // publish any extra information/metrics we may want to capture + publishExtraVars() + expvar := expvar.ExpVar{Resource: resource} return func(next middleware.Handler) middleware.Handler { @@ -24,12 +29,13 @@ func ExpVar(c *Controller) (middleware.Middleware, error) { func expVarParse(c *Controller) (expvar.Resource, error) { var resource expvar.Resource - var err error + for c.Next() { args := c.RemainingArgs() - switch len(args) { + case 0: + resource = expvar.Resource(defaultExpvarPath) case 1: resource = expvar.Resource(args[0]) default: @@ -39,3 +45,16 @@ func expVarParse(c *Controller) (expvar.Resource, error) { return resource, err } + +func publishExtraVars() { + // By using sync.Once instead of an init() function, we don't clutter + // the app's expvar export unnecessarily, or risk colliding with it. + publishOnce.Do(func() { + stdexpvar.Publish("Goroutines", stdexpvar.Func(func() interface{} { + return runtime.NumGoroutine() + })) + }) +} + +var publishOnce sync.Once // publishing variables should only be done once +var defaultExpvarPath = "/debug/vars" diff --git a/caddy/setup/expvar_test.go b/caddy/setup/expvar_test.go index 2b125c893..5fb018ce9 100644 --- a/caddy/setup/expvar_test.go +++ b/caddy/setup/expvar_test.go @@ -7,29 +7,32 @@ import ( ) func TestExpvar(t *testing.T) { - c := NewTestController(`expvar /d/v`) - + c := NewTestController(`expvar`) mid, err := ExpVar(c) - if err != nil { t.Errorf("Expected no errors, got: %v", err) } + if mid == nil { + t.Fatal("Expected middleware, was nil instead") + } + c = NewTestController(`expvar /d/v`) + mid, err = ExpVar(c) + if err != nil { + t.Errorf("Expected no errors, got: %v", err) + } if mid == nil { t.Fatal("Expected middleware, was nil instead") } handler := mid(EmptyNext) myHandler, ok := handler.(expvar.ExpVar) - if !ok { t.Fatalf("Expected handler to be type ExpVar, got: %#v", handler) } - if myHandler.Resource != "/d/v" { t.Errorf("Expected /d/v as expvar resource") } - if !SameNext(myHandler.Next, EmptyNext) { t.Error("'Next' field of handler was not set properly") } diff --git a/dist/CHANGES.txt b/dist/CHANGES.txt index 1915b97b2..5aa81fb3d 100644 --- a/dist/CHANGES.txt +++ b/dist/CHANGES.txt @@ -2,6 +2,7 @@ CHANGES - New pprof directive for exposing process performance profile +- New expvar directive for reading memory/GC performance - New -restart option to force in-process restarts on Unix systems - Toggle case-sensitive path matching with environment variable - proxy: New max_conns setting to limit max connections per upstream