Browse Source

Add interrupts metrics

pull/5/head
Johannes 'fish' Ziemke 11 years ago
parent
commit
107f94d90a
  1. 76
      exporter/native_collector.go

76
exporter/native_collector.go

@ -16,8 +16,9 @@ import (
)
const (
procLoad = "/proc/loadavg"
procMemInfo = "/proc/meminfo"
procLoad = "/proc/loadavg"
procMemInfo = "/proc/meminfo"
procInterrupts = "/proc/interrupts"
)
type nativeCollector struct {
@ -25,6 +26,7 @@ type nativeCollector struct {
attributes prometheus.Gauge
lastSeen prometheus.Gauge
memInfo prometheus.Gauge
interrupts prometheus.Counter
name string
config config
}
@ -43,6 +45,7 @@ func NewNativeCollector(config config, registry prometheus.Registry) (Collector,
attributes: prometheus.NewGauge(),
lastSeen: prometheus.NewGauge(),
memInfo: prometheus.NewGauge(),
interrupts: prometheus.NewCounter(),
}
registry.Register(
@ -73,6 +76,13 @@ func NewNativeCollector(config config, registry prometheus.Registry) (Collector,
c.memInfo,
)
registry.Register(
"node_interrupts",
"node_exporter: interrupt details.",
prometheus.NilLabels,
c.interrupts,
)
return &c, nil
}
@ -111,6 +121,27 @@ func (c *nativeCollector) Update() (updates int, err error) {
}
c.memInfo.Set(map[string]string{"type": k}, fv)
}
interrupts, err := getInterrupts()
if err != nil {
return updates, fmt.Errorf("Couldn't get interrupts: %s", err)
}
for name, interrupt := range interrupts {
for cpuNo, value := range interrupt.values {
updates++
fv, err := strconv.ParseFloat(value, 64)
if err != nil {
return updates, fmt.Errorf("Invalid value in interrupts: %s", err)
}
labels := map[string]string{
"CPU": strconv.Itoa(cpuNo),
"type": name,
"info": interrupt.info,
"devices": interrupt.devices,
}
c.interrupts.Set(labels, fv)
}
}
return updates, err
}
@ -202,3 +233,44 @@ func getMemInfo() (map[string]string, error) {
return memInfo, nil
}
type interrupt struct {
info string
devices string
values []string
}
func getInterrupts() (map[string]interrupt, error) {
interrupts := map[string]interrupt{}
fh, err := os.Open(procInterrupts)
if err != nil {
return nil, err
}
defer fh.Close()
scanner := bufio.NewScanner(fh)
if !scanner.Scan() {
return nil, fmt.Errorf("%s empty", procInterrupts)
}
cpuNum := len(strings.Fields(string(scanner.Text()))) // one header per cpu
for scanner.Scan() {
line := scanner.Text()
parts := strings.Fields(string(line))
if len(parts) < cpuNum+2 { // irq + one column per cpu + details,
continue // we ignore ERR and MIS for now
}
intName := parts[0][:len(parts[0])-1] // remove trailing :
intr := interrupt{
values: parts[1:cpuNum],
}
if _, err := strconv.Atoi(intName); err == nil { // numeral interrupt
intr.info = parts[cpuNum+1]
intr.devices = strings.Join(parts[cpuNum+2:], " ")
} else {
intr.info = strings.Join(parts[cpuNum+1:], " ")
}
interrupts[intName] = intr
}
return interrupts, nil
}

Loading…
Cancel
Save