From 8a0c89d182908a578fd0e718c0e3ac8f8ee3fad0 Mon Sep 17 00:00:00 2001 From: Enrico Stahn Date: Sun, 18 Mar 2018 12:23:38 +1100 Subject: [PATCH] Implement unix socket support and make status path configurable (#23) * Implement unix socket support and make status path configurable (Thx @herb123456 for the initial implementation) #19 #22 * Follow linting guidelines * Follow linting guidelines * Move `env` to where it's being used --- phpfpm/phpfpm.go | 45 +++++++++++++++++++++++++++++++++---------- phpfpm/phpfpm_test.go | 19 ++++++++++++++++++ 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/phpfpm/phpfpm.go b/phpfpm/phpfpm.go index 43e98f0..5bc3454 100644 --- a/phpfpm/phpfpm.go +++ b/phpfpm/phpfpm.go @@ -20,6 +20,7 @@ import ( "io/ioutil" "net/url" "strconv" + "strings" "sync" "time" @@ -144,26 +145,26 @@ func (pm *PoolManager) Update() (err error) { func (p *Pool) Update() (err error) { p.ScrapeError = nil - env := map[string]string{ - "SCRIPT_FILENAME": "/status", - "SCRIPT_NAME": "/status", - "SERVER_SOFTWARE": "go / php-fpm_exporter", - "REMOTE_ADDR": "127.0.0.1", - "QUERY_STRING": "json&full", - } - - uri, err := url.Parse(p.Address) + scheme, address, path, err := parseURL(p.Address) if err != nil { return p.error(err) } - fcgi, err := fcgiclient.DialTimeout(uri.Scheme, uri.Hostname()+":"+uri.Port(), time.Duration(3)*time.Second) + fcgi, err := fcgiclient.DialTimeout(scheme, address, time.Duration(3)*time.Second) if err != nil { return p.error(err) } defer fcgi.Close() + env := map[string]string{ + "SCRIPT_FILENAME": path, + "SCRIPT_NAME": path, + "SERVER_SOFTWARE": "go / php-fpm_exporter", + "REMOTE_ADDR": "127.0.0.1", + "QUERY_STRING": "json&full", + } + resp, err := fcgi.Get(env) if err != nil { return p.error(err) @@ -213,6 +214,30 @@ func CountProcessState(processes []PoolProcess) (active int64, idle int64, total return active, idle, active + idle } +// parseURL creates elements to be passed into fcgiclient.DialTimeout +func parseURL(rawurl string) (scheme string, address string, path string, err error) { + uri, err := url.Parse(rawurl) + if err != nil { + return uri.Scheme, uri.Host, uri.Path, err + } + + scheme = uri.Scheme + + switch uri.Scheme { + case "unix": + result := strings.Split(uri.Path, ";") + address = result[0] + if len(result) > 1 { + path = result[1] + } + default: + address = uri.Host + path = uri.Path + } + + return +} + type timestamp time.Time // MarshalJSON customise JSON for timestamp diff --git a/phpfpm/phpfpm_test.go b/phpfpm/phpfpm_test.go index c858396..b23044b 100644 --- a/phpfpm/phpfpm_test.go +++ b/phpfpm/phpfpm_test.go @@ -93,3 +93,22 @@ func TestCannotUnmarshalNumberIssue10(t *testing.T) { assert.NotNil(t, err, err.Error()) } + +func TestParseURL(t *testing.T) { + var uris = []struct { + in string + out []string + err error + }{ + {"tcp://127.0.0.1:9000/status", []string{"tcp", "127.0.0.1:9000", "/status"}, nil}, + {"tcp://127.0.0.1", []string{"tcp", "127.0.0.1", ""}, nil}, + {"unix:///tmp/php.sock;/status", []string{"unix", "/tmp/php.sock", "/status"}, nil}, + {"unix:///tmp/php.sock", []string{"unix", "/tmp/php.sock", ""}, nil}, + } + + for _, u := range uris { + scheme, address, path, err := parseURL(u.in) + assert.Equal(t, u.err, err) + assert.Equal(t, u.out, []string{scheme, address, path}) + } +}