| 
									
										
										
										
											2015-11-01 22:55:46 -08:00
										 |  |  | // 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.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 06:29:03 -07:00
										 |  |  | //go:build !nointerrupts && !amd64
 | 
					
						
							|  |  |  | // +build !nointerrupts,!amd64
 | 
					
						
							| 
									
										
										
										
											2015-11-01 22:55:46 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 ( | 
					
						
							| 
									
										
										
										
											2018-03-08 06:04:49 -08:00
										 |  |  | 	interruptLabelNames = []string{"cpu", "type", "devices"} | 
					
						
							| 
									
										
										
										
											2015-11-01 22:55:46 -08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 06:21:31 -08:00
										 |  |  | func (c *interruptsCollector) Update(ch chan<- prometheus.Metric) error { | 
					
						
							| 
									
										
										
										
											2015-11-01 22:55:46 -08:00
										 |  |  | 	interrupts, err := getInterrupts() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-15 13:27:14 -07:00
										 |  |  | 		return fmt.Errorf("couldn't get interrupts: %w", err) | 
					
						
							| 
									
										
										
										
											2015-11-01 22:55:46 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	for dev, interrupt := range interrupts { | 
					
						
							|  |  |  | 		for cpuNo, value := range interrupt.values { | 
					
						
							| 
									
										
										
										
											2024-07-14 07:17:20 -07:00
										 |  |  | 			interruptType := fmt.Sprintf("%d", interrupt.vector) | 
					
						
							|  |  |  | 			filterName := interruptType + ";" + dev | 
					
						
							|  |  |  | 			if c.nameFilter.ignored(filterName) { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 				c.logger.Debug("ignoring interrupt name", "filter_name", filterName) | 
					
						
							| 
									
										
										
										
											2024-07-14 07:17:20 -07:00
										 |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !c.includeZeros && value == 0.0 { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 				c.logger.Debug("ignoring interrupt with zero value", "filter_name", filterName, "cpu", cpuNo) | 
					
						
							| 
									
										
										
										
											2024-07-14 07:17:20 -07:00
										 |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-12-28 06:21:31 -08:00
										 |  |  | 			ch <- c.desc.mustNewConstMetric( | 
					
						
							|  |  |  | 				value, | 
					
						
							|  |  |  | 				strconv.Itoa(cpuNo), | 
					
						
							| 
									
										
										
										
											2024-07-14 07:17:20 -07:00
										 |  |  | 				interruptType, | 
					
						
							| 
									
										
										
										
											2016-12-28 06:21:31 -08:00
										 |  |  | 				dev, | 
					
						
							|  |  |  | 			) | 
					
						
							| 
									
										
										
										
											2015-11-01 22:55:46 -08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-28 06:21:31 -08:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-11-01 22:55:46 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type interrupt struct { | 
					
						
							|  |  |  | 	vector int | 
					
						
							|  |  |  | 	device string | 
					
						
							|  |  |  | 	values []float64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func getInterrupts() (map[string]interrupt, error) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2015-12-18 06:08:52 -08:00
										 |  |  | 		cintr      C.struct_intr | 
					
						
							| 
									
										
										
										
											2015-11-01 22:55:46 -08:00
										 |  |  | 		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 | 
					
						
							|  |  |  | } |