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) diff --git a/phpfpm/exporter.go b/phpfpm/exporter.go index ae8dbc1..86343a0 100644 --- a/phpfpm/exporter.go +++ b/phpfpm/exporter.go @@ -27,6 +27,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 +47,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 +135,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), pool.Name) + + if pool.ScrapeError != nil { + ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0, pool.Name) + 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 +157,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 }