diff --git a/collector/meminfo.go b/collector/meminfo.go new file mode 100644 index 00000000..4322470c --- /dev/null +++ b/collector/meminfo.go @@ -0,0 +1,59 @@ +// 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. + +// +build !nomeminfo + +package collector + +import ( + "fmt" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +const ( + memInfoSubsystem = "memory" +) + +type meminfoCollector struct{} + +func init() { + Factories["meminfo"] = NewMeminfoCollector +} + +// NewMeminfoCollector returns a new Collector exposing memory stats. +func NewMeminfoCollector() (Collector, error) { + return &meminfoCollector{}, nil +} + +// Update calls (*meminfoCollector).getMemInfo to get the platform specific +// memory metrics. +func (c *meminfoCollector) Update(ch chan<- prometheus.Metric) (err error) { + memInfo, err := c.getMemInfo() + if err != nil { + return fmt.Errorf("couldn't get meminfo: %s", err) + } + log.Debugf("Set node_mem: %#v", memInfo) + for k, v := range memInfo { + ch <- prometheus.MustNewConstMetric( + prometheus.NewDesc( + prometheus.BuildFQName(Namespace, memInfoSubsystem, k), + fmt.Sprintf("Memory information field %s.", k), + nil, nil, + ), + prometheus.GaugeValue, v, + ) + } + return nil +} diff --git a/collector/meminfo_bsd.go b/collector/meminfo_bsd.go index bcdc3879..be17d7a9 100644 --- a/collector/meminfo_bsd.go +++ b/collector/meminfo_bsd.go @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build freebsd darwin,amd64 dragonfly +// +build freebsd dragonfly // +build !nomeminfo package collector @@ -19,52 +19,33 @@ package collector import ( "fmt" - "github.com/prometheus/client_golang/prometheus" "golang.org/x/sys/unix" ) -const ( - memInfoSubsystem = "memory" -) - -type meminfoCollector struct{} - -func init() { - Factories["meminfo"] = NewMeminfoCollector -} - -// Takes a prometheus registry and returns a new Collector exposing -// Memory stats. -func NewMeminfoCollector() (Collector, error) { - return &meminfoCollector{}, nil -} - -func (c *meminfoCollector) Update(ch chan<- prometheus.Metric) (err error) { - pages := make(map[string]uint32) +func (c *meminfoCollector) getMemInfo() (map[string]float64, error) { + info := make(map[string]float64) size, err := unix.SysctlUint32("vm.stats.vm.v_page_size") if err != nil { - return fmt.Errorf("sysctl(vm.stats.vm.v_page_size) failed: %s", err) + return nil, fmt.Errorf("sysctl(vm.stats.vm.v_page_size) failed: %s", err) } - pages["active"], _ = unix.SysctlUint32("vm.stats.vm.v_active_count") - pages["inactive"], _ = unix.SysctlUint32("vm.stats.vm.v_inactive_count") - pages["wire"], _ = unix.SysctlUint32("vm.stats.vm.v_wire_count") - pages["cache"], _ = unix.SysctlUint32("vm.stats.vm.v_cache_count") - pages["free"], _ = unix.SysctlUint32("vm.stats.vm.v_free_count") - pages["swappgsin"], _ = unix.SysctlUint32("vm.stats.vm.v_swappgsin") - pages["swappgsout"], _ = unix.SysctlUint32("vm.stats.vm.v_swappgsout") - pages["total"], _ = unix.SysctlUint32("vm.stats.vm.v_page_count") - for k, v := range pages { - ch <- prometheus.MustNewConstMetric( - prometheus.NewDesc( - prometheus.BuildFQName(Namespace, memInfoSubsystem, k), - k+" from sysctl()", - nil, nil, - ), - // Convert metrics to kB (same as Linux meminfo). - prometheus.UntypedValue, float64(v)*float64(size), - ) + for key, v := range map[string]string{ + "active": "vm.stats.vm.v_active_count", + "inactive": "vm.stats.vm.v_inactive_count", + "wire": "vm.stats.vm.v_wire_count", + "cache": "vm.stats.vm.v_cache_count", + "free": "vm.stats.vm.v_free_count", + "swappgsin": "vm.stats.vm.v_swappgsin", + "swappgsout": "vm.stats.vm.v_swappgsout", + "total": "vm.stats.vm.v_page_count", + } { + value, err := unix.SysctlUint32(v) + if err != nil { + return nil, err + } + // Convert metrics to kB (same as Linux meminfo). + info[key] = float64(value) * float64(size) } - return err + return info, nil } diff --git a/collector/meminfo_darwin.go b/collector/meminfo_darwin.go new file mode 100644 index 00000000..0aa35ce0 --- /dev/null +++ b/collector/meminfo_darwin.go @@ -0,0 +1,59 @@ +// 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. + +// +build !nomeminfo + +package collector + +// #include +import "C" + +import ( + "encoding/binary" + "fmt" + "syscall" + "unsafe" + + "golang.org/x/sys/unix" +) + +func (c *meminfoCollector) getMemInfo() (map[string]float64, error) { + infoCount := C.mach_msg_type_number_t(C.HOST_VM_INFO_COUNT) + vmstat := C.vm_statistics_data_t{} + ret := C.host_statistics( + C.host_t(C.mach_host_self()), + C.HOST_VM_INFO, + C.host_info_t(unsafe.Pointer(&vmstat)), + &infoCount, + ) + if ret != C.KERN_SUCCESS { + return nil, fmt.Errorf("Couldn't get memory statistics, host_statistics returned %d", ret) + } + totalb, err := unix.Sysctl("hw.memsize") + if err != nil { + return nil, err + } + // Syscall removes terminating NUL which we need to cast to uint64 + total := binary.LittleEndian.Uint64([]byte(totalb + "\x00")) + + ps := C.natural_t(syscall.Getpagesize()) + return map[string]float64{ + "active_bytes_total": float64(ps * vmstat.active_count), + "inactive_bytes_total": float64(ps * vmstat.inactive_count), + "wired_bytes_total": float64(ps * vmstat.wire_count), + "free_bytes_total": float64(ps * vmstat.free_count), + "swapped_in_pages_total": float64(ps * vmstat.pageins), + "swapped_out_pages_total": float64(ps * vmstat.pageouts), + "bytes_total": float64(total), + }, nil +} diff --git a/collector/meminfo_linux.go b/collector/meminfo_linux.go index d1ebe26c..1a8556fd 100644 --- a/collector/meminfo_linux.go +++ b/collector/meminfo_linux.go @@ -23,47 +23,9 @@ import ( "regexp" "strconv" "strings" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/common/log" ) -const ( - memInfoSubsystem = "memory" -) - -type meminfoCollector struct{} - -func init() { - Factories["meminfo"] = NewMeminfoCollector -} - -// Takes a prometheus registry and returns a new Collector exposing -// memory stats. -func NewMeminfoCollector() (Collector, error) { - return &meminfoCollector{}, nil -} - -func (c *meminfoCollector) Update(ch chan<- prometheus.Metric) (err error) { - memInfo, err := getMemInfo() - if err != nil { - return fmt.Errorf("couldn't get meminfo: %s", err) - } - log.Debugf("Set node_mem: %#v", memInfo) - for k, v := range memInfo { - ch <- prometheus.MustNewConstMetric( - prometheus.NewDesc( - prometheus.BuildFQName(Namespace, memInfoSubsystem, k), - fmt.Sprintf("Memory information field %s.", k), - nil, nil, - ), - prometheus.GaugeValue, v, - ) - } - return nil -} - -func getMemInfo() (map[string]float64, error) { +func (c *meminfoCollector) getMemInfo() (map[string]float64, error) { file, err := os.Open(procFilePath("meminfo")) if err != nil { return nil, err