func metaLinuxVersion() { _ = util.ReadCommand(func(line string) error { AddMeta("", nil, "uname", line, true) return nil }, "uname", "-a") _ = util.ReadCommand(func(line string) error { fields := strings.Fields(line) hasNum := false for i := 0; i < len(fields); { if strings.HasPrefix(fields[i], `\`) { fields = append(fields[:i], fields[i+1:]...) } else { if v, _ := strconv.ParseFloat(fields[i], 32); v > 0 { hasNum = true } i++ } } if !hasNum { return nil } AddMeta("", nil, "version", strings.Join(fields, " "), true) return nil }, "cat", "/etc/issue") }
func c_meta_darwin_version() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint util.ReadCommand(func(line string) error { metadata.AddMeta("", nil, "uname", line, true) return nil }, "uname", "-a") var name, vers, build string util.ReadCommand(func(line string) error { sp := strings.SplitN(line, ":", 2) if len(sp) != 2 { return nil } v := strings.TrimSpace(sp[1]) switch sp[0] { case "ProductName": name = v case "ProductVersion": vers = v case "BuildVersion": build = v } return nil }, "sw_vers") if name != "" && vers != "" && build != "" { metadata.AddMeta("", nil, "version", fmt.Sprintf("%s.%s", vers, build), true) metadata.AddMeta("", nil, "versionCaption", fmt.Sprintf("%s %s", name, vers), true) } return md, nil }
func metaDarwinVersion() { util.ReadCommand(func(line string) error { AddMeta("", nil, "uname", line, true) return nil }, "uname", "-a") var name, vers, build string util.ReadCommand(func(line string) error { sp := strings.SplitN(line, ":", 2) if len(sp) != 2 { return nil } v := strings.TrimSpace(sp[1]) switch sp[0] { case "ProductName": name = v case "ProductVersion": vers = v case "BuildVersion": build = v } return nil }, "sw_vers") if name != "" && vers != "" && build != "" { AddMeta("", nil, "version", fmt.Sprintf("%s.%s", vers, build), true) AddMeta("", nil, "versionCaption", fmt.Sprintf("%s %s", name, vers), true) } }
func c_dfstat_blocks_linux() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint err := util.ReadCommand(func(line string) error { fields := strings.Fields(line) // TODO: support mount points with spaces in them. They mess up the field order // currently due to df's columnar output. if len(fields) != 6 || !IsDigit(fields[2]) { return nil } fs := fields[0] mount := fields[5] tags := opentsdb.TagSet{"mount": mount} os_tags := opentsdb.TagSet{"disk": mount} metric := "linux.disk.fs." ometric := "os.disk.fs." if removable_fs(fs) { metric += "rem." ometric += "rem." } Add(&md, metric+"space_total", fields[1], tags, metadata.Gauge, metadata.Bytes, osDiskTotalDesc) Add(&md, metric+"space_used", fields[2], tags, metadata.Gauge, metadata.Bytes, osDiskUsedDesc) Add(&md, metric+"space_free", fields[3], tags, metadata.Gauge, metadata.Bytes, osDiskFreeDesc) Add(&md, ometric+"space_total", fields[1], os_tags, metadata.Gauge, metadata.Bytes, osDiskTotalDesc) Add(&md, ometric+"space_used", fields[2], os_tags, metadata.Gauge, metadata.Bytes, osDiskUsedDesc) Add(&md, ometric+"space_free", fields[3], os_tags, metadata.Gauge, metadata.Bytes, osDiskFreeDesc) st, _ := strconv.ParseFloat(fields[1], 64) sf, _ := strconv.ParseFloat(fields[3], 64) if st != 0 { Add(&md, osDiskPctFree, sf/st*100, os_tags, metadata.Gauge, metadata.Pct, osDiskPctFreeDesc) } return nil }, "df", "-lP", "--block-size", "1") return md, err }
func parseRailURL() string { var config string var url string util.ReadCommand(func(line string) error { fields := strings.Fields(line) if len(fields) == 0 || !strings.Contains(fields[0], "rg-listener") { return nil } for i, s := range fields { if s == "-config" && len(fields) > i { config = fields[i+1] } } return nil }, "ps", "-e", "-o", "args") if config == "" { return config } readLine(config, func(s string) error { if m := rgListenRE.FindStringSubmatch(s); len(m) > 0 { url = "http://" + m[1] } return nil }) return url }
func c_dfstat_inodes_linux() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint err := util.ReadCommand(func(line string) error { fields := strings.Fields(line) if len(fields) != 7 || !IsDigit(fields[2]) { return nil } // /dev/mapper/vg0-usr ext4 851968 468711 383257 56% /usr fs := fields[0] fsType := fields[1] inodesTotal := fields[2] inodesUsed := fields[3] inodesFree := fields[4] mount := fields[6] if isPseudoFS(fsType) { return nil } tags := opentsdb.TagSet{"mount": mount} metric := "linux.disk.fs." if removable_fs(fs) { metric += "rem." } Add(&md, metric+"inodes_total", inodesTotal, tags, metadata.Gauge, metadata.Count, "") Add(&md, metric+"inodes_used", inodesUsed, tags, metadata.Gauge, metadata.Count, "") Add(&md, metric+"inodes_free", inodesFree, tags, metadata.Gauge, metadata.Count, "") return nil }, "df", "-liPT") return md, err }
func redisInit() { update := func() { var instances []opentsdb.TagSet oldRedis := false add := func(port string) { ri := make(opentsdb.TagSet) ri["port"] = port instances = append(instances, ri) } util.ReadCommand(func(line string) error { sp := strings.Fields(line) if len(sp) != 3 || !strings.HasSuffix(sp[1], "redis-server") { return nil } if !strings.Contains(sp[2], ":") { oldRedis = true return nil } port := strings.Split(sp[2], ":")[1] if port != "0" { add(port) } return nil }, "ps", "-e", "-o", "pid,args") if oldRedis { util.ReadCommand(func(line string) error { if !strings.Contains(line, "redis-server") { return nil } sp := strings.Fields(line) if len(sp) < 7 || !strings.Contains(sp[3], ":") { return nil } port := strings.Split(sp[3], ":")[1] add(port) return nil }, "netstat", "-tnlp") } redisInstances = instances } update() go func() { for range time.Tick(time.Minute * 5) { update() } }() }
func c_vmstat_darwin() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint var free float64 util.ReadCommand(func(line string) error { if line == "" || strings.HasPrefix(line, "Object cache") || strings.HasPrefix(line, "Mach Virtual") { return nil } fields := strings.Split(line, ":") if len(fields) < 2 { return nil } value, err := strconv.ParseFloat(strings.TrimSpace(fields[1]), 64) if err != nil { return nil } if strings.HasPrefix(fields[0], "Pages") { name := strings.TrimSpace(fields[0]) name = strings.Replace(name, "Pages ", "", -1) name = strings.Replace(name, " ", "", -1) Add(&md, "darwin.mem.vm.4kpages."+name, value, nil, metadata.Unknown, metadata.None, "") if name == "free" { free = value * 4096 Add(&md, osMemFree, free, nil, metadata.Gauge, metadata.Bytes, osMemFreeDesc) } } else if fields[0] == "Pageins" { Add(&md, "darwin.mem.vm.pageins", value, nil, metadata.Counter, metadata.None, "") } else if fields[0] == "Pageouts" { Add(&md, "darwin.mem.vm.pageouts", value, nil, metadata.Counter, metadata.None, "") } return nil }, "vm_stat") util.ReadCommand(func(line string) error { total, _ := strconv.ParseFloat(line, 64) if total == 0 { return nil } Add(&md, osMemTotal, total, nil, metadata.Gauge, metadata.Bytes, osMemTotalDesc) if free == 0 { return nil } Add(&md, osMemUsed, total-free, nil, metadata.Gauge, metadata.Bytes, osMemUsedDesc) Add(&md, osMemPctFree, free/total, nil, metadata.Gauge, metadata.Pct, osMemPctFreeDesc) return nil }, "sysctl", "-n", "hw.memsize") return md, nil }
func c_meta_linux_version() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint _ = util.ReadCommand(func(line string) error { metadata.AddMeta("", nil, "uname", line, true) return nil }, "uname", "-a") if !readOSRelease() { readIssue() } return md, nil }
func readOmreport(f func([]string), args ...string) { args = append(args, "-fmt", "ssv") _ = util.ReadCommand(func(line string) error { sp := strings.Split(line, ";") for i, s := range sp { sp[i] = clean(s) } f(sp) return nil }, "omreport", args...) }
func c_netbackup_frequency() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint var class, schedule string var clients []string if err := util.ReadCommand(func(line string) error { if strings.HasPrefix(line, "Policy Name:") { clients = nil f := strings.Fields(line) if len(f) == 3 { class = f[2] return nil } return fmt.Errorf("error parsing policy: %v", line) } if strings.HasPrefix(line, "Client/HW/OS/Pri/DMI/CIT:") { f := strings.Fields(line) if len(f) == 9 { clients = append(clients, f[1]) return nil } return fmt.Errorf("error parsing client") } if strings.HasPrefix(line, "Schedule:") { f := strings.Fields(line) if len(f) > 1 { schedule = f[1] return nil } return fmt.Errorf("error parsing client: %v", line) } if strings.HasPrefix(strings.TrimSpace(line), "Frequency:") { f := strings.Fields(line) if len(f) == 5 { freq := strings.TrimLeft(f[3], "(") for _, client := range clients { tags := opentsdb.TagSet{"class": class, "client": client, "schedule": schedule} Add(&md, "netbackup.backup.frequency", freq, tags, metadata.Gauge, metadata.Second, "") } return nil } return fmt.Errorf("error parsing frequency: %v", line) } return nil }, "bppllist", "-L", "-allpolicies"); err == util.ErrPath { return nil, nil } else if err != nil { return nil, err } return md, nil }
func collectMetadataOmreport() { _ = util.ReadCommand(func(line string) error { fields := strings.Split(line, ";") if len(fields) != 2 { return nil } switch fields[0] { case "Chassis Service Tag": AddMeta("", nil, "serialNumber", fields[1], true) case "Chassis Model": AddMeta("", nil, "model", fields[1], true) } return nil }, "omreport", "chassis", "info", "-fmt", "ssv") }
func metaLinuxSerial() { _ = util.ReadCommand(func(line string) error { fields := strings.SplitN(line, ":", 2) if len(fields) != 2 { return nil } switch fields[0] { case "\tSerial Number": AddMeta("", nil, "serialNumber", strings.TrimSpace(fields[1]), true) case "\tProduct Name": AddMeta("", nil, "model", strings.TrimSpace(fields[1]), true) } return nil }, "dmidecode", "-t", "system") }
func c_iostat_darwin() (opentsdb.MultiDataPoint, error) { var categories []string var md opentsdb.MultiDataPoint ln := 0 i := 0 util.ReadCommand(func(line string) error { ln++ if ln == 1 { categories = strings.Fields(line) } if ln < 4 { return nil } values := strings.Fields(line) for _, cat := range categories { if i+3 > len(values) { break } else if strings.HasPrefix(cat, "disk") { Add(&md, "darwin.disk.kilobytes_transfer", values[i], opentsdb.TagSet{"disk": cat}, metadata.Unknown, metadata.None, "") i++ Add(&md, "darwin.disk.transactions", values[i], opentsdb.TagSet{"disk": cat}, metadata.Unknown, metadata.None, "") i++ Add(&md, "darwin.disk.megabytes", values[i], opentsdb.TagSet{"disk": cat}, metadata.Unknown, metadata.None, "") i++ } else if cat == "cpu" { Add(&md, "darwin.cpu.user", values[i], nil, metadata.Gauge, metadata.Pct, descDarwinCPUUser) i++ Add(&md, "darwin.cpu.sys", values[i], nil, metadata.Gauge, metadata.Pct, descDarwinCPUSys) i++ Add(&md, "darwin.cpu.idle", values[i], nil, metadata.Gauge, metadata.Pct, descDarwinCPUIdle) i++ } else if cat == "load" { Add(&md, "darwin.loadavg_1_min", values[i], nil, metadata.Unknown, metadata.None, "") i++ Add(&md, "darwin.loadavg_5_min", values[i], nil, metadata.Unknown, metadata.None, "") i++ Add(&md, "darwin.loadavg_15_min", values[i], nil, metadata.Unknown, metadata.None, "") i++ } } return nil }, "iostat", "-c2", "-w1") if ln < 4 { return nil, fmt.Errorf("bad return value") } return md, nil }
func c_meta_linux_serial() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint _ = util.ReadCommand(func(line string) error { fields := strings.SplitN(line, ":", 2) if len(fields) != 2 { return nil } switch fields[0] { case "\tSerial Number": metadata.AddMeta("", nil, "serialNumber", strings.TrimSpace(fields[1]), true) case "\tProduct Name": metadata.AddMeta("", nil, "model", strings.TrimSpace(fields[1]), true) } return nil }, "dmidecode", "-t", "system") return md, nil }
func metaLinuxIfaces() { metaIfaces(func(iface net.Interface, tags opentsdb.TagSet) { if speed, err := ioutil.ReadFile("/sys/class/net/" + iface.Name + "/speed"); err == nil { v, _ := strconv.Atoi(strings.TrimSpace(string(speed))) if v > 0 { const MbitToBit = 1e6 AddMeta("", tags, "speed", v*MbitToBit, true) } } _ = util.ReadCommand(func(line string) error { if v := metaLinuxIfacesMaster(line); v != "" { AddMeta("", tags, "master", v, true) return doneErr } return nil }, "ip", "-o", "addr", "show", iface.Name) }) }
func c_ntp_peers_unix() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint const metric = "ntp." _ = util.ReadCommand(func(line string) error { fields := strings.Fields(line) if len(fields) != len(ntpNtpqPeerFields) || fields[0] == "remote" { return nil } r := []rune(line) if len(r) < 2 { return fmt.Errorf("unexpected length of line") } fl := string(r[0]) rest := string(r[1:]) fields = strings.Fields(rest) if len(fields) != len(ntpNtpqPeerFields) { return fmt.Errorf("unexpected length of fields") } remote := fields[0] tags := opentsdb.TagSet{"remote": remote, "refid": fields[1]} var current_source int if fl == "*" { current_source = 1 } Add(&md, metric+"current_source", current_source, tags, metadata.Gauge, metadata.Bool, "") Add(&md, metric+"stratum", fields[2], tags, metadata.Gauge, "Stratum", "") when, err := ntpUnPretty(fields[4]) if err != nil { return err } Add(&md, metric+"when", when, tags, metadata.Gauge, metadata.Second, "") poll, err := ntpUnPretty(fields[5]) if err != nil { return err } Add(&md, metric+"poll", poll, tags, metadata.Gauge, metadata.Second, "") Add(&md, metric+"reach", fields[6], tags, metadata.Gauge, "Code", "") Add(&md, metric+"delay", fields[7], tags, metadata.Gauge, metadata.MilliSecond, "") Add(&md, metric+"offset", fields[8], tags, metadata.Gauge, metadata.MilliSecond, "") Add(&md, metric+"jitter", fields[9], tags, metadata.Gauge, metadata.MilliSecond, "") return nil }, "ntpq", "-pn") return md, nil }
func c_netbackup_jobs() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint latest := make(map[string]nbJob) if err := util.ReadCommand(func(line string) error { if len(line) < 32 { return nil } var r nbJob reader := csv.NewReader(strings.NewReader(line)) if err := nbUnmarhsall(reader, &r); err != nil { return err } if !(r.Jobtype == 0 || r.Jobtype == 6) { return nil } if r.State != 3 && r.State != 5 { return nil } key := r.Class + r.Schedule + r.Client if existing, ok := latest[key]; !ok { latest[key] = r } else if r.Started.After(existing.Started) { latest[key] = r } return nil }, "bpdbjobs", "-report", "-all_columns"); err == util.ErrPath { return nil, nil } else if err != nil { return nil, err } now := time.Now() for _, r := range latest { tags := opentsdb.TagSet{"class": r.Class, "client": r.Client, "schedule": r.Schedule} Add(&md, "netbackup.backup.status", r.Status, tags, metadata.Gauge, metadata.StatusCode, "") Add(&md, "netbackup.backup.duration", r.Elapsed, tags, metadata.Gauge, metadata.Second, "") Add(&md, "netbackup.backup.attempt_age", now.Sub(r.Ended).Seconds(), tags, metadata.Gauge, metadata.Second, "") Add(&md, "netbackup.backup.duration", r.Elapsed, tags, metadata.Gauge, metadata.Second, "") Add(&md, "netbackup.backup.no_files", r.Files, tags, metadata.Gauge, metadata.Count, "") Add(&md, "netbackup.backup.kbytes", r.Kbytes, tags, metadata.Gauge, metadata.KBytes, "") } return md, nil }
func c_dfstat_blocks_linux() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint err := util.ReadCommand(func(line string) error { fields := strings.Fields(line) // TODO: support mount points with spaces in them. They mess up the field order // currently due to df's columnar output. if len(fields) != 7 || !IsDigit(fields[2]) { return nil } // /dev/mapper/vg0-usr ext4 13384816 9996920 2815784 79% /usr fs := fields[0] fsType := fields[1] spaceTotal := fields[2] spaceUsed := fields[3] spaceFree := fields[4] mount := fields[6] if isPseudoFS(fsType) { return nil } tags := opentsdb.TagSet{"mount": mount} os_tags := opentsdb.TagSet{"disk": mount} metric := "linux.disk.fs." ometric := "os.disk.fs." if removable_fs(fs) { metric += "rem." ometric += "rem." } Add(&md, metric+"space_total", spaceTotal, tags, metadata.Gauge, metadata.Bytes, osDiskTotalDesc) Add(&md, metric+"space_used", spaceUsed, tags, metadata.Gauge, metadata.Bytes, osDiskUsedDesc) Add(&md, metric+"space_free", spaceFree, tags, metadata.Gauge, metadata.Bytes, osDiskFreeDesc) Add(&md, ometric+"space_total", spaceTotal, os_tags, metadata.Gauge, metadata.Bytes, osDiskTotalDesc) Add(&md, ometric+"space_used", spaceUsed, os_tags, metadata.Gauge, metadata.Bytes, osDiskUsedDesc) Add(&md, ometric+"space_free", spaceFree, os_tags, metadata.Gauge, metadata.Bytes, osDiskFreeDesc) st, _ := strconv.ParseFloat(spaceTotal, 64) sf, _ := strconv.ParseFloat(spaceFree, 64) if st != 0 { Add(&md, osDiskPctFree, sf/st*100, os_tags, metadata.Gauge, metadata.Pct, osDiskPctFreeDesc) } return nil }, "df", "-lPT", "--block-size", "1") return md, err }
func c_dfstat_inodes_linux() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint err := util.ReadCommand(func(line string) error { fields := strings.Fields(line) if len(fields) != 6 || !IsDigit(fields[2]) { return nil } mount := fields[5] fs := fields[0] tags := opentsdb.TagSet{"mount": mount} metric := "linux.disk.fs." if removable_fs(fs) { metric += "rem." } Add(&md, metric+"inodes_total", fields[1], tags, metadata.Gauge, metadata.Count, "") Add(&md, metric+"inodes_used", fields[2], tags, metadata.Gauge, metadata.Count, "") Add(&md, metric+"inodes_free", fields[3], tags, metadata.Gauge, metadata.Count, "") return nil }, "df", "-liP") return md, err }
func c_ipcount_linux() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint v4c := 0 v6c := 0 err := util.ReadCommand(func(line string) error { tl := strings.TrimSpace(line) if strings.HasPrefix(tl, "inet ") { v4c++ } if strings.HasPrefix(tl, "inet6 ") { v6c++ } return nil }, "ip", "addr", "list") if err != nil { return md, err } Add(&md, "linux.net.ip_count", v4c, opentsdb.TagSet{"version": "4"}, metadata.Gauge, "IP_Addresses", "") Add(&md, "linux.net.ip_count", v6c, opentsdb.TagSet{"version": "6"}, metadata.Gauge, "IP_Addresses", "") return md, nil }
func c_memcached_stats() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint const metric = "memcached." util.ReadCommand(func(line string) error { f := strings.Fields(line) if len(f) != 2 { return nil } v, err := strconv.ParseFloat(f[1], 64) if err != nil { return nil } if m, ok := memcachedMeta[f[0]]; ok { name := f[0] if m.Metric != "" { name = m.Metric } Add(&md, metric+name, v, m.TagSet, m.RateType, m.Unit, m.Desc) } return nil }, "memcached-tool", "127.0.0.1:11211", "stats") return md, nil }
func c_nodestats_cfstats_linux() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint var keyspace, table string util.ReadCommand(func(line string) error { fields := strings.Split(strings.TrimSpace(line), ": ") if len(fields) != 2 { return nil } if fields[0] == "Keyspace" { keyspace = fields[1] table = "" return nil } if fields[0] == "Table" { table = fields[1] return nil } metric := strings.Replace(fields[0], " ", "_", -1) metric = strings.Replace(metric, "(", "", -1) metric = strings.Replace(metric, ")", "", -1) metric = strings.Replace(metric, ",", "", -1) metric = strings.ToLower(metric) values := strings.Fields(fields[1]) if values[0] == "NaN" { return nil } value := values[0] if table == "" { Add(&md, "cassandra.tables."+metric, value, opentsdb.TagSet{"keyspace": keyspace}, metadata.Unknown, metadata.None, "") } else { Add(&md, "cassandra.tables."+metric, value, opentsdb.TagSet{"keyspace": keyspace, "table": table}, metadata.Unknown, metadata.None, "") } return nil }, "nodetool", "cfstats") return md, nil }
func c_dfstat_darwin() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint util.ReadCommand(func(line string) error { fields := strings.Fields(line) if line == "" || len(fields) < 9 || !IsDigit(fields[2]) { return nil } mount := fields[8] if strings.HasPrefix(mount, "/Volumes/Time Machine Backups") { return nil } f5, _ := strconv.Atoi(fields[5]) f6, _ := strconv.Atoi(fields[6]) tags := opentsdb.TagSet{"mount": mount} Add(&md, "darwin.disk.fs.total", fields[1], tags, metadata.Unknown, metadata.None, "") Add(&md, "darwin.disk.fs.used", fields[2], tags, metadata.Unknown, metadata.None, "") Add(&md, "darwin.disk.fs.free", fields[3], tags, metadata.Unknown, metadata.None, "") Add(&md, "darwin.disk.fs.inodes.total", f5+f6, tags, metadata.Unknown, metadata.None, "") Add(&md, "darwin.disk.fs.inodes.used", fields[5], tags, metadata.Unknown, metadata.None, "") Add(&md, "darwin.disk.fs.inodes.free", fields[6], tags, metadata.Unknown, metadata.None, "") return nil }, "df", "-lki") return md, nil }
func c_sntp_windows() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint const metric = "sntp." var ( stratum string delay float64 when float64 source string poll float64 ) if err := util.ReadCommand(func(line string) error { f := strings.SplitN(line, ":", 2) if len(f) != 2 { return nil } f[1] = strings.TrimSpace(f[1]) switch f[0] { case "Stratum": sf := strings.Fields(f[1]) if len(sf) < 1 { return fmt.Errorf("Unexpected value for stratum") } stratum = sf[0] case "Root Delay": d, err := time.ParseDuration(f[1]) if err != nil { return err } delay = d.Seconds() case "Last Successful Sync Time": if f[1] == "unspecified" { break } t, err := time.Parse("1/2/2006 3:04:05 PM", f[1]) if err != nil { return err } when = time.Since(t).Seconds() case "Source": source = strings.TrimSpace(f[1]) case "Poll Interval": sf := strings.Fields(f[1]) if len(sf) != 2 { return fmt.Errorf("Unexpected value for Poll Interval") } s := strings.Trim(sf[1], "()") d, err := time.ParseDuration(strings.TrimSpace(s)) if err != nil { return err } poll = d.Seconds() } return nil }, "w32tm", "/query", "/status"); err != nil { return nil, nil } tags := opentsdb.TagSet{"remote": source} Add(&md, metric+"stratum", stratum, tags, metadata.Gauge, "Stratum", "") Add(&md, metric+"delay", delay, tags, metadata.Gauge, metadata.Second, "") Add(&md, metric+"when", when, tags, metadata.Gauge, metadata.Second, "") Add(&md, metric+"poll", poll, tags, metadata.Gauge, metadata.Second, "") _ = util.ReadCommand(func(line string) error { f := strings.SplitN(line, ",", 2) if len(f) != 2 { return nil } d, err := time.ParseDuration(strings.TrimSpace(f[1])) if err != nil { return nil } Add(&md, metric+"offset", d.Seconds(), tags, metadata.Gauge, metadata.Second, "") return nil }, "w32tm", "/stripchart", fmt.Sprintf("/computer:%v", source), "/samples:1", "/dataonly") return md, nil }
func c_nodestats_cfstats_linux() (opentsdb.MultiDataPoint, error) { var md opentsdb.MultiDataPoint var keyspace, table string util.ReadCommand(func(line string) error { fields := strings.Split(strings.TrimSpace(line), ": ") if len(fields) != 2 { return nil } if fields[0] == "Keyspace" { keyspace = fields[1] table = "" return nil } if fields[0] == "Table" { table = fields[1] return nil } tagset := make(opentsdb.TagSet) metricset := make(MetricSet) if table != "" { tagset["table"] = table } if keyspace != "" { tagset["keyspace"] = keyspace } metric := strings.Replace(fields[0], " ", "_", -1) metric = strings.Replace(metric, "(", "", -1) metric = strings.Replace(metric, ")", "", -1) metric = strings.Replace(metric, ",", "", -1) metric = strings.ToLower(metric) /* This is to handle lines like "SSTables in each level: [31/4, 0, 0, 0, 0, 0, 0, 0]" sstables_in_each_level format (BNF): <count> ::= <integer> <max_threshold> ::= <integer> <exceeded> ::= <count> "/" <max_threshold> <level_item> ::= <count>|<exceeded> <list_item> ::= <level_item> "," " " | <level_item> <list> ::= <list_item> | <list_item> <list> <per_level> ::= "[" <list> "]" */ if metric == "sstables_in_each_level" { fields[1] = strings.Replace(fields[1], "[", "", -1) fields[1] = strings.Replace(fields[1], "]", "", -1) per_level := strings.Split(fields[1], ", ") for index, count := range per_level { metricset["cassandra.tables.sstables_in_level_"+strconv.Itoa(index)] = strings.Split(count, "/")[0] } submitMetrics(&md, metricset, tagset) return nil } // every other value is simpler, and we only want the first word values := strings.Fields(fields[1]) if _, err := strconv.ParseFloat(values[0], 64); err != nil || values[0] == "NaN" { return nil } metricset["cassandra.tables."+metric] = values[0] submitMetrics(&md, metricset, tagset) return nil }, "nodetool", "cfstats") return md, nil }