master
go 89 lines 1.89 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package dovecot
4
5 import (
6 "bufio"
7 "bytes"
8 "errors"
9 "fmt"
10 "strconv"
11 "strings"
12 )
13
14 // FIXME: drop using "old_stats" in favour of "stats" (https://doc.dovecot.org/configuration_manual/stats/openmetrics/).
15
16 func (c *Collector) collect() (map[string]int64, error) {
17 if c.conn == nil {
18 conn, err := c.establishConn()
19 if err != nil {
20 return nil, err
21 }
22 c.conn = conn
23 }
24
25 stats, err := c.conn.queryExportGlobal()
26 if err != nil {
27 c.conn.disconnect()
28 c.conn = nil
29 return nil, err
30 }
31
32 mx := make(map[string]int64)
33
34 // https://doc.dovecot.org/configuration_manual/stats/old_statistics/#statistics-gathered
35 if err := c.collectExportGlobal(mx, stats); err != nil {
36 return nil, err
37 }
38
39 return mx, nil
40 }
41
42 func (c *Collector) collectExportGlobal(mx map[string]int64, resp []byte) error {
43 sc := bufio.NewScanner(bytes.NewReader(resp))
44
45 if !sc.Scan() {
46 return errors.New("failed to read fields line from export global response")
47 }
48 fieldsLine := strings.TrimSpace(sc.Text())
49
50 if !sc.Scan() {
51 return errors.New("failed to read values line from export global response")
52 }
53 valuesLine := strings.TrimSpace(sc.Text())
54
55 if fieldsLine == "" || valuesLine == "" {
56 return errors.New("empty fields line or values line from export global response")
57 }
58
59 fields := strings.Fields(fieldsLine)
60 values := strings.Fields(valuesLine)
61
62 if len(fields) != len(values) {
63 return fmt.Errorf("mismatched fields and values count: fields=%d, values=%d", len(fields), len(values))
64 }
65
66 for i, name := range fields {
67 val := values[i]
68
69 v, err := strconv.ParseInt(val, 10, 64)
70 if err != nil {
71 c.Debugf("failed to parse export value %s %s: %v", name, val, err)
72 continue
73 }
74
75 mx[name] = v
76 }
77
78 return nil
79 }
80
81 func (c *Collector) establishConn() (dovecotConn, error) {
82 conn := c.newConn(c.Config)
83
84 if err := conn.connect(); err != nil {
85 return nil, err
86 }
87
88 return conn, nil
89 }