From 73ee8f5257e34887de1ed149d0d82c5ce07c5d0b Mon Sep 17 00:00:00 2001 From: Nick Owens Date: Sun, 1 Nov 2015 22:55:46 -0800 Subject: [PATCH] collector: add openbsd support to interrupt collector --- collector/interrupts_common.go | 42 +++++++++ collector/interrupts_linux.go | 25 +----- collector/interrupts_openbsd.go | 152 ++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 22 deletions(-) create mode 100644 collector/interrupts_common.go create mode 100644 collector/interrupts_openbsd.go diff --git a/collector/interrupts_common.go b/collector/interrupts_common.go new file mode 100644 index 00000000..f1b57052 --- /dev/null +++ b/collector/interrupts_common.go @@ -0,0 +1,42 @@ +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !nointerrupts + +package collector + +import "github.com/prometheus/client_golang/prometheus" + +type interruptsCollector struct { + metric *prometheus.CounterVec +} + +func init() { + Factories["interrupts"] = NewInterruptsCollector +} + +// Takes a prometheus registry and returns a new Collector exposing +// interrupts stats +func NewInterruptsCollector() (Collector, error) { + return &interruptsCollector{ + metric: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: Namespace, + Name: "interrupts", + Help: "Interrupt details.", + }, + interruptLabelNames, + ), + }, nil +} + diff --git a/collector/interrupts_linux.go b/collector/interrupts_linux.go index 58fc738f..970641cb 100644 --- a/collector/interrupts_linux.go +++ b/collector/interrupts_linux.go @@ -27,28 +27,9 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -type interruptsCollector struct { - metric *prometheus.CounterVec -} - -func init() { - Factories["interrupts"] = NewInterruptsCollector -} - -// Takes a prometheus registry and returns a new Collector exposing -// interrupts stats -func NewInterruptsCollector() (Collector, error) { - return &interruptsCollector{ - metric: prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: Namespace, - Name: "interrupts", - Help: "Interrupt details.", - }, - []string{"CPU", "type", "info", "devices"}, - ), - }, nil -} +var ( + interruptLabelNames = []string{"CPU", "type", "info", "devices"} +) func (c *interruptsCollector) Update(ch chan<- prometheus.Metric) (err error) { interrupts, err := getInterrupts() diff --git a/collector/interrupts_openbsd.go b/collector/interrupts_openbsd.go new file mode 100644 index 00000000..c6ded5a8 --- /dev/null +++ b/collector/interrupts_openbsd.go @@ -0,0 +1,152 @@ +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !nointerrupts + +package collector + +import ( + "fmt" + "strconv" + + "github.com/prometheus/client_golang/prometheus" +) + +/* +#include +#include +#include + +#include +#include + +struct intr +{ + int vector; + char device[128]; + u_int64_t count; +}; + +int sysctl_nintr(void) +{ + int nintr, mib[4]; + size_t siz; + + mib[0] = CTL_KERN; + mib[1] = KERN_INTRCNT; + mib[2] = KERN_INTRCNT_NUM; + siz = sizeof(nintr); + if (sysctl(mib, 3, &nintr, &siz, NULL, 0) < 0) { + return -1; + } + + return nintr; +} + +int +sysctl_intr(struct intr *intr, int idx) +{ + int mib[4]; + size_t siz; + u_quad_t cnt; + + mib[0] = CTL_KERN; + mib[1] = KERN_INTRCNT; + mib[2] = KERN_INTRCNT_NAME; + mib[3] = idx; + siz = sizeof intr->device; + if (sysctl(mib, 4, intr->device, &siz, NULL, 0) < 0) { + return -1; + } + + mib[0] = CTL_KERN; + mib[1] = KERN_INTRCNT; + mib[2] = KERN_INTRCNT_VECTOR; + mib[3] = idx; + siz = sizeof intr->vector; + if (sysctl(mib, 4, &intr->vector, &siz, NULL, 0) < 0) { + return -1; + } + + mib[0] = CTL_KERN; + mib[1] = KERN_INTRCNT; + mib[2] = KERN_INTRCNT_CNT; + mib[3] = idx; + siz = sizeof(cnt); + if (sysctl(mib, 4, &cnt, &siz, NULL, 0) < 0) { + return -1; + } + + intr->count = cnt; + + return 1; +} +*/ +import "C" + + +var ( + interruptLabelNames = []string{"CPU", "type", "devices"} +) + +func (c *interruptsCollector) Update(ch chan<- prometheus.Metric) (err error) { + interrupts, err := getInterrupts() + if err != nil { + return fmt.Errorf("couldn't get interrupts: %s", err) + } + for dev, interrupt := range interrupts { + for cpuNo, value := range interrupt.values { + labels := prometheus.Labels{ + "CPU": strconv.Itoa(cpuNo), + "type": fmt.Sprintf("%d", interrupt.vector), + "devices": dev, + } + c.metric.With(labels).Set(value) + } + } + c.metric.Collect(ch) + return err +} + +type interrupt struct { + vector int + device string + values []float64 +} + +func getInterrupts() (map[string]interrupt, error) { + var ( + cintr C.struct_intr + interrupts = map[string]interrupt{} + ) + + nintr := C.sysctl_nintr() + + for i := C.int(0); i < nintr; i++ { + _, err := C.sysctl_intr(&cintr, i) + if err != nil { + return nil, err + } + + dev := C.GoString(&cintr.device[0]) + + interrupts[dev] = interrupt{ + vector: int(cintr.vector), + device: dev, + // XXX: openbsd appears to only handle interrupts on cpu 0. + values: []float64{float64(cintr.count)}, + } + } + + return interrupts, nil +}