| 
									
										
										
										
											2022-07-27 05:11:01 -07:00
										 |  |  | // Copyright 2018 The Prometheus Authors
 | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | // 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.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-15 05:24:50 -08:00
										 |  |  | //go:build !nocpu
 | 
					
						
							|  |  |  | // +build !nocpu
 | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package collector | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	"log/slog" | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"unsafe" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							|  |  |  | 	"golang.org/x/sys/unix" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-15 05:24:50 -08:00
										 |  |  | const ( | 
					
						
							|  |  |  | 	CP_USER = iota | 
					
						
							|  |  |  | 	CP_NICE | 
					
						
							|  |  |  | 	CP_SYS | 
					
						
							|  |  |  | 	CP_SPIN | 
					
						
							|  |  |  | 	CP_INTR | 
					
						
							|  |  |  | 	CP_IDLE | 
					
						
							|  |  |  | 	CPUSTATES | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	CP_USER_O63 = iota | 
					
						
							|  |  |  | 	CP_NICE_O63 | 
					
						
							|  |  |  | 	CP_SYS_O63 | 
					
						
							|  |  |  | 	CP_INTR_O63 | 
					
						
							|  |  |  | 	CP_IDLE_O63 | 
					
						
							|  |  |  | 	CPUSTATES_O63 | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | type cpuCollector struct { | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | 	cpu    typedDesc | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	logger *slog.Logger | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2019-02-04 22:46:50 -08:00
										 |  |  | 	registerCollector("cpu", defaultEnabled, NewCPUCollector) | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func NewCPUCollector(logger *slog.Logger) (Collector, error) { | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 	return &cpuCollector{ | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | 		cpu:    typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue}, | 
					
						
							|  |  |  | 		logger: logger, | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *cpuCollector) Update(ch chan<- prometheus.Metric) (err error) { | 
					
						
							|  |  |  | 	clockb, err := unix.SysctlRaw("kern.clockrate") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-05-11 01:39:51 -07:00
										 |  |  | 	clock := *(*unix.Clockinfo)(unsafe.Pointer(&clockb[0])) | 
					
						
							|  |  |  | 	hz := float64(clock.Stathz) | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ncpus, err := unix.SysctlUint32("hw.ncpu") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-15 05:24:50 -08:00
										 |  |  | 	var cpTime [][CPUSTATES]uint64 | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 	for i := 0; i < int(ncpus); i++ { | 
					
						
							| 
									
										
										
										
											2019-02-04 22:46:50 -08:00
										 |  |  | 		cpb, err := unix.SysctlRaw("kern.cp_time2", i) | 
					
						
							| 
									
										
										
										
											2018-10-02 01:21:30 -07:00
										 |  |  | 		if err != nil && err != unix.ENODEV { | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-10-02 01:21:30 -07:00
										 |  |  | 		if err != unix.ENODEV { | 
					
						
							| 
									
										
										
										
											2021-02-15 05:24:50 -08:00
										 |  |  | 			var times [CPUSTATES]uint64 | 
					
						
							|  |  |  | 			for n := 0; n < len(cpb); n += 8 { | 
					
						
							|  |  |  | 				times[n/8] = *(*uint64)(unsafe.Pointer(&cpb[n])) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if len(cpb)/8 == CPUSTATES_O63 { | 
					
						
							|  |  |  | 				copy(times[CP_INTR:], times[CP_INTR_O63:]) | 
					
						
							|  |  |  | 				times[CP_SPIN] = 0 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			cpTime = append(cpTime, times) | 
					
						
							| 
									
										
										
										
											2018-10-02 01:21:30 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-04 22:46:50 -08:00
										 |  |  | 	for cpu, time := range cpTime { | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 		lcpu := strconv.Itoa(cpu) | 
					
						
							| 
									
										
										
										
											2021-02-15 05:24:50 -08:00
										 |  |  | 		ch <- c.cpu.mustNewConstMetric(float64(time[CP_USER])/hz, lcpu, "user") | 
					
						
							|  |  |  | 		ch <- c.cpu.mustNewConstMetric(float64(time[CP_NICE])/hz, lcpu, "nice") | 
					
						
							|  |  |  | 		ch <- c.cpu.mustNewConstMetric(float64(time[CP_SYS])/hz, lcpu, "system") | 
					
						
							|  |  |  | 		ch <- c.cpu.mustNewConstMetric(float64(time[CP_SPIN])/hz, lcpu, "spin") | 
					
						
							|  |  |  | 		ch <- c.cpu.mustNewConstMetric(float64(time[CP_INTR])/hz, lcpu, "interrupt") | 
					
						
							|  |  |  | 		ch <- c.cpu.mustNewConstMetric(float64(time[CP_IDLE])/hz, lcpu, "idle") | 
					
						
							| 
									
										
										
										
											2018-02-01 09:33:49 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } |