18 func parseStats(r io.Reader) (map[string]float64, error) {
19 stats := make(map[string]float64)
20 sc := bufio.NewScanner(r)
22 stat, err := parseStat(sc.Text())
24 return stats, fmt.Errorf("parse stat: %v", err)
26 stats[stat.name] = stat.value
28 return stats, sc.Err()
31 func parseStat(line string) (stat, error) {
32 k, v, found := strings.Cut(line, "=")
34 return stat{}, fmt.Errorf("%q not found", "=")
36 f, err := strconv.ParseFloat(v, 64)
38 return stat{}, fmt.Errorf("parse %s value: %v", k, err)
40 return stat{name: k, value: f}, nil
43 func execForStats(path string) (map[string]float64, error) {
44 cmd := exec.Command(path, "stats_noreset")
45 buf := &bytes.Buffer{}
47 if err := cmd.Run(); err != nil {
50 return parseStats(buf)
53 func ReadUnboundStats() (map[string]float64, error) {
54 return execForStats("unbound-control")
57 func ReadNSDStats() (map[string]float64, error) {
58 return execForStats("nsd-control")