From 8303048f5e2820a8647ee128c8e8464d8411349d Mon Sep 17 00:00:00 2001 From: Enrico Stahn Date: Thu, 22 Feb 2018 15:41:27 +1100 Subject: [PATCH 1/4] Add metrics "phpfpm_up" and "phpfpm_scrape_failures" to report on scraping issues (#2) --- phpfpm/exporter.go | 29 ++++++++++++++++++++++++----- phpfpm/phpfpm.go | 27 ++++++++++++++++----------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/phpfpm/exporter.go b/phpfpm/exporter.go index ae8dbc1..55c27b6 100644 --- a/phpfpm/exporter.go +++ b/phpfpm/exporter.go @@ -14,6 +14,7 @@ package phpfpm import ( + "fmt" "github.com/prometheus/client_golang/prometheus" "sync" ) @@ -27,6 +28,8 @@ type Exporter struct { PoolManager PoolManager mutex sync.Mutex + up *prometheus.Desc + scrapeFailues *prometheus.Desc startSince *prometheus.Desc acceptedConnections *prometheus.Desc listenQueue *prometheus.Desc @@ -45,6 +48,18 @@ func NewExporter(pm PoolManager) *Exporter { return &Exporter{ PoolManager: pm, + up: prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", "up"), + "Could PHP-FPM be reached?", + []string{"pool"}, + nil), + + scrapeFailues: prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", "scrape_failures"), + "The number of failures scraping from PHP-FPM.", + []string{"pool"}, + nil), + startSince: prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "start_since"), "The number of seconds since FPM has started.", @@ -121,6 +136,15 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { e.PoolManager.Update() for _, pool := range e.PoolManager.Pools { + ch <- prometheus.MustNewConstMetric(e.scrapeFailues, prometheus.CounterValue, float64(pool.ScrapeFailures)) + + if pool.ScrapeError != nil { + ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0) + log.Error("Error scraping PHP-FPM: %v", pool.ScrapeError) + continue + } + + ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 1, pool.Name) ch <- prometheus.MustNewConstMetric(e.startSince, prometheus.CounterValue, float64(pool.AcceptedConnections), pool.Name) ch <- prometheus.MustNewConstMetric(e.acceptedConnections, prometheus.CounterValue, float64(pool.StartSince), pool.Name) ch <- prometheus.MustNewConstMetric(e.listenQueue, prometheus.GaugeValue, float64(pool.ListenQueue), pool.Name) @@ -134,11 +158,6 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric(e.slowRequests, prometheus.CounterValue, float64(pool.SlowRequests), pool.Name) } - //if err := e.collect(ch); err != nil { - // log.Errorf("Error scraping apache: %s", err) - // e.scrapeFailures.Inc() - // e.scrapeFailures.Collect(ch) - //} return } diff --git a/phpfpm/phpfpm.go b/phpfpm/phpfpm.go index 35ea6aa..a48d3f1 100644 --- a/phpfpm/phpfpm.go +++ b/phpfpm/phpfpm.go @@ -41,7 +41,8 @@ type PoolManager struct { type Pool struct { // The address of the pool, e.g. tcp://127.0.0.1:9000 or unix:///tmp/php-fpm.sock Address string `json:"-"` - CollectionError error `json:"-"` + ScrapeError error `json:"-"` + ScrapeFailures int64 `json:"-"` Name string `json:"pool"` ProcessManager string `json:"process manager"` StartTime timestamp `json:"start time"` @@ -108,14 +109,15 @@ func (pm *PoolManager) Update() (err error) { // Update will connect to PHP-FPM and retrieve the latest data for the pool. func (p *Pool) Update() (err error) { - p.CollectionError = nil + p.ScrapeError = nil - env := make(map[string]string) - env["SCRIPT_FILENAME"] = "/status" - env["SCRIPT_NAME"] = "/status" - env["SERVER_SOFTWARE"] = "go / php-fpm_exporter " - env["REMOTE_ADDR"] = "127.0.0.1" - env["QUERY_STRING"] = "json&full" + 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) if err != nil { @@ -127,18 +129,20 @@ func (p *Pool) Update() (err error) { return p.error(err) } + defer fcgi.Close() + resp, err := fcgi.Get(env) if err != nil { return p.error(err) } + defer resp.Body.Close() + content, err := ioutil.ReadAll(resp.Body) if err != nil { return p.error(err) } - fcgi.Close() - log.Debugf("Pool[", p.Address, "]:", string(content)) if err = json.Unmarshal(content, &p); err != nil { @@ -149,7 +153,8 @@ func (p *Pool) Update() (err error) { } func (p *Pool) error(err error) error { - p.CollectionError = err + p.ScrapeError = err + p.ScrapeFailures++ log.Error(err) return err } From a23e9f0c270b137990780208d08a7c4858318bce Mon Sep 17 00:00:00 2001 From: Enrico Stahn Date: Thu, 22 Feb 2018 15:44:28 +1100 Subject: [PATCH 2/4] Remove unused package "fmt" --- phpfpm/exporter.go | 1 - 1 file changed, 1 deletion(-) diff --git a/phpfpm/exporter.go b/phpfpm/exporter.go index 55c27b6..598b185 100644 --- a/phpfpm/exporter.go +++ b/phpfpm/exporter.go @@ -14,7 +14,6 @@ package phpfpm import ( - "fmt" "github.com/prometheus/client_golang/prometheus" "sync" ) From 510d087da9a3892044f6a6cd9fc08f3ee8c9b02f Mon Sep 17 00:00:00 2001 From: Enrico Stahn Date: Thu, 22 Feb 2018 16:05:49 +1100 Subject: [PATCH 3/4] Fix: Label pool.Name on metric was missing --- phpfpm/exporter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpfpm/exporter.go b/phpfpm/exporter.go index 598b185..86343a0 100644 --- a/phpfpm/exporter.go +++ b/phpfpm/exporter.go @@ -135,10 +135,10 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { e.PoolManager.Update() for _, pool := range e.PoolManager.Pools { - ch <- prometheus.MustNewConstMetric(e.scrapeFailues, prometheus.CounterValue, float64(pool.ScrapeFailures)) + ch <- prometheus.MustNewConstMetric(e.scrapeFailues, prometheus.CounterValue, float64(pool.ScrapeFailures), pool.Name) if pool.ScrapeError != nil { - ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0) + ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0, pool.Name) log.Error("Error scraping PHP-FPM: %v", pool.ScrapeError) continue } From dc5bc0ae6e19934910d26ac9ccb4ae246f0f7f14 Mon Sep 17 00:00:00 2001 From: Enrico Stahn Date: Thu, 22 Feb 2018 16:06:07 +1100 Subject: [PATCH 4/4] Update "Metrics collected" in README.md --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 5113da8..2b8b8f3 100644 --- a/README.md +++ b/README.md @@ -94,12 +94,16 @@ The `server` command runs the server required for prometheus to retrieve the sta # TYPE phpfpm_max_children_reached counter # HELP phpfpm_max_listen_queue The maximum number of requests in the queue of pending connections since FPM has started. # TYPE phpfpm_max_listen_queue counter +# HELP phpfpm_scrape_failures The number of failures scraping from PHP-FPM. +# TYPE phpfpm_scrape_failures counter # HELP phpfpm_slow_requests The number of requests that exceeded your 'request_slowlog_timeout' value. # TYPE phpfpm_slow_requests counter # HELP phpfpm_start_since The number of seconds since FPM has started. # TYPE phpfpm_start_since counter # HELP phpfpm_total_processes The number of idle + active processes. # TYPE phpfpm_total_processes gauge +# HELP phpfpm_up Could PHP-FPM be reached? +# TYPE phpfpm_up gauge ``` ## Contributing @@ -110,6 +114,15 @@ The project follows the typical GitHub pull request model. See " [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) " for more details. Before starting any work, please either comment on an existing issue, or file a new one. +## FAQ + +* **How to update "Metrics collected"?** + + Copy&paste the output from: + ``` + curl http://127.0.0.1:12345/metrics | grep phpfpm | grep "#" + ``` + ## Alternatives * [bakins/php-fpm-exporter](https://github.com/bakins/php-fpm-exporter)