| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | // Copyright 2016 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.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Based on gopsutil/cpu/cpu_darwin_cgo.go @ ae251eb which is licensed under
 | 
					
						
							|  |  |  | // BSD. See https://github.com/shirou/gopsutil/blob/master/LICENSE for details.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-03 04:35:24 -07:00
										 |  |  | //go:build !nocpu
 | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | // +build !nocpu
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package collector | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"encoding/binary" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	"log/slog" | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"unsafe" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  | #cgo LDFLAGS: | 
					
						
							|  |  |  | #include <stdlib.h> | 
					
						
							| 
									
										
										
										
											2018-03-07 02:56:57 -08:00
										 |  |  | #include <limits.h> | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | #include <sys/sysctl.h> | 
					
						
							|  |  |  | #include <sys/mount.h> | 
					
						
							|  |  |  | #include <mach/mach_init.h> | 
					
						
							|  |  |  | #include <mach/mach_host.h> | 
					
						
							|  |  |  | #include <mach/host_info.h> | 
					
						
							| 
									
										
										
										
											2021-11-09 08:52:49 -08:00
										 |  |  | #include <TargetConditionals.h> | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | #if TARGET_OS_MAC | 
					
						
							|  |  |  | #include <libproc.h> | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | #include <mach/processor_info.h> | 
					
						
							|  |  |  | #include <mach/vm_map.h> | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | import "C" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-14 04:29:26 -07:00
										 |  |  | // ClocksPerSec default value. from time.h
 | 
					
						
							| 
									
										
										
										
											2018-03-07 02:56:57 -08:00
										 |  |  | const ClocksPerSec = float64(C.CLK_TCK) | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | type statCollector struct { | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | 	cpu    *prometheus.Desc | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	logger *slog.Logger | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 	registerCollector("cpu", defaultEnabled, NewCPUCollector) | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-14 04:29:26 -07:00
										 |  |  | // NewCPUCollector returns a new Collector exposing CPU stats.
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func NewCPUCollector(logger *slog.Logger) (Collector, error) { | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | 	return &statCollector{ | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | 		cpu:    nodeCPUSecondsDesc, | 
					
						
							|  |  |  | 		logger: logger, | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *statCollector) Update(ch chan<- prometheus.Metric) error { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		count   C.mach_msg_type_number_t | 
					
						
							|  |  |  | 		cpuload *C.processor_cpu_load_info_data_t | 
					
						
							|  |  |  | 		ncpu    C.natural_t | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	status := C.host_processor_info(C.host_t(C.mach_host_self()), | 
					
						
							|  |  |  | 		C.PROCESSOR_CPU_LOAD_INFO, | 
					
						
							|  |  |  | 		&ncpu, | 
					
						
							|  |  |  | 		(*C.processor_info_array_t)(unsafe.Pointer(&cpuload)), | 
					
						
							|  |  |  | 		&count) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if status != C.KERN_SUCCESS { | 
					
						
							|  |  |  | 		return fmt.Errorf("host_processor_info error=%d", status) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// jump through some cgo casting hoops and ensure we properly free
 | 
					
						
							|  |  |  | 	// the memory that cpuload points to
 | 
					
						
							|  |  |  | 	target := C.vm_map_t(C.mach_task_self_) | 
					
						
							|  |  |  | 	address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload))) | 
					
						
							|  |  |  | 	defer C.vm_deallocate(target, address, C.vm_size_t(ncpu)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// the body of struct processor_cpu_load_info
 | 
					
						
							|  |  |  | 	// aka processor_cpu_load_info_data_t
 | 
					
						
							| 
									
										
										
										
											2017-05-14 04:30:05 -07:00
										 |  |  | 	var cpuTicks [C.CPU_STATE_MAX]uint32 | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// copy the cpuload array to a []byte buffer
 | 
					
						
							|  |  |  | 	// where we can binary.Read the data
 | 
					
						
							| 
									
										
										
										
											2017-05-14 04:30:05 -07:00
										 |  |  | 	size := int(ncpu) * binary.Size(cpuTicks) | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | 	buf := (*[1 << 30]byte)(unsafe.Pointer(cpuload))[:size:size] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bbuf := bytes.NewBuffer(buf) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < int(ncpu); i++ { | 
					
						
							| 
									
										
										
										
											2017-05-14 04:30:05 -07:00
										 |  |  | 		err := binary.Read(bbuf, binary.LittleEndian, &cpuTicks) | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for k, v := range map[string]int{ | 
					
						
							|  |  |  | 			"user":   C.CPU_STATE_USER, | 
					
						
							|  |  |  | 			"system": C.CPU_STATE_SYSTEM, | 
					
						
							|  |  |  | 			"nice":   C.CPU_STATE_NICE, | 
					
						
							|  |  |  | 			"idle":   C.CPU_STATE_IDLE, | 
					
						
							|  |  |  | 		} { | 
					
						
							| 
									
										
										
										
											2018-02-01 09:42:20 -08:00
										 |  |  | 			ch <- prometheus.MustNewConstMetric(c.cpu, prometheus.CounterValue, float64(cpuTicks[v])/ClocksPerSec, strconv.Itoa(i), k) | 
					
						
							| 
									
										
										
										
											2016-12-28 09:26:27 -08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |