package collectors import ( "io/ioutil" lp "github.com/influxdata/line-protocol" // "log" "encoding/json" "errors" "strconv" "strings" "time" ) const DISKSTATFILE = `/proc/diskstats` const DISKSTAT_SYSFSPATH = `/sys/block` type DiskstatCollectorConfig struct { ExcludeMetrics []string `json:"exclude_metrics,omitempty"` } type DiskstatCollector struct { MetricCollector matches map[int]string config DiskstatCollectorConfig } func (m *DiskstatCollector) Init(config []byte) error { var err error m.name = "DiskstatCollector" m.setup() if len(config) > 0 { err = json.Unmarshal(config, &m.config) if err != nil { return err } } // https://www.kernel.org/doc/html/latest/admin-guide/iostats.html matches := map[int]string{ 3: "reads", 4: "reads_merged", 5: "read_sectors", 6: "read_ms", 7: "writes", 8: "writes_merged", 9: "writes_sectors", 10: "writes_ms", 11: "ioops", 12: "ioops_ms", 13: "ioops_weighted_ms", 14: "discards", 15: "discards_merged", 16: "discards_sectors", 17: "discards_ms", 18: "flushes", 19: "flushes_ms", } m.matches = make(map[int]string) for k, v := range matches { _, skip := stringArrayContains(m.config.ExcludeMetrics, v) if !skip { m.matches[k] = v } } if len(m.matches) == 0 { return errors.New("No metrics to collect") } _, err = ioutil.ReadFile(string(DISKSTATFILE)) if err == nil { m.init = true } return err } func (m *DiskstatCollector) Read(interval time.Duration, out *[]lp.MutableMetric) { var lines []string if !m.init { return } buffer, err := ioutil.ReadFile(string(DISKSTATFILE)) if err != nil { return } lines = strings.Split(string(buffer), "\n") for _, line := range lines { if len(line) == 0 { continue } f := strings.Fields(line) if strings.Contains(f[2], "loop") { continue } tags := map[string]string{ "device": f[2], "type": "node", } for idx, name := range m.matches { if idx < len(f) { x, err := strconv.ParseInt(f[idx], 0, 64) if err == nil { y, err := lp.New(name, tags, map[string]interface{}{"value": int(x)}, time.Now()) if err == nil { *out = append(*out, y) } } } } } } func (m *DiskstatCollector) Close() { m.init = false }