bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/ntp_unix.go (about)

     1  // +build !windows
     2  
     3  package collectors
     4  
     5  import (
     6  	"fmt"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"time"
    11  
    12  	"bosun.org/metadata"
    13  	"bosun.org/opentsdb"
    14  	"bosun.org/util"
    15  )
    16  
    17  func init() {
    18  	collectors = append(collectors, &IntervalCollector{F: c_ntp_peers_unix, Interval: time.Minute})
    19  }
    20  
    21  var ntpNtpqPeerFields = []string{
    22  	"remote",
    23  	"refid",
    24  	"st",
    25  	"t",
    26  	"when",
    27  	"poll",
    28  	"reach",
    29  	"delay",
    30  	"offset",
    31  	"jitter",
    32  }
    33  
    34  // ntUnPretty reverses human formating for poll and when, see prettyinterval in ntpq/ntpq-subs.c
    35  func ntpUnPretty(s string) (int64, error) {
    36  	if len(s) < 1 {
    37  		return 0, fmt.Errorf("Zero length string passed to ntpUnPretty")
    38  	}
    39  	var multiplier int64 = 1
    40  	shift := 1
    41  	switch s[len(s)-1] {
    42  	case 'm':
    43  		multiplier = 60
    44  	case 'h':
    45  		multiplier = 60 * 60
    46  	case 'd':
    47  		multiplier = 60 * 60 * 24
    48  	default:
    49  		shift = 0
    50  	}
    51  	i, err := strconv.ParseInt(s[0:len(s)-shift], 10, 64)
    52  	return i * multiplier, err
    53  }
    54  
    55  func c_ntp_peers_unix() (opentsdb.MultiDataPoint, error) {
    56  	var md opentsdb.MultiDataPoint
    57  	const metric = "ntp."
    58  	_ = util.ReadCommand(func(line string) error {
    59  		fields := strings.Fields(line)
    60  		if len(fields) != len(ntpNtpqPeerFields) || fields[0] == "remote" {
    61  			return nil
    62  		}
    63  		r := []rune(line)
    64  		if len(r) < 2 {
    65  			return fmt.Errorf("unexpected length of line")
    66  		}
    67  		fl := string(r[0])
    68  		rest := string(r[1:])
    69  		fields = strings.Fields(rest)
    70  		if len(fields) != len(ntpNtpqPeerFields) {
    71  			return fmt.Errorf("unexpected length of fields")
    72  		}
    73  		remote := fields[0]
    74  		tags := opentsdb.TagSet{"remote": remote, "refid": fields[1]}
    75  		var current_source int
    76  		if fl == "*" {
    77  			current_source = 1
    78  		}
    79  		Add(&md, metric+"current_source", current_source, tags, metadata.Gauge, metadata.Bool, "")
    80  		Add(&md, metric+"stratum", fields[2], tags, metadata.Gauge, "Stratum", "")
    81  		when, err := ntpUnPretty(fields[4])
    82  		if err != nil {
    83  			return err
    84  		}
    85  		Add(&md, metric+"when", when, tags, metadata.Gauge, metadata.Second, "")
    86  		poll, err := ntpUnPretty(fields[5])
    87  		if err != nil {
    88  			return err
    89  		}
    90  		Add(&md, metric+"poll", poll, tags, metadata.Gauge, metadata.Second, "")
    91  		Add(&md, metric+"reach", fields[6], tags, metadata.Gauge, "Code", "")
    92  		Add(&md, metric+"delay", fields[7], tags, metadata.Gauge, metadata.MilliSecond, "")
    93  		Add(&md, metric+"offset", fields[8], tags, metadata.Gauge, metadata.MilliSecond, "")
    94  		Add(&md, metric+"jitter", fields[9], tags, metadata.Gauge, metadata.MilliSecond, "")
    95  		return nil
    96  	}, "ntpq", "-pn")
    97  	return md, nil
    98  }