diff options
author | Johannes 'fish' Ziemke <github@freigeist.org> | 2016-12-28 18:26:27 +0100 |
---|---|---|
committer | Johannes 'fish' Ziemke <github@freigeist.org> | 2016-12-28 18:38:52 +0100 |
commit | 050d6f7f134298acc1cfd3f214e8feff46d65949 (patch) | |
tree | f66711ec7ecf6340bc9df24d48d85bacf58a174e /collector/cpu_darwin.go | |
parent | 41271cd99cf6b3583cf27df85b1cc784c7eb2a21 (diff) | |
download | prometheus_node_collector-050d6f7f134298acc1cfd3f214e8feff46d65949.tar.bz2 prometheus_node_collector-050d6f7f134298acc1cfd3f214e8feff46d65949.tar.xz prometheus_node_collector-050d6f7f134298acc1cfd3f214e8feff46d65949.zip |
Add cpu collector for darwin
Diffstat (limited to 'collector/cpu_darwin.go')
-rw-r--r-- | collector/cpu_darwin.go | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/collector/cpu_darwin.go b/collector/cpu_darwin.go new file mode 100644 index 0000000..174e541 --- /dev/null +++ b/collector/cpu_darwin.go | |||
@@ -0,0 +1,119 @@ | |||
1 | // Copyright 2016 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | // Based on gopsutil/cpu/cpu_darwin_cgo.go @ ae251eb which is licensed under | ||
15 | // BSD. See https://github.com/shirou/gopsutil/blob/master/LICENSE for details. | ||
16 | |||
17 | // +build !nocpu | ||
18 | |||
19 | package collector | ||
20 | |||
21 | import ( | ||
22 | "bytes" | ||
23 | "encoding/binary" | ||
24 | "fmt" | ||
25 | "strconv" | ||
26 | "unsafe" | ||
27 | |||
28 | "github.com/prometheus/client_golang/prometheus" | ||
29 | ) | ||
30 | |||
31 | /* | ||
32 | #cgo LDFLAGS: | ||
33 | #include <stdlib.h> | ||
34 | #include <sys/sysctl.h> | ||
35 | #include <sys/mount.h> | ||
36 | #include <mach/mach_init.h> | ||
37 | #include <mach/mach_host.h> | ||
38 | #include <mach/host_info.h> | ||
39 | #if TARGET_OS_MAC | ||
40 | #include <libproc.h> | ||
41 | #endif | ||
42 | #include <mach/processor_info.h> | ||
43 | #include <mach/vm_map.h> | ||
44 | */ | ||
45 | import "C" | ||
46 | |||
47 | // default value. from time.h | ||
48 | const ClocksPerSec = float64(128) | ||
49 | |||
50 | type statCollector struct { | ||
51 | cpu *prometheus.Desc | ||
52 | } | ||
53 | |||
54 | func init() { | ||
55 | Factories["cpu"] = NewCPUCollector | ||
56 | } | ||
57 | |||
58 | // Takes a prometheus registry and returns a new Collector exposing | ||
59 | // CPU stats. | ||
60 | func NewCPUCollector() (Collector, error) { | ||
61 | return &statCollector{ | ||
62 | cpu: prometheus.NewDesc( | ||
63 | prometheus.BuildFQName(Namespace, "", "cpu"), | ||
64 | "Seconds the cpus spent in each mode.", | ||
65 | []string{"cpu", "mode"}, nil, | ||
66 | ), | ||
67 | }, nil | ||
68 | } | ||
69 | |||
70 | func (c *statCollector) Update(ch chan<- prometheus.Metric) error { | ||
71 | var ( | ||
72 | count C.mach_msg_type_number_t | ||
73 | cpuload *C.processor_cpu_load_info_data_t | ||
74 | ncpu C.natural_t | ||
75 | ) | ||
76 | |||
77 | status := C.host_processor_info(C.host_t(C.mach_host_self()), | ||
78 | C.PROCESSOR_CPU_LOAD_INFO, | ||
79 | &ncpu, | ||
80 | (*C.processor_info_array_t)(unsafe.Pointer(&cpuload)), | ||
81 | &count) | ||
82 | |||
83 | if status != C.KERN_SUCCESS { | ||
84 | return fmt.Errorf("host_processor_info error=%d", status) | ||
85 | } | ||
86 | |||
87 | // jump through some cgo casting hoops and ensure we properly free | ||
88 | // the memory that cpuload points to | ||
89 | target := C.vm_map_t(C.mach_task_self_) | ||
90 | address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload))) | ||
91 | defer C.vm_deallocate(target, address, C.vm_size_t(ncpu)) | ||
92 | |||
93 | // the body of struct processor_cpu_load_info | ||
94 | // aka processor_cpu_load_info_data_t | ||
95 | var cpu_ticks [C.CPU_STATE_MAX]uint32 | ||
96 | |||
97 | // copy the cpuload array to a []byte buffer | ||
98 | // where we can binary.Read the data | ||
99 | size := int(ncpu) * binary.Size(cpu_ticks) | ||
100 | buf := (*[1 << 30]byte)(unsafe.Pointer(cpuload))[:size:size] | ||
101 | |||
102 | bbuf := bytes.NewBuffer(buf) | ||
103 | |||
104 | for i := 0; i < int(ncpu); i++ { | ||
105 | err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks) | ||
106 | if err != nil { | ||
107 | return err | ||
108 | } | ||
109 | for k, v := range map[string]int{ | ||
110 | "user": C.CPU_STATE_USER, | ||
111 | "system": C.CPU_STATE_SYSTEM, | ||
112 | "nice": C.CPU_STATE_NICE, | ||
113 | "idle": C.CPU_STATE_IDLE, | ||
114 | } { | ||
115 | ch <- prometheus.MustNewConstMetric(c.cpu, prometheus.CounterValue, float64(cpu_ticks[v])/ClocksPerSec, "cpu"+strconv.Itoa(i), k) | ||
116 | } | ||
117 | } | ||
118 | return nil | ||
119 | } | ||