1
0
mirror of https://github.com/divan/expvarmon.git synced 2025-04-25 13:48:54 +08:00

Add customizable endpoints ('/debug/vars')

This commit is contained in:
Ivan Daniluk 2015-10-15 23:11:48 -04:00
parent b4e096514e
commit b82a1e996c
4 changed files with 79 additions and 31 deletions

View File

@ -11,8 +11,8 @@ import (
"github.com/antonholmquist/jason"
)
// ExpvarsUrl is the default url for fetching expvar info.
const ExpvarsPath = "/debug/vars"
// DefaultEndpoint is the default url for fetching expvar info.
var DefaultEndpoint = "/debug/vars"
// Expvar represents fetched expvar variable.
type Expvar struct {

View File

@ -17,12 +17,15 @@ var (
varsArg = flag.String("vars", "mem:memstats.Alloc,mem:memstats.Sys,mem:memstats.HeapAlloc,mem:memstats.HeapInuse,duration:memstats.PauseNs,duration:memstats.PauseTotalNs", "Vars to monitor (comma-separated)")
dummy = flag.Bool("dummy", false, "Use dummy (console) output")
self = flag.Bool("self", false, "Monitor itself")
endpoint = flag.String("endpoint", DefaultEndpoint, "URL endpoint for expvars")
)
func main() {
flag.Usage = Usage
flag.Parse()
DefaultEndpoint = *endpoint
// Process ports/urls
ports, _ := ParsePorts(*urls)
if *self {

View File

@ -53,7 +53,9 @@ func flattenURLs(rawurl string, ports []string) ([]url.URL, error) {
if err != nil {
return nil, err
}
baseUrl.Path = ExpvarsPath
if baseUrl.Path == "" {
baseUrl.Path = DefaultEndpoint
}
// Create new URL for each port
for _, port := range ports {
@ -69,35 +71,9 @@ func ParsePorts(s string) ([]url.URL, error) {
var urls []url.URL
fields := strings.FieldsFunc(s, func(r rune) bool { return r == ',' })
for _, field := range fields {
// Try simple 'ports range' mode, ports only ("1234-1235,80")
// Defaults to "localhost" will be used.
ports, err := parseRange(field)
if err == nil {
furls, err := flattenURLs("http://localhost", ports)
if err != nil {
return nil, err
}
urls = append(urls, furls...)
continue
}
rawurl, portsRange := extractUrlAndPorts(field)
// then, try host:ports notation ("localhost:1234-1235,https://remote:2000,2345")
var rawurl, portsRange string
parts := strings.FieldsFunc(field, func(r rune) bool { return r == ':' })
switch len(parts) {
case 1:
// "1234-234"
rawurl = "http://localhost"
case 2:
// "localhost:1234"
rawurl, portsRange = parts[0], parts[1]
default:
// "https://user:pass@remote.name:1234"
rawurl = strings.Join(parts[:len(parts)-1], ":")
portsRange = parts[len(parts)-1]
}
ports, err = parseRange(portsRange)
ports, err := parseRange(portsRange)
if err != nil {
return nil, ErrParsePorts
}
@ -113,6 +89,42 @@ func ParsePorts(s string) ([]url.URL, error) {
return urls, nil
}
// extractUrlAndPorts attempts to split url and extract raw url
// for the single port and range of ports to parse.
//
// i.e. "http://name:1234-1236/_endpoint" would return "http://name/_endpoint" and
// "1234-1236"
func extractUrlAndPorts(s string) (string, string) {
var rawurl, ports string
parts := strings.Split(s, ":")
switch len(parts) {
case 1:
// "1234-234"
rawurl = "http://localhost"
ports = parts[0]
case 2:
// "localhost:1234"
rawurl, ports = parts[0], parts[1]
default:
// "https://user:pass@remote.name:1234" or "http://name:1234-1236/_endpoint"
// construct endpoint from the first part of URI, before ports appera
rawurl = strings.Join(parts[:len(parts)-1], ":")
// get either "1234-1235" or "1234-1235/_endpoint"
lastPart := parts[len(parts)-1]
// try to find endpoint and attach it to rawurl
fields := strings.SplitN(lastPart, "/", 2)
ports = fields[0]
if len(fields) > 1 {
rawurl = fmt.Sprintf("%s/%s", rawurl, fields[1])
}
}
return rawurl, ports
}
// parseRange flattens port ranges, such as "1234-1240,1333"
func parseRange(s string) ([]string, error) {
portsInt, err := ranges.Parse(s)

View File

@ -26,6 +26,29 @@ func TestUtils(t *testing.T) {
}
}
func TestExtractUrlAndPorts(t *testing.T) {
var rawurl, ports string
rawurl, ports = extractUrlAndPorts("40000-40002")
if rawurl != "http://localhost" || ports != "40000-40002" {
t.Fatalf("extract url and ports failed: %v, %v", rawurl, ports)
}
rawurl, ports = extractUrlAndPorts("https://example.com:1234")
if rawurl != "https://example.com" || ports != "1234" {
t.Fatalf("extract url and ports failed: %v, %v", rawurl, ports)
}
rawurl, ports = extractUrlAndPorts("http://user:passwd@example.com:1234-1256")
if rawurl != "http://user:passwd@example.com" || ports != "1234-1256" {
t.Fatalf("extract url and ports failed: %v, %v", rawurl, ports)
}
rawurl, ports = extractUrlAndPorts("https://example.com:1234-1256/_endpoint")
if rawurl != "https://example.com/_endpoint" || ports != "1234-1256" {
t.Fatalf("extract url and ports failed: %v, %v", rawurl, ports)
}
}
func TestPorts(t *testing.T) {
arg := "1234,1235"
ports, err := ParsePorts(arg)
@ -85,4 +108,14 @@ func TestPorts(t *testing.T) {
if err == nil {
t.Fatalf("err shouldn't be nil")
}
// Test endpoints
arg = "localhost:2000,https://example.com:1234/_custom_expvars"
ports, err = ParsePorts(arg)
if err != nil {
t.Fatal(err)
}
if ports[0].Path != "/debug/vars" || ports[1].Path != "/_custom_expvars" {
t.Fatalf("ParsePorts returns wrong data: %v", ports)
}
}