diff --git a/.promu.yml b/.promu.yml index 7cdecea8..8797d4b9 100644 --- a/.promu.yml +++ b/.promu.yml @@ -31,3 +31,4 @@ crossbuild: - linux/ppc64 - linux/ppc64le - linux/s390x + - openbsd/amd64 diff --git a/CHANGELOG.md b/CHANGELOG.md index 27f8eefc..9eb8fd13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * [FEATURE] * [ENHANCEMENT] Include TCP OutRsts in netstat metrics * [ENHANCEMENT] Added XFS inode operations to XFS metrics +* [ENHANCEMENT] Remove CGO dependencies for OpenBSD amd64 * [BUGFIX] ## 1.0.1 / 2020-06-15 diff --git a/Makefile b/Makefile index 504ed3d0..d991d35c 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,16 @@ else PROMU_CONF ?= .promu-cgo.yml endif else - PROMU_CONF ?= .promu-cgo.yml + # Do not use CGO for openbsd/amd64 builds + ifeq ($(GOOS), openbsd) + ifeq ($(GOARCH), amd64) + PROMU_CONF ?= .promu.yml + else + PROMU_CONF ?= .promu-cgo.yml + endif + else + PROMU_CONF ?= .promu-cgo.yml + endif endif endif diff --git a/README.md b/README.md index 17a4b1fd..08f2bb0f 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ bcache | Exposes bcache statistics from `/sys/fs/bcache/`. | Linux bonding | Exposes the number of configured and active slaves of Linux bonding interfaces. | Linux boottime | Exposes system boot time derived from the `kern.boottime` sysctl. | Darwin, Dragonfly, FreeBSD, NetBSD, OpenBSD, Solaris conntrack | Shows conntrack statistics (does nothing if no `/proc/sys/net/netfilter/` present). | Linux -cpu | Exposes CPU statistics | Darwin, Dragonfly, FreeBSD, Linux, Solaris +cpu | Exposes CPU statistics | Darwin, Dragonfly, FreeBSD, Linux, Solaris, OpenBSD cpufreq | Exposes CPU frequency statistics | Linux, Solaris diskstats | Exposes disk I/O statistics. | Darwin, Linux, OpenBSD edac | Exposes error detection and correction statistics. | Linux diff --git a/collector/boot_time_bsd.go b/collector/boot_time_bsd.go index 74d4bcee..8dcc1e02 100644 --- a/collector/boot_time_bsd.go +++ b/collector/boot_time_bsd.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build freebsd dragonfly openbsd netbsd darwin +// +build freebsd dragonfly openbsd,!amd64 netbsd darwin // +build !noboottime package collector diff --git a/collector/boot_time_openbsd_amd64.go b/collector/boot_time_openbsd_amd64.go new file mode 100644 index 00000000..957cecd6 --- /dev/null +++ b/collector/boot_time_openbsd_amd64.go @@ -0,0 +1,61 @@ +// Copyright 2020 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. + +// +build !noboottime + +package collector + +import ( + "github.com/go-kit/kit/log" + "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sys/unix" + "unsafe" +) + +type bootTimeCollector struct { + name, description string + logger log.Logger +} + +func init() { + registerCollector("boottime", defaultEnabled, newBootTimeCollector) +} + +// newBootTimeCollector returns a new Collector exposing system boot time on BSD systems. +func newBootTimeCollector(logger log.Logger) (Collector, error) { + return &bootTimeCollector{ + name: "boot_time_seconds", + description: "Unix time of last boot, including microseconds.", + logger: logger, + }, nil +} + +// Update pushes boot time onto ch +func (c *bootTimeCollector) Update(ch chan<- prometheus.Metric) error { + raw, err := unix.SysctlRaw("kern.boottime") + if err != nil { + return err + } + + tv := *(*unix.Timeval)(unsafe.Pointer(&raw[0])) + v := (float64(tv.Sec) + (float64(tv.Usec) / float64(1000*1000))) + + ch <- prometheus.MustNewConstMetric( + prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", c.name), + c.description, + nil, nil, + ), prometheus.GaugeValue, v) + + return nil +} diff --git a/collector/cpu_openbsd.go b/collector/cpu_openbsd.go index b7d76887..7d405103 100644 --- a/collector/cpu_openbsd.go +++ b/collector/cpu_openbsd.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build openbsd,!amd64 // +build !nocpu package collector diff --git a/collector/cpu_openbsd_amd64.go b/collector/cpu_openbsd_amd64.go new file mode 100644 index 00000000..293cc41e --- /dev/null +++ b/collector/cpu_openbsd_amd64.go @@ -0,0 +1,95 @@ +// Copyright 2020 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. + +// +build !nocpu + +package collector + +import ( + "strconv" + "unsafe" + + "github.com/go-kit/kit/log" + "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sys/unix" +) + +type clockinfo struct { + hz int32 + tick int32 + tickadj int32 + stathz int32 + profhz int32 +} + +const ( + CP_USER = 0 + CP_NICE = 1 + CP_SYS = 2 + CP_SPIN = 3 + CP_INTR = 4 + CP_IDLE = 5 + CPUSTATES = 6 +) + +type cpuCollector struct { + cpu typedDesc + logger log.Logger +} + +func init() { + registerCollector("cpu", defaultEnabled, NewCPUCollector) +} + +func NewCPUCollector(logger log.Logger) (Collector, error) { + return &cpuCollector{ + cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue}, + logger: logger, + }, nil +} + +func (c *cpuCollector) Update(ch chan<- prometheus.Metric) (err error) { + clockb, err := unix.SysctlRaw("kern.clockrate") + if err != nil { + return err + } + clock := *(*clockinfo)(unsafe.Pointer(&clockb[0])) + hz := float64(clock.stathz) + + ncpus, err := unix.SysctlUint32("hw.ncpu") + if err != nil { + return err + } + + var cpTime [][CPUSTATES]int64 + for i := 0; i < int(ncpus); i++ { + cpb, err := unix.SysctlRaw("kern.cp_time2", i) + if err != nil && err != unix.ENODEV { + return err + } + if err != unix.ENODEV { + cpTime = append(cpTime, *(*[CPUSTATES]int64)(unsafe.Pointer(&cpb[0]))) + } + } + + for cpu, time := range cpTime { + lcpu := strconv.Itoa(cpu) + 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") + } + return err +} diff --git a/collector/diskstats_openbsd.go b/collector/diskstats_openbsd.go index 3385f377..6318bd79 100644 --- a/collector/diskstats_openbsd.go +++ b/collector/diskstats_openbsd.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build openbsd,!amd64 // +build !nodiskstats package collector diff --git a/collector/diskstats_openbsd_amd64.go b/collector/diskstats_openbsd_amd64.go new file mode 100644 index 00000000..602fae6c --- /dev/null +++ b/collector/diskstats_openbsd_amd64.go @@ -0,0 +1,89 @@ +// Copyright 2020 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. + +// +build !nodiskstats + +package collector + +import ( + "unsafe" + + "github.com/go-kit/kit/log" + "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sys/unix" +) + +const ( + DS_DISKNAMELEN = 16 +) + +type DiskStats struct { + Name [DS_DISKNAMELEN]int8 + Busy int32 + Rxfer uint64 + Wxfer uint64 + Seek uint64 + Rbytes uint64 + Wbytes uint64 + Attachtime unix.Timeval + Timestamp unix.Timeval + Time unix.Timeval +} + +type diskstatsCollector struct { + rxfer typedDesc + rbytes typedDesc + wxfer typedDesc + wbytes typedDesc + time typedDesc + logger log.Logger +} + +func init() { + registerCollector("diskstats", defaultEnabled, NewDiskstatsCollector) +} + +// NewDiskstatsCollector returns a new Collector exposing disk device stats. +func NewDiskstatsCollector(logger log.Logger) (Collector, error) { + return &diskstatsCollector{ + rxfer: typedDesc{readsCompletedDesc, prometheus.CounterValue}, + rbytes: typedDesc{readBytesDesc, prometheus.CounterValue}, + wxfer: typedDesc{writesCompletedDesc, prometheus.CounterValue}, + wbytes: typedDesc{writtenBytesDesc, prometheus.CounterValue}, + time: typedDesc{ioTimeSecondsDesc, prometheus.CounterValue}, + logger: logger, + }, nil +} + +func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) (err error) { + diskstatsb, err := unix.SysctlRaw("hw.diskstats") + if err != nil { + return err + } + + ndisks := len(diskstatsb) / int(unsafe.Sizeof(DiskStats{})) + diskstats := *(*[]DiskStats)(unsafe.Pointer(&diskstatsb)) + + for i := 0; i < ndisks; i++ { + dn := *(*[DS_DISKNAMELEN]int8)(unsafe.Pointer(&diskstats[i].Name[0])) + diskname := int8ToString(dn[:]) + + ch <- c.rxfer.mustNewConstMetric(float64(diskstats[i].Rxfer), diskname) + ch <- c.rbytes.mustNewConstMetric(float64(diskstats[i].Rbytes), diskname) + ch <- c.wxfer.mustNewConstMetric(float64(diskstats[i].Wxfer), diskname) + ch <- c.wbytes.mustNewConstMetric(float64(diskstats[i].Wbytes), diskname) + time := float64(diskstats[i].Time.Sec) + float64(diskstats[i].Time.Usec)/1000000 + ch <- c.time.mustNewConstMetric(time, diskname) + } + return nil +} diff --git a/collector/filesystem_bsd.go b/collector/filesystem_bsd.go index 7b309040..79cd419d 100644 --- a/collector/filesystem_bsd.go +++ b/collector/filesystem_bsd.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build openbsd darwin,amd64 dragonfly +// +build openbsd,!amd64 darwin,amd64 dragonfly // +build !nofilesystem package collector diff --git a/collector/filesystem_openbsd_amd64.go b/collector/filesystem_openbsd_amd64.go new file mode 100644 index 00000000..8c74a7f6 --- /dev/null +++ b/collector/filesystem_openbsd_amd64.go @@ -0,0 +1,77 @@ +// Copyright 2020 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. + +// +build openbsd darwin,amd64 dragonfly +// +build !nofilesystem + +package collector + +import ( + "github.com/go-kit/kit/log/level" + "golang.org/x/sys/unix" +) + +const ( + defIgnoredMountPoints = "^/(dev)($|/)" + defIgnoredFSTypes = "^devfs$" +) + +// Expose filesystem fullness. +func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) { + var mnt []unix.Statfs_t + size, err := unix.Getfsstat(mnt, unix.MNT_NOWAIT) + if err != nil { + return nil, err + } + mnt = make([]unix.Statfs_t, size) + _, err = unix.Getfsstat(mnt, unix.MNT_NOWAIT) + if err != nil { + return nil, err + } + + stats = []filesystemStats{} + for _, v := range mnt { + mountpoint := int8ToString(v.F_mntonname[:]) + if c.ignoredMountPointsPattern.MatchString(mountpoint) { + level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", mountpoint) + continue + } + + device := int8ToString(v.F_mntfromname[:]) + fstype := int8ToString(v.F_fstypename[:]) + if c.ignoredFSTypesPattern.MatchString(fstype) { + level.Debug(c.logger).Log("msg", "Ignoring fs type", "type", fstype) + continue + } + + var ro float64 + if (v.F_flags & unix.MNT_RDONLY) != 0 { + ro = 1 + } + + stats = append(stats, filesystemStats{ + labels: filesystemLabels{ + device: device, + mountPoint: mountpoint, + fsType: fstype, + }, + size: float64(v.F_blocks) * float64(v.F_bsize), + free: float64(v.F_bfree) * float64(v.F_bsize), + avail: float64(v.F_bavail) * float64(v.F_bsize), + files: float64(v.F_files), + filesFree: float64(v.F_ffree), + ro: ro, + }) + } + return stats, nil +} diff --git a/collector/interrupts_openbsd_amd64.go b/collector/interrupts_openbsd_amd64.go new file mode 100644 index 00000000..2d1847e2 --- /dev/null +++ b/collector/interrupts_openbsd_amd64.go @@ -0,0 +1,113 @@ +// Copyright 2020 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. + +// +build !nointerrupts + +package collector + +import ( + "fmt" + "strconv" + "unsafe" + + "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sys/unix" +) + +const ( + KERN_INTRCNT = 63 + KERN_INTRCNT_NUM = 1 + KERN_INTRCNT_CNT = 2 + KERN_INTRCNT_NAME = 3 + KERN_INTRCNT_VECTOR = 4 +) + +func nintr() _C_int { + mib := [3]_C_int{unix.CTL_KERN, KERN_INTRCNT, KERN_INTRCNT_NUM} + buf, err := sysctl(mib[:]) + if err != nil { + return 0 + } + return *(*_C_int)(unsafe.Pointer(&buf[0])) +} + +func intr(idx _C_int) (itr interrupt, err error) { + mib := [4]_C_int{unix.CTL_KERN, KERN_INTRCNT, KERN_INTRCNT_NAME, idx} + buf, err := sysctl(mib[:]) + if err != nil { + return + } + dev := *(*[128]byte)(unsafe.Pointer(&buf[0])) + itr.device = string(dev[:]) + + mib[2] = KERN_INTRCNT_VECTOR + buf, err = sysctl(mib[:]) + if err != nil { + return + } + itr.vector = *(*int)(unsafe.Pointer(&buf[0])) + + mib[2] = KERN_INTRCNT_CNT + buf, err = sysctl(mib[:]) + if err != nil { + return + } + count := *(*uint64)(unsafe.Pointer(&buf[0])) + itr.values = []float64{float64(count)} + return +} + +var ( + interruptLabelNames = []string{"cpu", "type", "devices"} +) + +func (c *interruptsCollector) Update(ch chan<- prometheus.Metric) error { + interrupts, err := getInterrupts() + if err != nil { + return fmt.Errorf("couldn't get interrupts: %s", err) + } + for dev, interrupt := range interrupts { + for cpuNo, value := range interrupt.values { + ch <- c.desc.mustNewConstMetric( + value, + strconv.Itoa(cpuNo), + fmt.Sprintf("%d", interrupt.vector), + dev, + ) + } + } + return nil +} + +type interrupt struct { + vector int + device string + values []float64 +} + +func getInterrupts() (map[string]interrupt, error) { + var interrupts = map[string]interrupt{} + + n := nintr() + + for i := _C_int(0); i < n; i++ { + itr, err := intr(i) + if err != nil { + return nil, err + } + + interrupts[itr.device] = itr + } + + return interrupts, nil +} diff --git a/collector/meminfo_openbsd.go b/collector/meminfo_openbsd.go index 81102d59..d9cf940e 100644 --- a/collector/meminfo_openbsd.go +++ b/collector/meminfo_openbsd.go @@ -11,7 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build openbsd // +build !nomeminfo package collector diff --git a/collector/meminfo_openbsd_amd64.go b/collector/meminfo_openbsd_amd64.go new file mode 100644 index 00000000..418e3d75 --- /dev/null +++ b/collector/meminfo_openbsd_amd64.go @@ -0,0 +1,45 @@ +// Copyright 2020 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. + +// +build !nomeminfo + +package collector + +import ( + "golang.org/x/sys/unix" + "unsafe" +) + +func (c *meminfoCollector) getMemInfo() (map[string]float64, error) { + uvmexpb, err := unix.SysctlRaw("vm.uvmexp") + if err != nil { + return nil, err + } + uvmexp := *(*unix.Uvmexp)(unsafe.Pointer(&uvmexpb[0])) + + ps := float64(uvmexp.Pagesize) + + // see uvm(9) + return map[string]float64{ + "active_bytes": ps * float64(uvmexp.Active), + "cache_bytes": ps * float64(uvmexp.Vnodepages), + "free_bytes": ps * float64(uvmexp.Free), + "inactive_bytes": ps * float64(uvmexp.Inactive), + "size_bytes": ps * float64(uvmexp.Npages), + "swap_size_bytes": ps * float64(uvmexp.Swpages), + "swap_used_bytes": ps * float64(uvmexp.Swpginuse), + "swapped_in_pages_bytes_total": ps * float64(uvmexp.Pgswapin), + "swapped_out_pages_bytes_total": ps * float64(uvmexp.Pgswapout), + "wired_bytes": ps * float64(uvmexp.Wired), + }, nil +} diff --git a/collector/netdev_openbsd_amd64.go b/collector/netdev_openbsd_amd64.go new file mode 100644 index 00000000..37227b49 --- /dev/null +++ b/collector/netdev_openbsd_amd64.go @@ -0,0 +1,79 @@ +// Copyright 2020 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. + +// +build !nonetdev + +package collector + +import ( + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "strconv" + + "golang.org/x/sys/unix" + "regexp" + "unsafe" +) + +func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) { + netDev := map[string]map[string]string{} + + mib := [6]_C_int{unix.CTL_NET, unix.AF_ROUTE, 0, 0, unix.NET_RT_IFLIST, 0} + buf, err := sysctl(mib[:]) + if err != nil { + return nil, err + } + n := uintptr(len(buf)) + index := uintptr(unsafe.Pointer(&buf[0])) + next := uintptr(0) + + var rtm *unix.RtMsghdr + + for next = index; next < (index + n); next += uintptr(rtm.Msglen) { + rtm = (*unix.RtMsghdr)(unsafe.Pointer(next)) + if rtm.Version != unix.RTM_VERSION || rtm.Type != unix.RTM_IFINFO { + continue + } + ifm := (*unix.IfMsghdr)(unsafe.Pointer(next)) + if ifm.Addrs&unix.RTA_IFP == 0 { + continue + } + dl := (*unix.RawSockaddrDatalink)(unsafe.Pointer(next + uintptr(rtm.Hdrlen))) + if dl.Family != unix.AF_LINK { + continue + } + data := ifm.Data + dev := int8ToString(dl.Data[:dl.Nlen]) + if ignore != nil && ignore.MatchString(dev) { + level.Debug(logger).Log("msg", "Ignoring device", "device", dev) + continue + } + if accept != nil && !accept.MatchString(dev) { + level.Debug(logger).Log("msg", "Ignoring device", "device", dev) + continue + } + + devStats := map[string]string{} + devStats["receive_packets"] = strconv.Itoa(int(data.Ipackets)) + devStats["transmit_packets"] = strconv.Itoa(int(data.Opackets)) + devStats["receive_errs"] = strconv.Itoa(int(data.Ierrors)) + devStats["transmit_errs"] = strconv.Itoa(int(data.Oerrors)) + devStats["receive_bytes"] = strconv.Itoa(int(data.Ibytes)) + devStats["transmit_bytes"] = strconv.Itoa(int(data.Obytes)) + devStats["receive_multicast"] = strconv.Itoa(int(data.Imcasts)) + devStats["transmit_multicast"] = strconv.Itoa(int(data.Omcasts)) + devStats["receive_drop"] = strconv.Itoa(int(data.Iqdrops)) + netDev[dev] = devStats + } + return netDev, nil +} diff --git a/collector/sysctl_openbsd_amd64.go b/collector/sysctl_openbsd_amd64.go new file mode 100644 index 00000000..56ae7346 --- /dev/null +++ b/collector/sysctl_openbsd_amd64.go @@ -0,0 +1,82 @@ +// Copyright 2020 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. + +package collector + +import ( + "golang.org/x/sys/unix" + "syscall" + "unsafe" +) + +func int8ToString(a []int8) string { + b := make([]byte, len(a)) + for i, v := range a { + b[i] = byte(v) + } + return string(b) +} + +// unix._C_int +type _C_int int32 + +var _zero uintptr + +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case unix.EAGAIN: + return syscall.EAGAIN + case unix.EINVAL: + return syscall.EINVAL + case unix.ENOENT: + return syscall.ENOENT + } + return e +} + +func _sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + for { + _, _, e1 := unix.Syscall6(unix.SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + if err != unix.EINTR { + return + } + } + return +} + +func sysctl(mib []_C_int) ([]byte, error) { + n := uintptr(0) + if err := _sysctl(mib, nil, &n, nil, 0); err != nil { + return nil, err + } + if n == 0 { + return nil, nil + } + + buf := make([]byte, n) + if err := _sysctl(mib, &buf[0], &n, nil, 0); err != nil { + return nil, err + } + return buf[:n], nil +}