summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/phpfpm/decode.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/go/collectors/go.d.plugin/modules/phpfpm/decode.go132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/phpfpm/decode.go b/src/go/collectors/go.d.plugin/modules/phpfpm/decode.go
new file mode 100644
index 000000000..021e1fb4c
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/phpfpm/decode.go
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package phpfpm
+
+import (
+ "bufio"
+ "encoding/json"
+ "errors"
+ "io"
+ "strconv"
+ "strings"
+)
+
+type decoder func(r io.Reader, s *status) error
+
+func decodeJSON(r io.Reader, s *status) error {
+ return json.NewDecoder(r).Decode(s)
+}
+
+func decodeText(r io.Reader, s *status) error {
+ parts := readParts(r)
+ if len(parts) == 0 {
+ return errors.New("invalid text format")
+ }
+
+ part, parts := parts[0], parts[1:]
+ if err := readStatus(part, s); err != nil {
+ return err
+ }
+
+ return readProcesses(parts, s)
+}
+
+func readParts(r io.Reader) [][]string {
+ sc := bufio.NewScanner(r)
+
+ var parts [][]string
+ var lines []string
+ for sc.Scan() {
+ line := strings.Trim(sc.Text(), "\r\n ")
+ // Split parts by star border
+ if strings.HasPrefix(line, "***") {
+ parts = append(parts, lines)
+ lines = []string{}
+ continue
+ }
+ // Skip empty lines
+ if line == "" {
+ continue
+ }
+ lines = append(lines, line)
+ }
+
+ if len(lines) > 0 {
+ parts = append(parts, lines)
+ }
+ return parts
+}
+
+func readStatus(data []string, s *status) error {
+ for _, line := range data {
+ key, val, err := parseLine(line)
+ if err != nil {
+ return err
+ }
+
+ switch key {
+ case "active processes":
+ s.Active = parseInt(val)
+ case "max active processes":
+ s.MaxActive = parseInt(val)
+ case "idle processes":
+ s.Idle = parseInt(val)
+ case "accepted conn":
+ s.Requests = parseInt(val)
+ case "max children reached":
+ s.Reached = parseInt(val)
+ case "slow requests":
+ s.Slow = parseInt(val)
+ }
+ }
+ return nil
+}
+
+func readProcesses(procs [][]string, s *status) error {
+ for _, part := range procs {
+ var proc proc
+ for _, line := range part {
+ key, val, err := parseLine(line)
+ if err != nil {
+ return err
+ }
+
+ switch key {
+ case "state":
+ proc.State = val
+ case "request duration":
+ proc.Duration = requestDuration(parseInt(val))
+ case "last request cpu":
+ proc.CPU = parseFloat(val)
+ case "last request memory":
+ proc.Memory = parseInt(val)
+ }
+ }
+ s.Processes = append(s.Processes, proc)
+ }
+ return nil
+}
+
+func parseLine(s string) (string, string, error) {
+ kv := strings.SplitN(s, ":", 2)
+ if len(kv) != 2 {
+ return "", "", errors.New("invalid text format line")
+ }
+ return strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1]), nil
+}
+
+func parseInt(s string) int64 {
+ val, err := strconv.ParseInt(strings.TrimSpace(s), 10, 64)
+ if err != nil {
+ return 0
+ }
+ return val
+}
+
+func parseFloat(s string) float64 {
+ val, err := strconv.ParseFloat(strings.TrimSpace(s), 64)
+ if err != nil {
+ return 0
+ }
+ return val
+}