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