diff --git a/README.md b/README.md index a6ccb73..356c339 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Flags: Address on which to expose metrics and web interface. --web.telemetry-path="/metrics" Path under which to expose metrics. + --buckets=BUCKETS A comma delimited list of buckets to use -i, --ping.interval=1s Ping interval duration --privileged Run in privileged ICMP mode --log.level="info" Only log messages with the given severity or above. Valid levels: [debug, info, warn, diff --git a/collector.go b/collector.go index 182baf7..5d04246 100644 --- a/collector.go +++ b/collector.go @@ -27,20 +27,18 @@ const ( var ( labelNames = []string{"ip", "host"} +) - pingResponseSeconds = prometheus.NewHistogramVec( +func newPingResponseHistogram(buckets []float64) *prometheus.HistogramVec { + return prometheus.NewHistogramVec( prometheus.HistogramOpts{ Namespace: namespace, Name: "response_duration_seconds", Help: "A histogram of latencies for ping responses.", - Buckets: prometheus.ExponentialBuckets(0.00005, 2, 20), + Buckets: buckets, }, labelNames, ) -) - -func init() { - prometheus.MustRegister(pingResponseSeconds) } // SmokepingCollector collects metrics from the pinger. @@ -50,7 +48,7 @@ type SmokepingCollector struct { requestsSent *prometheus.Desc } -func NewSmokepingCollector(pingers *[]*ping.Pinger) *SmokepingCollector { +func NewSmokepingCollector(pingers *[]*ping.Pinger, pingResponseSeconds prometheus.HistogramVec) *SmokepingCollector { for _, pinger := range *pingers { pinger.OnRecv = func(pkt *ping.Packet) { pingResponseSeconds.WithLabelValues(pkt.IPAddr.String(), pkt.Addr).Observe(pkt.Rtt.Seconds()) diff --git a/main.go b/main.go index 7b2a3a7..93634bf 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,8 @@ import ( "fmt" "math" "net/http" + "strconv" + "strings" "time" "github.com/superq/smokeping_prober/ping" @@ -60,11 +62,25 @@ func init() { prometheus.MustRegister(version.NewCollector("smokeping_prober")) } +func parseBuckets(buckets string) ([]float64, error) { + bucketstrings := strings.Split(buckets, ",") + bucketlist := make([]float64, len(bucketstrings)) + for i := range bucketstrings { + value, err := strconv.ParseFloat(bucketstrings[i], 64) + if err != nil { + return nil, err + } + bucketlist[i] = value + } + return bucketlist, nil +} + func main() { var ( listenAddress = kingpin.Flag("web.listen-address", "Address on which to expose metrics and web interface.").Default(":9374").String() metricsPath = kingpin.Flag("web.telemetry-path", "Path under which to expose metrics.").Default("/metrics").String() + buckets = kingpin.Flag("buckets", "A comma delimited list of buckets to use").String() interval = kingpin.Flag("ping.interval", "Ping interval duration").Short('i').Default("1s").Duration() privileged = kingpin.Flag("privileged", "Run in privileged ICMP mode").Default("true").Bool() hosts = HostList(kingpin.Arg("hosts", "List of hosts to ping").Required()) @@ -77,6 +93,19 @@ func main() { log.Infoln("Starting smokeping_prober", version.Info()) log.Infoln("Build context", version.BuildContext()) + var bucketlist []float64 + if len(*buckets) == 0 { + bucketlist = prometheus.ExponentialBuckets(0.00005, 2, 20) + } else { + var err error + bucketlist, err = parseBuckets(*buckets) + if err != nil { + log.Errorf("ERROR: %s\n", err.Error()) + return + } + } + pingResponseSeconds := newPingResponseHistogram(bucketlist) + prometheus.MustRegister(pingResponseSeconds) pingers := make([]*ping.Pinger, len(*hosts)) for i, host := range *hosts { @@ -95,7 +124,7 @@ func main() { pingers[i] = pinger } - prometheus.MustRegister(NewSmokepingCollector(&pingers)) + prometheus.MustRegister(NewSmokepingCollector(&pingers, *pingResponseSeconds)) http.Handle(*metricsPath, promhttp.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {