| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | // Copyright 2017 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.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-03 04:35:24 -07:00
										 |  |  | //go:build (freebsd || dragonfly || openbsd || netbsd || darwin) && cgo
 | 
					
						
							| 
									
										
										
										
											2018-04-14 21:42:02 -07:00
										 |  |  | // +build freebsd dragonfly openbsd netbsd darwin
 | 
					
						
							| 
									
										
										
										
											2020-06-12 01:26:30 -07:00
										 |  |  | // +build cgo
 | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package collector | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-04-11 03:04:14 -07:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2018-02-01 09:43:40 -08:00
										 |  |  | 	"unsafe" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							|  |  |  | 	"golang.org/x/sys/unix" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-11 03:04:14 -07:00
										 |  |  | // #include <sys/types.h>
 | 
					
						
							|  |  |  | import "C" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | type bsdSysctlType uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // BSD-specific sysctl value types.  There is an impedience mismatch between
 | 
					
						
							|  |  |  | // native C types, e.g. int vs long, and the golang unix.Sysctl variables
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	// Default to uint32.
 | 
					
						
							|  |  |  | 	bsdSysctlTypeUint32 bsdSysctlType = iota | 
					
						
							|  |  |  | 	bsdSysctlTypeUint64 | 
					
						
							| 
									
										
										
										
											2017-10-25 11:55:22 -07:00
										 |  |  | 	bsdSysctlTypeCLong | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-25 11:55:22 -07:00
										 |  |  | // Contains all the info needed to map a single bsd-sysctl to a prometheus
 | 
					
						
							|  |  |  | // value.
 | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | type bsdSysctl struct { | 
					
						
							|  |  |  | 	// Prometheus name
 | 
					
						
							|  |  |  | 	name string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Simple prometheus description
 | 
					
						
							|  |  |  | 	description string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Prometheus type
 | 
					
						
							|  |  |  | 	valueType prometheus.ValueType | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Sysctl name
 | 
					
						
							|  |  |  | 	mib string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Sysctl data-type
 | 
					
						
							|  |  |  | 	dataType bsdSysctlType | 
					
						
							| 
									
										
										
										
											2017-03-07 17:54:28 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Post-retrieval conversion hooks
 | 
					
						
							| 
									
										
										
										
											2017-04-11 03:04:14 -07:00
										 |  |  | 	conversion func(float64) float64 | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (b bsdSysctl) Value() (float64, error) { | 
					
						
							|  |  |  | 	var tmp32 uint32 | 
					
						
							|  |  |  | 	var tmp64 uint64 | 
					
						
							| 
									
										
										
										
											2017-04-11 03:04:14 -07:00
										 |  |  | 	var tmpf64 float64 | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | 	var err error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch b.dataType { | 
					
						
							|  |  |  | 	case bsdSysctlTypeUint32: | 
					
						
							|  |  |  | 		tmp32, err = unix.SysctlUint32(b.mib) | 
					
						
							| 
									
										
										
										
											2017-04-11 03:04:14 -07:00
										 |  |  | 		tmpf64 = float64(tmp32) | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | 	case bsdSysctlTypeUint64: | 
					
						
							|  |  |  | 		tmp64, err = unix.SysctlUint64(b.mib) | 
					
						
							| 
									
										
										
										
											2017-04-11 03:04:14 -07:00
										 |  |  | 		tmpf64 = float64(tmp64) | 
					
						
							| 
									
										
										
										
											2017-10-25 11:55:22 -07:00
										 |  |  | 	case bsdSysctlTypeCLong: | 
					
						
							|  |  |  | 		tmpf64, err = b.getCLong() | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-11 03:04:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return 0, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-07 17:54:28 -08:00
										 |  |  | 	if b.conversion != nil { | 
					
						
							| 
									
										
										
										
											2017-04-11 03:04:14 -07:00
										 |  |  | 		return b.conversion(tmpf64), nil | 
					
						
							| 
									
										
										
										
											2017-03-07 17:54:28 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-11 03:04:14 -07:00
										 |  |  | 	return tmpf64, nil | 
					
						
							| 
									
										
										
										
											2017-02-28 13:23:10 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-10-25 11:55:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (b bsdSysctl) getCLong() (float64, error) { | 
					
						
							|  |  |  | 	raw, err := unix.SysctlRaw(b.mib) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return 0, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(raw) == C.sizeof_long { | 
					
						
							|  |  |  | 		return float64(*(*C.long)(unsafe.Pointer(&raw[0]))), nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(raw) == C.sizeof_int { | 
					
						
							|  |  |  | 		// This is valid for at least vfs.bufspace, and the default
 | 
					
						
							|  |  |  | 		// long handler - which can clamp longs to 32-bits:
 | 
					
						
							|  |  |  | 		//   https://github.com/freebsd/freebsd/blob/releng/10.3/sys/kern/vfs_bio.c#L338
 | 
					
						
							|  |  |  | 		//   https://github.com/freebsd/freebsd/blob/releng/10.3/sys/kern/kern_sysctl.c#L1062
 | 
					
						
							|  |  |  | 		return float64(*(*C.int)(unsafe.Pointer(&raw[0]))), nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0, fmt.Errorf( | 
					
						
							|  |  |  | 		"length of bytes received from sysctl (%d) does not match expected bytes (long: %d), (int: %d)", | 
					
						
							|  |  |  | 		len(raw), | 
					
						
							|  |  |  | 		C.sizeof_long, | 
					
						
							|  |  |  | 		C.sizeof_int, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |