Skip to content

Commit 35f290f

Browse files
committed
Refactored, fixed scrape on non-unix socket
1 parent b7fe538 commit 35f290f

File tree

3 files changed

+113
-99
lines changed

3 files changed

+113
-99
lines changed

fpmPrometeus/fpmPrometeus.go

Lines changed: 14 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,22 @@
11
package fpmPrometeus
22

33
import (
4-
"encoding/json"
54
"fmt"
6-
"io"
7-
"io/ioutil"
85
"strings"
96
"sync"
107
"time"
118

129
"github.com/prometheus/client_golang/prometheus"
13-
"github.com/tomasen/fcgi_client"
1410

1511
"github.com/code-tool/docker-fpm-wrapper/fpmConfig"
12+
"github.com/code-tool/docker-fpm-wrapper/pkg/phpfpm"
1613
)
1714

1815
const namespace = "phpfpm"
1916

20-
type Status struct {
21-
Name string `json:"pool"`
22-
ProcessManager string `json:"process manager"`
23-
StartTime int `json:"start time"`
24-
StartSince int `json:"start since"`
25-
AcceptedConn int `json:"accepted conn"`
26-
ListenQueue int `json:"listen queue"`
27-
MaxListenQueue int `json:"max listen queue"`
28-
ListenQueueLen int `json:"listen queue len"`
29-
IdleProcesses int `json:"idle processes"`
30-
ActiveProcesses int `json:"active processes"`
31-
TotalProcesses int `json:"total processes"`
32-
MaxActiveProcesses int `json:"max active processes"`
33-
MaxChildrenReached int `json:"max children reached"`
34-
SlowRequests int `json:"slow requests"`
35-
}
36-
3717
type stat struct {
3818
mu *sync.Mutex
39-
statuses []Status
19+
statuses []phpfpm.Status
4020
pools []fpmConfig.Pool
4121
}
4222

@@ -62,19 +42,26 @@ func startUpdateStatuses(fpmStatus *FPMPoolStatus, update time.Duration) {
6242
}
6343
}
6444

65-
func (s *stat) GetStatuses() []Status {
45+
func (s *stat) GetStatuses() []phpfpm.Status {
6646
s.mu.Lock()
67-
statuses := make([]Status, len(s.statuses))
47+
statuses := make([]phpfpm.Status, len(s.statuses))
6848
copy(statuses, s.statuses)
6949
s.mu.Unlock()
7050
return statuses
7151
}
7252

7353
func (s *stat) UpdateStatuses() error {
74-
statusCh := make(chan Status, 1)
54+
statusCh := make(chan phpfpm.Status, 1)
7555
errCh := make(chan error, 1)
7656
for _, pool := range s.pools {
77-
go getStats(pool.Listen, pool.StatusPath, statusCh, errCh)
57+
go func() {
58+
status, err := phpfpm.GetStats(pool.Listen, pool.StatusPath)
59+
if err != nil {
60+
errCh <- err
61+
} else {
62+
statusCh <- *status
63+
}
64+
}()
7865
}
7966

8067
errors := []string{}
@@ -120,7 +107,7 @@ func NewFPMPoolStatus(pools []fpmConfig.Pool) *FPMPoolStatus {
120107
stat: stat{
121108
mu: &sync.Mutex{},
122109
pools: pools,
123-
statuses: make([]Status, len(pools)),
110+
statuses: make([]phpfpm.Status, len(pools)),
124111
},
125112
startSince: prometheus.NewGaugeVec(
126113
prometheus.GaugeOpts{
@@ -249,43 +236,3 @@ func (e *FPMPoolStatus) Describe(ch chan<- *prometheus.Desc) {
249236
e.maxChildrenReached.Describe(ch)
250237
e.slowRequests.Describe(ch)
251238
}
252-
253-
func getStats(socket, script string, statusCh chan Status, errCh chan error) {
254-
if socket == "" {
255-
return
256-
}
257-
258-
env := map[string]string{
259-
"QUERY_STRING": "json&full",
260-
"SCRIPT_FILENAME": script,
261-
"SCRIPT_NAME": script,
262-
}
263-
264-
fcgi, err := fcgiclient.Dial("unix", socket)
265-
if err != nil {
266-
errCh <- err
267-
return
268-
}
269-
defer fcgi.Close()
270-
271-
resp, err := fcgi.Get(env)
272-
if err != nil && err != io.EOF {
273-
errCh <- err
274-
return
275-
}
276-
defer resp.Body.Close()
277-
278-
content, err := ioutil.ReadAll(resp.Body)
279-
if err != nil && err != io.EOF {
280-
errCh <- err
281-
return
282-
}
283-
s := Status{}
284-
err = json.Unmarshal(content, &s)
285-
if err != nil {
286-
errCh <- err
287-
return
288-
}
289-
290-
statusCh <- s
291-
}

main.go

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,37 @@ import (
1818

1919
func init() {
2020
pflag.StringP("fpm", "f", "", "path to php-fpm")
21+
pflag.StringP("fpm-config", "y", "/etc/php/php-fpm.conf", "path to php-fpm config file")
22+
2123
pflag.StringP("wrapper-socket", "s", "/tmp/fpm-wrapper.sock", "path to socket")
2224

23-
pflag.BoolP("prometheus", "p", false, "enable prometheus statistic")
24-
pflag.String("prometheus-addr", ":8080", "prometheus statistic addr")
25-
pflag.String("prometheus-path", "/metrics", "prometheus statistic path")
26-
pflag.Duration("fpm-statuses-update-interval", 10*time.Second, "fpm statuses update interval")
27-
pflag.String("fpm-config", "/etc/php/php-fpm.conf", "path to php-fpm config file")
25+
pflag.Bool("scrape", false, "Enable prometheus statistic")
26+
pflag.Duration("scrape-interval", 10*time.Second, "fpm statuses update interval")
27+
28+
pflag.String("listen", ":8080", "prometheus statistic addr")
29+
pflag.String("metrics-path", "/metrics", "prometheus statistic path")
30+
2831
pflag.Parse()
2932

3033
viper.BindPFlags(pflag.CommandLine)
3134
}
3235

36+
func findFpmArgs() []string {
37+
doubleDashIndex := -1
38+
39+
for i := range os.Args {
40+
if os.Args[i] == "--" {
41+
doubleDashIndex = i
42+
break
43+
}
44+
}
45+
if doubleDashIndex == -1 || doubleDashIndex+1 == len(os.Args) {
46+
return nil
47+
}
48+
49+
return os.Args[doubleDashIndex+1:]
50+
}
51+
3352
func main() {
3453
if viper.GetString("fpm") == "" {
3554
fmt.Println("php-fpm path not set")
@@ -46,6 +65,7 @@ func main() {
4665
cmd.Env = os.Environ()
4766
cmd.Env = append(cmd.Env, fmt.Sprintf("FPM_WRAPPER_SOCK=unix://%s", viper.GetString("wrapper-socket")))
4867
cmd.Args = append(cmd.Args, "--nodaemonize")
68+
cmd.Args = append(cmd.Args, "--fpm-config", viper.GetString("fpm-config"))
4969
cmd.Args = append(cmd.Args, findFpmArgs()...)
5070

5171
err := cmd.Start()
@@ -61,14 +81,20 @@ func main() {
6181
procErrCh <- cmd.Wait()
6282
}()
6383

64-
dataChan := make(chan string, 1)
6584
errCh := make(chan error, 1)
85+
86+
dataChan := make(chan string, 1)
6687
dataListener := NewDataListener(viper.GetString("wrapper-socket"), dataChan, errCh)
6788
dataListener.Start()
6889
defer dataListener.Stop()
6990

70-
if viper.GetBool("prometheus") {
71-
go startPrometheus()
91+
http.Handle(viper.GetString("metrics-path"), promhttp.Handler())
92+
go func() {
93+
errCh <- http.ListenAndServe(viper.GetString("listen"), nil)
94+
}()
95+
96+
if viper.GetBool("scrape") {
97+
fpmPrometeus.Register(viper.GetString("fpm-config"), viper.GetDuration("scrape-interval"))
7298
}
7399

74100
for {
@@ -83,8 +109,8 @@ func main() {
83109
if err == nil {
84110
os.Exit(0)
85111
}
86-
if exiterr, ok := err.(*exec.ExitError); ok {
87-
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
112+
if exitErr, ok := err.(*exec.ExitError); ok {
113+
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
88114
os.Exit(status.ExitStatus())
89115
}
90116
} else {
@@ -94,28 +120,6 @@ func main() {
94120
}
95121
}
96122

97-
func startPrometheus() {
98-
fpmPrometeus.Register(viper.GetString("fpm-config"), viper.GetDuration("fpm-statuses-update-interval"))
99-
http.Handle(viper.GetString("prometheus-path"), promhttp.Handler())
100-
http.ListenAndServe(viper.GetString("prometheus-addr"), nil)
101-
}
102-
103-
func findFpmArgs() []string {
104-
doubleDashIndex := -1
105-
106-
for i := range os.Args {
107-
if os.Args[i] == "--" {
108-
doubleDashIndex = i
109-
break
110-
}
111-
}
112-
if doubleDashIndex == -1 || doubleDashIndex+1 == len(os.Args) {
113-
return nil
114-
}
115-
116-
return os.Args[doubleDashIndex+1:]
117-
}
118-
119123
func handleSignals(cmd *exec.Cmd, signalCh chan os.Signal) {
120124
for {
121125
err := cmd.Process.Signal(<-signalCh)

pkg/phpfpm/status.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package phpfpm
2+
3+
import (
4+
"github.com/tomasen/fcgi_client"
5+
"time"
6+
"io"
7+
"io/ioutil"
8+
"encoding/json"
9+
"strings"
10+
)
11+
12+
type Status struct {
13+
Name string `json:"pool"`
14+
ProcessManager string `json:"process manager"`
15+
StartTime int `json:"start time"`
16+
StartSince int `json:"start since"`
17+
AcceptedConn int `json:"accepted conn"`
18+
ListenQueue int `json:"listen queue"`
19+
MaxListenQueue int `json:"max listen queue"`
20+
ListenQueueLen int `json:"listen queue len"`
21+
IdleProcesses int `json:"idle processes"`
22+
ActiveProcesses int `json:"active processes"`
23+
TotalProcesses int `json:"total processes"`
24+
MaxActiveProcesses int `json:"max active processes"`
25+
MaxChildrenReached int `json:"max children reached"`
26+
SlowRequests int `json:"slow requests"`
27+
}
28+
29+
func GetStats(listen, statusPath string) (*Status, error) {
30+
network := "tcp"
31+
if strings.Contains(listen, "/") && listen[0:1] != "[" {
32+
network = "unix"
33+
}
34+
35+
fcgi, err := fcgiclient.DialTimeout(network, listen, time.Second)
36+
if err != nil {
37+
return nil, err
38+
}
39+
defer fcgi.Close()
40+
41+
env := map[string]string{
42+
"QUERY_STRING": "json&full",
43+
"SCRIPT_FILENAME": statusPath,
44+
"SCRIPT_NAME": statusPath,
45+
}
46+
resp, err := fcgi.Get(env)
47+
if err != nil && err != io.EOF {
48+
return nil, err
49+
}
50+
defer resp.Body.Close()
51+
52+
content, err := ioutil.ReadAll(resp.Body)
53+
if err != nil && err != io.EOF {
54+
return nil, err
55+
}
56+
s := Status{}
57+
err = json.Unmarshal(content, &s)
58+
if err != nil {
59+
return nil, err
60+
}
61+
62+
return &s, nil
63+
}

0 commit comments

Comments
 (0)