added ability to filter ExpvarHandler output with regexp

This commit is contained in:
Aliaksandr Valialkin
2016-02-05 17:39:32 +02:00
parent e05941507f
commit a66138e80f
2 changed files with 64 additions and 6 deletions
+34 -2
View File
@@ -3,26 +3,58 @@ package fasthttputil
import (
"expvar"
"fmt"
"regexp"
"github.com/valyala/fasthttp"
)
var (
expvarHandlerCalls = expvar.NewInt("expvarHandlerCalls")
expvarRegexpErrors = expvar.NewInt("expvarRegexpErrors")
)
// ExpvarHandler dumps json representation of expvars to http response.
//
// Expvars may be filtered by regexp provided via 'r' query argument.
//
// See https://golang.org/pkg/expvar/ for details.
func ExpvarHandler(ctx *fasthttp.RequestCtx) {
expvarHandlerCalls.Add(1)
ctx.Response.Reset()
r, err := getExpvarRegexp(ctx)
if err != nil {
expvarRegexpErrors.Add(1)
fmt.Fprintf(ctx, "Error when obtaining expvar regexp: %s", err)
ctx.SetStatusCode(fasthttp.StatusBadRequest)
return
}
fmt.Fprintf(ctx, "{\n")
first := true
expvar.Do(func(kv expvar.KeyValue) {
if !first {
fmt.Fprintf(ctx, ",\n")
}
first = false
fmt.Fprintf(ctx, "%q: %s", kv.Key, kv.Value)
if r.MatchString(kv.Key) {
first = false
fmt.Fprintf(ctx, "\t%q: %s", kv.Key, kv.Value)
}
})
fmt.Fprintf(ctx, "\n}\n")
ctx.SetContentType("application/json; charset=utf-8")
}
func getExpvarRegexp(ctx *fasthttp.RequestCtx) (*regexp.Regexp, error) {
r := string(ctx.QueryArgs().Peek("r"))
if len(r) == 0 {
r = "."
}
rr, err := regexp.Compile(r)
if err != nil {
return nil, fmt.Errorf("cannot parse r=%q: %s", r, err)
}
return rr, nil
}
+30 -4
View File
@@ -3,18 +3,21 @@ package fasthttputil
import (
"encoding/json"
"expvar"
"strings"
"testing"
"github.com/valyala/fasthttp"
)
func TestExpvarHandler(t *testing.T) {
func TestExpvarHandlerBasic(t *testing.T) {
expvar.Publish("customVar", expvar.Func(func() interface{} {
return "foobar"
}))
var ctx fasthttp.RequestCtx
expvarHandlerCalls.Set(0)
ExpvarHandler(&ctx)
body := ctx.Response.Body()
@@ -31,11 +34,34 @@ func TestExpvarHandler(t *testing.T) {
t.Fatalf("cannot locate memstats expvar")
}
v, ok := m["customVar"]
v := m["customVar"]
sv, ok := v.(string)
if !ok {
t.Fatalf("cannot locate customVar")
t.Fatalf("unexpected custom var type %T. Expecting string", v)
}
if v != "foobar" {
if sv != "foobar" {
t.Fatalf("unexpected custom var value: %q. Expecting %q", v, "foobar")
}
v = m["expvarHandlerCalls"]
fv, ok := v.(float64)
if !ok {
t.Fatalf("unexpected expvarHandlerCalls type %T. Expecting float64", v)
}
if int(fv) != 1 {
t.Fatalf("unexpected value for expvarHandlerCalls: %v. Expecting %v", fv, 1)
}
}
func TestExpvarHandlerRegexp(t *testing.T) {
var ctx fasthttp.RequestCtx
ctx.QueryArgs().Set("r", "cmd")
ExpvarHandler(&ctx)
body := string(ctx.Response.Body())
if !strings.Contains(body, `"cmdline"`) {
t.Fatalf("missing 'cmdline' expvar")
}
if strings.Contains(body, `"memstats"`) {
t.Fatalf("unexpected memstats expvar found")
}
}