Nick Owens
9 years ago
3 changed files with 197 additions and 22 deletions
@ -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 |
||||
} |
||||
|
@ -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 <sys/param.h> |
||||
#include <sys/types.h> |
||||
#include <sys/sysctl.h> |
||||
|
||||
#include <errno.h> |
||||
#include <stdio.h> |
||||
|
||||
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 |
||||
} |
Loading…
Reference in new issue