master
go 83 lines 1.54 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 //go:build linux || freebsd || openbsd || netbsd || dragonfly || darwin
4
5 package nsd
6
7 import (
8 "bufio"
9 "bytes"
10 "errors"
11 "strconv"
12 "strings"
13 )
14
15 func (c *Collector) collect() (map[string]int64, error) {
16 stats, err := c.exec.stats()
17 if err != nil {
18 return nil, err
19 }
20
21 if len(stats) == 0 {
22 return nil, errors.New("empty stats response")
23 }
24
25 mx := make(map[string]int64)
26
27 sc := bufio.NewScanner(bytes.NewReader(stats))
28
29 for sc.Scan() {
30 c.collectStatsLine(mx, sc.Text())
31 }
32
33 if len(mx) == 0 {
34 return nil, errors.New("unexpected stats response: no metrics found")
35 }
36
37 addMissingMetrics(mx, "num.rcode.", answerRcodes)
38 addMissingMetrics(mx, "num.opcode.", queryOpcodes)
39 addMissingMetrics(mx, "num.class.", queryClasses)
40 addMissingMetrics(mx, "num.type.", queryTypes)
41
42 return mx, nil
43 }
44
45 func (c *Collector) collectStatsLine(mx map[string]int64, line string) {
46 if line = strings.TrimSpace(line); line == "" {
47 return
48 }
49
50 key, value, ok := strings.Cut(line, "=")
51 if !ok {
52 c.Debugf("invalid line in stats: '%s'", line)
53 return
54 }
55
56 var v int64
57 var f float64
58 var err error
59
60 switch key {
61 case "time.boot":
62 f, err = strconv.ParseFloat(value, 64)
63 v = int64(f)
64 default:
65 v, err = strconv.ParseInt(value, 10, 64)
66 }
67
68 if err != nil {
69 c.Debugf("invalid value in stats line '%s': '%s'", line, value)
70 return
71 }
72
73 mx[key] = v
74 }
75
76 func addMissingMetrics(mx map[string]int64, prefix string, values []string) {
77 for _, v := range values {
78 k := prefix + v
79 if _, ok := mx[k]; !ok {
80 mx[k] = 0
81 }
82 }
83 }