2021-08-24 04:37:44 +08:00
|
|
|
//go:build !windows
|
2020-11-23 23:40:32 +08:00
|
|
|
// +build !windows
|
|
|
|
|
|
|
|
|
|
// TODO: Windows - should be enabled for Windows when super asterisk is fixed on Windows
|
|
|
|
|
// https://github.com/influxdata/telegraf/issues/6248
|
|
|
|
|
|
2015-10-12 09:36:21 +08:00
|
|
|
package phpfpm
|
|
|
|
|
|
|
|
|
|
import (
|
2016-01-15 06:20:59 +08:00
|
|
|
"crypto/rand"
|
|
|
|
|
"encoding/binary"
|
2015-10-12 09:36:21 +08:00
|
|
|
"fmt"
|
2016-01-15 06:20:59 +08:00
|
|
|
"net"
|
|
|
|
|
"net/http"
|
|
|
|
|
"net/http/fcgi"
|
|
|
|
|
"net/http/httptest"
|
2015-10-12 09:36:21 +08:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
2021-11-15 23:14:09 +08:00
|
|
|
|
|
|
|
|
"github.com/influxdata/telegraf/testutil"
|
2015-10-12 09:36:21 +08:00
|
|
|
)
|
|
|
|
|
|
2016-01-15 06:20:59 +08:00
|
|
|
type statServer struct{}
|
|
|
|
|
|
|
|
|
|
// We create a fake server to return test data
|
2021-03-23 01:21:36 +08:00
|
|
|
func (s statServer) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
|
2016-01-15 06:20:59 +08:00
|
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
|
|
|
w.Header().Set("Content-Length", fmt.Sprint(len(outputSample)))
|
2021-04-09 00:43:39 +08:00
|
|
|
// Ignore the returned error as the tests will fail anyway
|
|
|
|
|
//nolint:errcheck,revive
|
2016-01-15 06:20:59 +08:00
|
|
|
fmt.Fprint(w, outputSample)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPhpFpmGeneratesMetrics_From_Http(t *testing.T) {
|
2020-10-20 23:45:30 +08:00
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
require.Equal(t, "ok", r.URL.Query().Get("test"))
|
|
|
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
|
|
|
w.Header().Set("Content-Length", fmt.Sprint(len(outputSample)))
|
2021-04-09 00:43:39 +08:00
|
|
|
_, err := fmt.Fprint(w, outputSample)
|
|
|
|
|
require.NoError(t, err)
|
2020-10-20 23:45:30 +08:00
|
|
|
}))
|
2015-10-12 09:36:21 +08:00
|
|
|
defer ts.Close()
|
|
|
|
|
|
2020-10-20 23:45:30 +08:00
|
|
|
url := ts.URL + "?test=ok"
|
2015-10-12 09:36:21 +08:00
|
|
|
r := &phpfpm{
|
2020-10-20 23:45:30 +08:00
|
|
|
Urls: []string{url},
|
2015-10-12 09:36:21 +08:00
|
|
|
}
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, r.Init())
|
2020-07-01 05:19:54 +08:00
|
|
|
|
2015-10-12 09:36:21 +08:00
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, acc.GatherError(r.Gather))
|
2015-10-12 09:36:21 +08:00
|
|
|
|
|
|
|
|
tags := map[string]string{
|
2016-01-15 06:20:59 +08:00
|
|
|
"pool": "www",
|
2020-10-20 23:45:30 +08:00
|
|
|
"url": url,
|
2016-01-15 06:20:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fields := map[string]interface{}{
|
2019-06-18 03:55:09 +08:00
|
|
|
"start_since": int64(1991),
|
2016-01-15 06:20:59 +08:00
|
|
|
"accepted_conn": int64(3),
|
|
|
|
|
"listen_queue": int64(1),
|
|
|
|
|
"max_listen_queue": int64(0),
|
|
|
|
|
"listen_queue_len": int64(0),
|
|
|
|
|
"idle_processes": int64(1),
|
|
|
|
|
"active_processes": int64(1),
|
|
|
|
|
"total_processes": int64(2),
|
|
|
|
|
"max_active_processes": int64(1),
|
|
|
|
|
"max_children_reached": int64(2),
|
|
|
|
|
"slow_requests": int64(1),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "phpfpm", fields, tags)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPhpFpmGeneratesMetrics_From_Fcgi(t *testing.T) {
|
|
|
|
|
// Let OS find an available port
|
|
|
|
|
tcp, err := net.Listen("tcp", "127.0.0.1:0")
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, err, "Cannot initialize test server")
|
2016-01-15 06:20:59 +08:00
|
|
|
defer tcp.Close()
|
|
|
|
|
|
|
|
|
|
s := statServer{}
|
2021-04-09 00:43:39 +08:00
|
|
|
//nolint:errcheck,revive
|
2016-01-15 06:20:59 +08:00
|
|
|
go fcgi.Serve(tcp, s)
|
|
|
|
|
|
|
|
|
|
//Now we tested again above server
|
|
|
|
|
r := &phpfpm{
|
|
|
|
|
Urls: []string{"fcgi://" + tcp.Addr().String() + "/status"},
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, r.Init())
|
2020-07-01 05:19:54 +08:00
|
|
|
|
2016-01-15 06:20:59 +08:00
|
|
|
var acc testutil.Accumulator
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, acc.GatherError(r.Gather))
|
2016-01-15 06:20:59 +08:00
|
|
|
|
|
|
|
|
tags := map[string]string{
|
|
|
|
|
"pool": "www",
|
2018-03-24 02:50:52 +08:00
|
|
|
"url": r.Urls[0],
|
2016-01-15 06:20:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fields := map[string]interface{}{
|
2019-06-18 03:55:09 +08:00
|
|
|
"start_since": int64(1991),
|
2016-01-15 06:20:59 +08:00
|
|
|
"accepted_conn": int64(3),
|
|
|
|
|
"listen_queue": int64(1),
|
|
|
|
|
"max_listen_queue": int64(0),
|
|
|
|
|
"listen_queue_len": int64(0),
|
|
|
|
|
"idle_processes": int64(1),
|
|
|
|
|
"active_processes": int64(1),
|
|
|
|
|
"total_processes": int64(2),
|
|
|
|
|
"max_active_processes": int64(1),
|
|
|
|
|
"max_children_reached": int64(2),
|
|
|
|
|
"slow_requests": int64(1),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "phpfpm", fields, tags)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPhpFpmGeneratesMetrics_From_Socket(t *testing.T) {
|
|
|
|
|
// Create a socket in /tmp because we always have write permission and if the
|
|
|
|
|
// removing of socket fail when system restart /tmp is clear so
|
|
|
|
|
// we don't have junk files around
|
|
|
|
|
var randomNumber int64
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, binary.Read(rand.Reader, binary.LittleEndian, &randomNumber))
|
2016-01-15 06:20:59 +08:00
|
|
|
tcp, err := net.Listen("unix", fmt.Sprintf("/tmp/test-fpm%d.sock", randomNumber))
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, err, "Cannot initialize server on port ")
|
2016-01-15 06:20:59 +08:00
|
|
|
|
|
|
|
|
defer tcp.Close()
|
|
|
|
|
s := statServer{}
|
2021-04-09 00:43:39 +08:00
|
|
|
//nolint:errcheck,revive
|
2016-01-15 06:20:59 +08:00
|
|
|
go fcgi.Serve(tcp, s)
|
|
|
|
|
|
|
|
|
|
r := &phpfpm{
|
|
|
|
|
Urls: []string{tcp.Addr().String()},
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, r.Init())
|
2020-07-01 05:19:54 +08:00
|
|
|
|
2016-01-15 06:20:59 +08:00
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, acc.GatherError(r.Gather))
|
2016-01-15 06:20:59 +08:00
|
|
|
|
|
|
|
|
tags := map[string]string{
|
|
|
|
|
"pool": "www",
|
2018-03-24 02:50:52 +08:00
|
|
|
"url": r.Urls[0],
|
2016-01-15 06:20:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fields := map[string]interface{}{
|
2019-06-18 03:55:09 +08:00
|
|
|
"start_since": int64(1991),
|
2016-01-15 06:20:59 +08:00
|
|
|
"accepted_conn": int64(3),
|
|
|
|
|
"listen_queue": int64(1),
|
|
|
|
|
"max_listen_queue": int64(0),
|
|
|
|
|
"listen_queue_len": int64(0),
|
|
|
|
|
"idle_processes": int64(1),
|
|
|
|
|
"active_processes": int64(1),
|
|
|
|
|
"total_processes": int64(2),
|
|
|
|
|
"max_active_processes": int64(1),
|
|
|
|
|
"max_children_reached": int64(2),
|
|
|
|
|
"slow_requests": int64(1),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "phpfpm", fields, tags)
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-29 06:47:04 +08:00
|
|
|
func TestPhpFpmGeneratesMetrics_From_Multiple_Sockets_With_Glob(t *testing.T) {
|
|
|
|
|
// Create a socket in /tmp because we always have write permission and if the
|
|
|
|
|
// removing of socket fail when system restart /tmp is clear so
|
|
|
|
|
// we don't have junk files around
|
|
|
|
|
var randomNumber int64
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, binary.Read(rand.Reader, binary.LittleEndian, &randomNumber))
|
2020-02-29 06:47:04 +08:00
|
|
|
socket1 := fmt.Sprintf("/tmp/test-fpm%d.sock", randomNumber)
|
|
|
|
|
tcp1, err := net.Listen("unix", socket1)
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, err, "Cannot initialize server on port ")
|
2020-02-29 06:47:04 +08:00
|
|
|
defer tcp1.Close()
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, binary.Read(rand.Reader, binary.LittleEndian, &randomNumber))
|
2020-02-29 06:47:04 +08:00
|
|
|
socket2 := fmt.Sprintf("/tmp/test-fpm%d.sock", randomNumber)
|
|
|
|
|
tcp2, err := net.Listen("unix", socket2)
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, err, "Cannot initialize server on port ")
|
2020-02-29 06:47:04 +08:00
|
|
|
defer tcp2.Close()
|
|
|
|
|
|
|
|
|
|
s := statServer{}
|
2021-04-09 00:43:39 +08:00
|
|
|
//nolint:errcheck,revive
|
2020-02-29 06:47:04 +08:00
|
|
|
go fcgi.Serve(tcp1, s)
|
2021-04-09 00:43:39 +08:00
|
|
|
//nolint:errcheck,revive
|
2020-02-29 06:47:04 +08:00
|
|
|
go fcgi.Serve(tcp2, s)
|
|
|
|
|
|
|
|
|
|
r := &phpfpm{
|
|
|
|
|
Urls: []string{"/tmp/test-fpm[\\-0-9]*.sock"},
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, r.Init())
|
2020-07-01 05:19:54 +08:00
|
|
|
|
2020-02-29 06:47:04 +08:00
|
|
|
var acc1, acc2 testutil.Accumulator
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, acc1.GatherError(r.Gather))
|
2020-02-29 06:47:04 +08:00
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, acc2.GatherError(r.Gather))
|
2020-02-29 06:47:04 +08:00
|
|
|
|
|
|
|
|
tags1 := map[string]string{
|
|
|
|
|
"pool": "www",
|
|
|
|
|
"url": socket1,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tags2 := map[string]string{
|
|
|
|
|
"pool": "www",
|
|
|
|
|
"url": socket2,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fields := map[string]interface{}{
|
|
|
|
|
"start_since": int64(1991),
|
|
|
|
|
"accepted_conn": int64(3),
|
|
|
|
|
"listen_queue": int64(1),
|
|
|
|
|
"max_listen_queue": int64(0),
|
|
|
|
|
"listen_queue_len": int64(0),
|
|
|
|
|
"idle_processes": int64(1),
|
|
|
|
|
"active_processes": int64(1),
|
|
|
|
|
"total_processes": int64(2),
|
|
|
|
|
"max_active_processes": int64(1),
|
|
|
|
|
"max_children_reached": int64(2),
|
|
|
|
|
"slow_requests": int64(1),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
acc1.AssertContainsTaggedFields(t, "phpfpm", fields, tags1)
|
|
|
|
|
acc2.AssertContainsTaggedFields(t, "phpfpm", fields, tags2)
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-15 06:20:59 +08:00
|
|
|
func TestPhpFpmGeneratesMetrics_From_Socket_Custom_Status_Path(t *testing.T) {
|
|
|
|
|
// Create a socket in /tmp because we always have write permission. If the
|
|
|
|
|
// removing of socket fail we won't have junk files around. Cuz when system
|
|
|
|
|
// restart, it clears out /tmp
|
|
|
|
|
var randomNumber int64
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, binary.Read(rand.Reader, binary.LittleEndian, &randomNumber))
|
2016-01-15 06:20:59 +08:00
|
|
|
tcp, err := net.Listen("unix", fmt.Sprintf("/tmp/test-fpm%d.sock", randomNumber))
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, err, "Cannot initialize server on port ")
|
2016-01-15 06:20:59 +08:00
|
|
|
|
|
|
|
|
defer tcp.Close()
|
|
|
|
|
s := statServer{}
|
2021-04-09 00:43:39 +08:00
|
|
|
//nolint:errcheck,revive
|
2016-01-15 06:20:59 +08:00
|
|
|
go fcgi.Serve(tcp, s)
|
|
|
|
|
|
|
|
|
|
r := &phpfpm{
|
|
|
|
|
Urls: []string{tcp.Addr().String() + ":custom-status-path"},
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, r.Init())
|
2020-07-01 05:19:54 +08:00
|
|
|
|
2016-01-15 06:20:59 +08:00
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, acc.GatherError(r.Gather))
|
2016-01-15 06:20:59 +08:00
|
|
|
|
|
|
|
|
tags := map[string]string{
|
2015-10-12 09:36:21 +08:00
|
|
|
"pool": "www",
|
2018-03-24 02:50:52 +08:00
|
|
|
"url": r.Urls[0],
|
2015-10-12 09:36:21 +08:00
|
|
|
}
|
|
|
|
|
|
2016-01-07 08:37:56 +08:00
|
|
|
fields := map[string]interface{}{
|
2019-06-18 03:55:09 +08:00
|
|
|
"start_since": int64(1991),
|
2016-01-07 08:37:56 +08:00
|
|
|
"accepted_conn": int64(3),
|
|
|
|
|
"listen_queue": int64(1),
|
|
|
|
|
"max_listen_queue": int64(0),
|
|
|
|
|
"listen_queue_len": int64(0),
|
|
|
|
|
"idle_processes": int64(1),
|
|
|
|
|
"active_processes": int64(1),
|
|
|
|
|
"total_processes": int64(2),
|
|
|
|
|
"max_active_processes": int64(1),
|
|
|
|
|
"max_children_reached": int64(2),
|
|
|
|
|
"slow_requests": int64(1),
|
2015-10-12 09:36:21 +08:00
|
|
|
}
|
|
|
|
|
|
2016-01-07 08:37:56 +08:00
|
|
|
acc.AssertContainsTaggedFields(t, "phpfpm", fields, tags)
|
2015-10-12 09:36:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//When not passing server config, we default to localhost
|
|
|
|
|
//We just want to make sure we did request stat from localhost
|
2016-01-15 06:20:59 +08:00
|
|
|
func TestPhpFpmDefaultGetFromLocalhost(t *testing.T) {
|
2021-07-31 03:14:23 +08:00
|
|
|
r := &phpfpm{Urls: []string{"http://bad.localhost:62001/status"}}
|
2015-10-12 09:36:21 +08:00
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, r.Init())
|
2020-07-01 05:19:54 +08:00
|
|
|
|
2015-10-12 09:36:21 +08:00
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
err := acc.GatherError(r.Gather)
|
2015-10-12 09:36:21 +08:00
|
|
|
require.Error(t, err)
|
2021-11-15 23:14:09 +08:00
|
|
|
require.Contains(t, err.Error(), "/status")
|
2015-10-12 09:36:21 +08:00
|
|
|
}
|
|
|
|
|
|
2016-01-15 06:20:59 +08:00
|
|
|
func TestPhpFpmGeneratesMetrics_Throw_Error_When_Fpm_Status_Is_Not_Responding(t *testing.T) {
|
2022-01-19 04:45:03 +08:00
|
|
|
if testing.Short() {
|
|
|
|
|
t.Skip("Skipping long test in short mode")
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-15 06:20:59 +08:00
|
|
|
r := &phpfpm{
|
|
|
|
|
Urls: []string{"http://aninvalidone"},
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, r.Init())
|
2020-07-01 05:19:54 +08:00
|
|
|
|
2016-01-15 06:20:59 +08:00
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
err := acc.GatherError(r.Gather)
|
2016-01-15 06:20:59 +08:00
|
|
|
require.Error(t, err)
|
2021-11-15 23:14:09 +08:00
|
|
|
require.Contains(t, err.Error(), `unable to connect to phpfpm status page 'http://aninvalidone'`)
|
|
|
|
|
require.Contains(t, err.Error(), `lookup aninvalidone`)
|
2016-01-15 06:20:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPhpFpmGeneratesMetrics_Throw_Error_When_Socket_Path_Is_Invalid(t *testing.T) {
|
|
|
|
|
r := &phpfpm{
|
|
|
|
|
Urls: []string{"/tmp/invalid.sock"},
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
require.NoError(t, r.Init())
|
2020-07-01 05:19:54 +08:00
|
|
|
|
2016-01-15 06:20:59 +08:00
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
|
2021-04-09 00:43:39 +08:00
|
|
|
err := acc.GatherError(r.Gather)
|
2016-01-15 06:20:59 +08:00
|
|
|
require.Error(t, err)
|
2021-11-15 23:14:09 +08:00
|
|
|
require.Equal(t, `socket doesn't exist "/tmp/invalid.sock"`, err.Error())
|
2016-01-15 06:20:59 +08:00
|
|
|
}
|
|
|
|
|
|
2015-10-12 09:36:21 +08:00
|
|
|
const outputSample = `
|
|
|
|
|
pool: www
|
|
|
|
|
process manager: dynamic
|
|
|
|
|
start time: 11/Oct/2015:23:38:51 +0000
|
|
|
|
|
start since: 1991
|
|
|
|
|
accepted conn: 3
|
|
|
|
|
listen queue: 1
|
|
|
|
|
max listen queue: 0
|
|
|
|
|
listen queue len: 0
|
|
|
|
|
idle processes: 1
|
|
|
|
|
active processes: 1
|
|
|
|
|
total processes: 2
|
|
|
|
|
max active processes: 1
|
|
|
|
|
max children reached: 2
|
|
|
|
|
slow requests: 1
|
|
|
|
|
`
|