Blob


1 package nlnet
3 import (
4 "bufio"
5 "bytes"
6 "fmt"
7 "io"
8 "os/exec"
9 "strconv"
10 "strings"
11 )
13 type stat struct {
14 name string
15 value float64
16 }
18 func parseStats(r io.Reader) (map[string]float64, error) {
19 stats := make(map[string]float64)
20 sc := bufio.NewScanner(r)
21 for sc.Scan() {
22 stat, err := parseStat(sc.Text())
23 if err != nil {
24 return stats, fmt.Errorf("parse stat: %v", err)
25 }
26 stats[stat.name] = stat.value
27 }
28 return stats, sc.Err()
29 }
31 func parseStat(line string) (stat, error) {
32 k, v, found := strings.Cut(line, "=")
33 if !found {
34 return stat{}, fmt.Errorf("%q not found", "=")
35 }
36 f, err := strconv.ParseFloat(v, 64)
37 if err != nil {
38 return stat{}, fmt.Errorf("parse %s value: %v", k, err)
39 }
40 return stat{name: k, value: f}, nil
41 }
43 func execForStats(path string) (map[string]float64, error) {
44 cmd := exec.Command(path, "stats_noreset")
45 buf := &bytes.Buffer{}
46 cmd.Stdout = buf
47 if err := cmd.Run(); err != nil {
48 return nil, err
49 }
50 return parseStats(buf)
51 }
53 func ReadUnboundStats() (map[string]float64, error) {
54 return execForStats("unbound-control")
55 }
57 func ReadNSDStats() (map[string]float64, error) {
58 return execForStats("nsd-control")
59 }