/
ntpdate_poller.go
71 lines (60 loc) · 1.78 KB
/
ntpdate_poller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package shh
import (
"bytes"
"io"
"os/exec"
"strings"
"time"
"github.com/heroku/slog"
)
type Ntpdate struct {
measurements chan<- Measurement
Servers []string
}
func NewNtpdatePoller(measurements chan<- Measurement, config Config) Ntpdate {
return Ntpdate{
measurements: measurements,
Servers: config.NtpdateServers,
}
}
//FIXME: Timeout
func (poller Ntpdate) Poll(tick time.Time) {
ctx := slog.Context{"poller": poller.Name(), "fn": "Poll", "tick": tick}
if len(poller.Servers) > 0 {
cmd := exec.Command("ntpdate", "-q", "-u")
cmd.Args = append(cmd.Args, poller.Servers...)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
LogError(ctx, err, "running sub command: "+string(stderr.Bytes()))
poller.measurements <- GaugeMeasurement{tick, poller.Name(), []string{"error"}, 1, Errors}
return
}
for {
line, err := stdout.ReadString('\n')
if err == nil {
if strings.HasPrefix(line, "server") {
parts := strings.Split(line, ",")
server := strings.Replace(strings.Fields(parts[0])[1], ".", "_", 4)
offset := strings.Fields(parts[2])[1]
delay := strings.Fields(parts[3])[1]
poller.measurements <- FloatGaugeMeasurement{tick, poller.Name(), []string{"offset", server}, Atofloat64(offset), Seconds}
poller.measurements <- FloatGaugeMeasurement{tick, poller.Name(), []string{"delay", server}, Atofloat64(delay), Seconds}
}
} else {
if err == io.EOF {
break
} else {
LogError(ctx, err, "unknown error reading data from subcommand")
poller.measurements <- GaugeMeasurement{tick, poller.Name(), []string{"error"}, 1, Errors}
return
}
}
}
}
}
func (poller Ntpdate) Name() string {
return "ntpdate"
}
func (poller Ntpdate) Exit() {}