diff --git a/metric/memory/memory.go b/metric/memory/memory.go deleted file mode 100644 index 08f6cbad96..0000000000 --- a/metric/memory/memory.go +++ /dev/null @@ -1,103 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 memory - -import ( - "fmt" - - "github.com/elastic/elastic-agent-libs/opt" - "github.com/elastic/elastic-agent-system-metrics/metric" - "github.com/elastic/elastic-agent-system-metrics/metric/system/resolve" -) - -// Memory holds os-specifc memory usage data -// The vast majority of these values are cross-platform -// However, we're wrapping all them for the sake of safety, and for the more variable swap metrics -type Memory struct { - Total opt.Uint `struct:"total,omitempty"` - Used UsedMemStats `struct:"used,omitempty"` - - Free opt.Uint `struct:"free,omitempty"` - Cached opt.Uint `struct:"cached,omitempty"` - // "Actual" values are, technically, a linux-only concept - // For better or worse we've expanded it to include "derived" - // Memory values on other platforms, which we should - // probably keep for the sake of backwards compatibility - // However, because the derived value varies from platform to platform, - // We may want to more precisely document what these mean. - Actual ActualMemoryMetrics `struct:"actual,omitempty"` - - // Swap metrics - Swap SwapMetrics `struct:"swap,omitempty"` -} - -// UsedMemStats wraps used.* memory metrics -type UsedMemStats struct { - Pct opt.Float `struct:"pct,omitempty"` - Bytes opt.Uint `struct:"bytes,omitempty"` -} - -// ActualMemoryMetrics wraps the actual.* memory metrics -type ActualMemoryMetrics struct { - Free opt.Uint `struct:"free,omitempty"` - Used UsedMemStats `struct:"used,omitempty"` -} - -// SwapMetrics wraps swap.* memory metrics -type SwapMetrics struct { - Total opt.Uint `struct:"total,omitempty"` - Used UsedMemStats `struct:"used,omitempty"` - Free opt.Uint `struct:"free,omitempty"` -} - -// Get returns platform-independent memory metrics. -func Get(procfs resolve.Resolver) (Memory, error) { - base, err := get(procfs) - if err != nil { - return Memory{}, fmt.Errorf("error getting system memory info: %w", err) - } - base.fillPercentages() - return base, nil -} - -// IsZero implements the zeroer interface for structform's folders -func (used UsedMemStats) IsZero() bool { - return used.Pct.IsZero() && used.Bytes.IsZero() -} - -// IsZero implements the zeroer interface for structform's folders -func (swap SwapMetrics) IsZero() bool { - return swap.Free.IsZero() && swap.Used.IsZero() && swap.Total.IsZero() -} - -func (base *Memory) fillPercentages() { - // Add percentages - // In theory, `Used` and `Total` are available everywhere, so assume values are good. - if base.Total.Exists() && base.Total.ValueOr(0) != 0 { - percUsed := float64(base.Used.Bytes.ValueOr(0)) / float64(base.Total.ValueOr(1)) - base.Used.Pct = opt.FloatWith(metric.Round(percUsed)) - - actualPercUsed := float64(base.Actual.Used.Bytes.ValueOr(0)) / float64(base.Total.ValueOr(0)) - base.Actual.Used.Pct = opt.FloatWith(metric.Round(actualPercUsed)) - } - - if base.Swap.Total.ValueOr(0) != 0 && base.Swap.Used.Bytes.Exists() { - perc := float64(base.Swap.Used.Bytes.ValueOr(0)) / float64(base.Swap.Total.ValueOr(0)) - base.Swap.Used.Pct = opt.FloatWith(metric.Round(perc)) - } -} diff --git a/metric/memory/memory_aix.go b/metric/memory/memory_aix.go deleted file mode 100644 index 1c163b379d..0000000000 --- a/metric/memory/memory_aix.go +++ /dev/null @@ -1,76 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 memory - -/* -#cgo LDFLAGS: -L/usr/lib -lperfstat - -#include -#include -#include -#include -#include -#include -#include -#include - -*/ -import "C" - -import ( - "fmt" - "os" - - "github.com/elastic/elastic-agent-libs/opt" - "github.com/elastic/elastic-agent-system-metrics/metric/system/resolve" -) - -var system struct { - ticks uint64 - btime uint64 - pagesize uint64 -} - -func init() { - // sysconf(_SC_CLK_TCK) returns the number of ticks by second. - system.ticks = uint64(C.sysconf(C._SC_CLK_TCK)) - system.pagesize = uint64(os.Getpagesize()) -} - -func get(_ resolve.Resolver) (Memory, error) { - memData := Memory{} - meminfo := C.perfstat_memory_total_t{} - _, err := C.perfstat_memory_total(nil, &meminfo, C.sizeof_perfstat_memory_total_t, 1) - if err != nil { - return memData, fmt.Errorf("perfstat_memory_total: %s", err) - } - - totalMem := uint64(meminfo.real_total) * system.pagesize - freeMem := uint64(meminfo.real_free) * system.pagesize - - memData.Total = opt.UintWith(totalMem) - memData.Free = opt.UintWith(freeMem) - - kern := uint64(meminfo.numperm) * system.pagesize // number of pages in file cache - - memData.Used.Bytes = opt.UintWith(totalMem - freeMem) - memData.Actual.Free = opt.UintWith(freeMem + kern) - memData.Actual.Used.Bytes = opt.UintWith(memData.Used.Bytes.ValueOr(0) - kern) - - return memData, nil -} diff --git a/metric/memory/memory_darwin.go b/metric/memory/memory_darwin.go deleted file mode 100644 index 94f0913d4c..0000000000 --- a/metric/memory/memory_darwin.go +++ /dev/null @@ -1,132 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 memory - -/* -#include -#include -#include -#include -#include -#include -#include -#include -#include -*/ -import "C" - -import ( - "bytes" - "encoding/binary" - "fmt" - "syscall" - "unsafe" - - "github.com/elastic/elastic-agent-libs/opt" - "github.com/elastic/elastic-agent-system-metrics/metric/system/resolve" -) - -type xswUsage struct { - Total, Avail, Used uint64 -} - -// get is the darwin implementation for fetching Memory data -func get(_ resolve.Resolver) (Memory, error) { - var vmstat C.vm_statistics_data_t - - mem := Memory{} - - var total uint64 - - if err := sysctlbyname("hw.memsize", &total); err != nil { - return Memory{}, fmt.Errorf("error getting memsize: %w", err) - } - mem.Total = opt.UintWith(total) - - if err := vmInfo(&vmstat); err != nil { - return Memory{}, fmt.Errorf("error getting VM info") - } - - kern := uint64(vmstat.inactive_count) << 12 - free := uint64(vmstat.free_count) << 12 - - mem.Free = opt.UintWith(free) - mem.Used.Bytes = opt.UintWith(total - free) - - mem.Actual.Free = opt.UintWith(free + kern) - mem.Actual.Used.Bytes = opt.UintWith((total - free) - kern) - - var err error - mem.Swap, err = getSwap() - if err != nil { - return mem, fmt.Errorf("error getting swap memory: %w", err) - } - - return mem, nil -} - -// Get fetches swap data -func getSwap() (SwapMetrics, error) { - swUsage := xswUsage{} - - swap := SwapMetrics{} - if err := sysctlbyname("vm.swapusage", &swUsage); err != nil { - return swap, fmt.Errorf("error getting swap usage: %w", err) - } - - swap.Total = opt.UintWith(swUsage.Total) - swap.Used.Bytes = opt.UintWith(swUsage.Used) - swap.Free = opt.UintWith(swUsage.Avail) - - return swap, nil -} - -// generic Sysctl buffer unmarshalling -func sysctlbyname(name string, data interface{}) (err error) { - val, err := syscall.Sysctl(name) - if err != nil { - return err - } - - buf := []byte(val) - - switch v := data.(type) { - case *uint64: - *v = *(*uint64)(unsafe.Pointer(&buf[0])) - return - } - - bbuf := bytes.NewBuffer([]byte(val)) - return binary.Read(bbuf, binary.LittleEndian, data) -} - -func vmInfo(vmstat *C.vm_statistics_data_t) error { - var count C.mach_msg_type_number_t = C.HOST_VM_INFO_COUNT - - status := C.host_statistics( - C.host_t(C.mach_host_self()), - C.HOST_VM_INFO, - C.host_info_t(unsafe.Pointer(vmstat)), - &count) - - if status != C.KERN_SUCCESS { - return fmt.Errorf("host_statistics=%d", status) - } - - return nil -} diff --git a/metric/memory/memory_freebsd.go b/metric/memory/memory_freebsd.go deleted file mode 100644 index 1ec306d935..0000000000 --- a/metric/memory/memory_freebsd.go +++ /dev/null @@ -1,90 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 memory - -import ( - "errors" - "unsafe" - - "github.com/elastic/elastic-agent-libs/opt" - "github.com/elastic/elastic-agent-system-metrics/metric/system/resolve" -) - -/* -#include -#include -#include -#include -#include -#include -#include -#include -#include -*/ -import "C" - -func get(_ resolve.Resolver) (Memory, error) { - val := C.uint32_t(0) - sc := C.size_t(4) - - memData := Memory{} - - name := C.CString("vm.stats.vm.v_page_count") - _, err := C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0) - C.free(unsafe.Pointer(name)) - if err != nil { - return memData, errors.New("error in vm.stats.vm.v_page_count") - } - pagecount := uint64(val) - - name = C.CString("vm.stats.vm.v_page_size") - _, err = C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0) - C.free(unsafe.Pointer(name)) - if err != nil { - return memData, errors.New("error in vm.stats.vm.v_page_size") - } - pagesize := uint64(val) - - name = C.CString("vm.stats.vm.v_free_count") - _, err = C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0) - C.free(unsafe.Pointer(name)) - if err != nil { - return memData, errors.New("error in vm.stats.vm.v_free_count") - } - - memFree := uint64(val) * pagesize - memData.Free = opt.UintWith(memFree) - - name = C.CString("vm.stats.vm.v_inactive_count") - _, err = C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0) - C.free(unsafe.Pointer(name)) - if err != nil { - return memData, errors.New("error in vm.stats.vm.v_inactive_count") - } - kern := uint64(val) - - memTotal := uint64(pagecount * pagesize) - - memData.Total = opt.UintWith(memTotal) - - memData.Used.Bytes = opt.UintWith(memTotal - memFree) - memData.Actual.Free = opt.UintWith(memFree + (kern * pagesize)) - memData.Actual.Used.Bytes = opt.UintWith((memTotal - memFree) - (kern * pagesize)) - - return memData, nil -} diff --git a/metric/memory/memory_helpers.go b/metric/memory/memory_helpers.go deleted file mode 100644 index a2cf1e54b4..0000000000 --- a/metric/memory/memory_helpers.go +++ /dev/null @@ -1,79 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 memory - -import ( - "bufio" - "bytes" - "fmt" - "io" - "os" - "strconv" - "strings" - - "github.com/elastic/elastic-agent-system-metrics/metric/system/resolve" -) - -// ParseMeminfo parses the contents of /proc/meminfo into a hashmap -func ParseMeminfo(rootfs resolve.Resolver) (map[string]uint64, error) { - table := map[string]uint64{} - - meminfoPath := rootfs.ResolveHostFS("/proc/meminfo") - err := readFile(meminfoPath, func(line string) bool { - fields := strings.Split(line, ":") - - if len(fields) != 2 { - return true // skip on errors - } - - valueUnit := strings.Fields(fields[1]) - value, err := strconv.ParseUint(valueUnit[0], 10, 64) - if err != nil { - return true // skip on errors - } - - if len(valueUnit) > 1 && valueUnit[1] == "kB" { - value *= 1024 - } - table[fields[0]] = value - - return true - }) - return table, err -} - -func readFile(file string, handler func(string) bool) error { - contents, err := os.ReadFile(file) - if err != nil { - return fmt.Errorf("error reading file %s: %w", file, err) - } - - reader := bufio.NewReader(bytes.NewBuffer(contents)) - - for { - line, _, err := reader.ReadLine() - if err == io.EOF { - break - } - if !handler(string(line)) { - break - } - } - - return nil -} diff --git a/metric/memory/memory_linux.go b/metric/memory/memory_linux.go deleted file mode 100644 index 947d2744fd..0000000000 --- a/metric/memory/memory_linux.go +++ /dev/null @@ -1,88 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 memory - -import ( - "fmt" - - "github.com/elastic/elastic-agent-libs/opt" - "github.com/elastic/elastic-agent-system-metrics/metric/system/resolve" -) - -// get is the linux implementation for fetching Memory data -func get(rootfs resolve.Resolver) (Memory, error) { - table, err := ParseMeminfo(rootfs) - if err != nil { - return Memory{}, fmt.Errorf("error fetching meminfo: %w", err) - } - - memData := Memory{} - - var free, cached uint64 - var ok bool - if total, ok := table["MemTotal"]; ok { - memData.Total = opt.UintWith(total) - } - if free, ok = table["MemFree"]; ok { - memData.Free = opt.UintWith(free) - } - if cached, ok = table["Cached"]; ok { - memData.Cached = opt.UintWith(cached) - } - - // overlook parsing issues here - // On the very small chance some of these don't exist, - // It's not the end of the world - buffers := table["Buffers"] - - if memAvail, ok := table["MemAvailable"]; ok { - // MemAvailable is in /proc/meminfo (kernel 3.14+) - memData.Actual.Free = opt.UintWith(memAvail) - } else { - // in the future we may want to find another way to do this. - // "MemAvailable" and other more derivied metrics - // Are very relative, and can be unhelpful in cerntain workloads - // We may want to find a way to more clearly express to users - // where a certain value is coming from and what it represents - - // The use of `cached` here is particularly concerning, - // as under certain intense DB server workloads, the cached memory can be quite large - // and give the impression that we've passed memory usage watermark - memData.Actual.Free = opt.UintWith(free + buffers + cached) - } - - memData.Used.Bytes = opt.UintWith(memData.Total.ValueOr(0) - memData.Free.ValueOr(0)) - memData.Actual.Used.Bytes = opt.UintWith(memData.Total.ValueOr(0) - memData.Actual.Free.ValueOr(0)) - - // Populate swap data - swapTotal, okST := table["SwapTotal"] - if okST { - memData.Swap.Total = opt.UintWith(swapTotal) - } - swapFree, okSF := table["SwapFree"] - if okSF { - memData.Swap.Free = opt.UintWith(swapFree) - } - - if okSF && okST { - memData.Swap.Used.Bytes = opt.UintWith(swapTotal - swapFree) - } - - return memData, nil - -} diff --git a/metric/memory/memory_openbsd.go b/metric/memory/memory_openbsd.go deleted file mode 100644 index 88e4ee71aa..0000000000 --- a/metric/memory/memory_openbsd.go +++ /dev/null @@ -1,236 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 memory - -/* -#include -#include -#include -#include -#include -#include -#include -#include -*/ -import "C" - -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/elastic/elastic-agent-libs/opt" - "github.com/elastic/elastic-agent-system-metrics/metric/system/resolve" -) - -// Uvmexp wraps memory data from sysctl -type Uvmexp struct { - pagesize uint32 - pagemask uint32 - pageshift uint32 - npages uint32 - free uint32 - active uint32 - inactive uint32 - paging uint32 - wired uint32 - zeropages uint32 - reserve_pagedaemon uint32 - reserve_kernel uint32 - anonpages uint32 - vnodepages uint32 - vtextpages uint32 - freemin uint32 - freetarg uint32 - inactarg uint32 - wiredmax uint32 - anonmin uint32 - vtextmin uint32 - vnodemin uint32 - anonminpct uint32 - vtextmi uint32 - npct uint32 - vnodeminpct uint32 - nswapdev uint32 - swpages uint32 - swpginuse uint32 - swpgonly uint32 - nswget uint32 - nanon uint32 - nanonneeded uint32 - nfreeanon uint32 - faults uint32 - traps uint32 - intrs uint32 - swtch uint32 - softs uint32 - syscalls uint32 - pageins uint32 - obsolete_swapins uint32 - obsolete_swapouts uint32 - pgswapin uint32 - pgswapout uint32 - forks uint32 - forks_ppwait uint32 - forks_sharevm uint32 - pga_zerohit uint32 - pga_zeromiss uint32 - zeroaborts uint32 - fltnoram uint32 - fltnoanon uint32 - fltpgwait uint32 - fltpgrele uint32 - fltrelck uint32 - fltrelckok uint32 - fltanget uint32 - fltanretry uint32 - fltamcopy uint32 - fltnamap uint32 - fltnomap uint32 - fltlget uint32 - fltget uint32 - flt_anon uint32 - flt_acow uint32 - flt_obj uint32 - flt_prcopy uint32 - flt_przero uint32 - pdwoke uint32 - pdrevs uint32 - pdswout uint32 - pdfreed uint32 - pdscans uint32 - pdanscan uint32 - pdobscan uint32 - pdreact uint32 - pdbusy uint32 - pdpageouts uint32 - pdpending uint32 - pddeact uint32 - pdreanon uint32 - pdrevnode uint32 - pdrevtext uint32 - fpswtch uint32 - kmapent uint32 -} - -// Bcachestats reports cache stats from sysctl -type Bcachestats struct { - numbufs uint64 - numbufpages uint64 - numdirtypages uint64 - numcleanpages uint64 - pendingwrites uint64 - pendingreads uint64 - numwrites uint64 - numreads uint64 - cachehits uint64 - busymapped uint64 - dmapages uint64 - highpages uint64 - delwribufs uint64 - kvaslots uint64 - kvaslots_avail uint64 -} - -// Swapent reports swap metrics from sysctl -type Swapent struct { - se_dev C.dev_t - se_flags int32 - se_nblks int32 - se_inuse int32 - se_priority int32 - sw_path []byte -} - -func get(_ resolve.Resolver) (Memory, error) { - - memData := Memory{} - - n := uintptr(0) - var uvmexp Uvmexp - mib := [2]int32{C.CTL_VM, C.VM_UVMEXP} - n = uintptr(0) - // First we determine how much memory we'll need to pass later on (via `n`) - _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0) - if errno != 0 || n == 0 { - return memData, fmt.Errorf("Error in size VM_UVMEXP sysctl call, errno %d", errno) - } - - _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&uvmexp)), uintptr(unsafe.Pointer(&n)), 0, 0) - if errno != 0 || n == 0 { - return memData, fmt.Errorf("Error in VM_UVMEXP sysctl call, errno %d", errno) - } - - var bcachestats Bcachestats - mib3 := [3]int32{C.CTL_VFS, C.VFS_GENERIC, C.VFS_BCACHESTAT} - n = uintptr(0) - _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib3[0])), 3, 0, uintptr(unsafe.Pointer(&n)), 0, 0) - if errno != 0 || n == 0 { - return memData, fmt.Errorf("Error in size VFS_BCACHESTAT sysctl call, errno %d", errno) - } - _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib3[0])), 3, uintptr(unsafe.Pointer(&bcachestats)), uintptr(unsafe.Pointer(&n)), 0, 0) - if errno != 0 || n == 0 { - return memData, fmt.Errorf("Error in VFS_BCACHESTAT sysctl call, errno %d", errno) - } - - memFree := uint64(uvmexp.free) << uvmexp.pageshift - memUsed := uint64(uvmexp.npages-uvmexp.free) << uvmexp.pageshift - - memData.Total = opt.UintWith(uint64(uvmexp.npages) << uvmexp.pageshift) - memData.Used.Bytes = opt.UintWith(memUsed) - memData.Free = opt.UintWith(memFree) - - memData.Actual.Free = opt.UintWith(memFree + (uint64(bcachestats.numbufpages) << uvmexp.pageshift)) - memData.Actual.Used.Bytes = opt.UintWith(memUsed - (uint64(bcachestats.numbufpages) << uvmexp.pageshift)) - - var err error - memData.Swap, err = getSwap() - if err != nil { - return memData, fmt.Errorf("error getting swap data: %w", err) - } - - return memData, nil -} - -func getSwap() (SwapMetrics, error) { - swapData := SwapMetrics{} - nswap := C.swapctl(C.SWAP_NSWAP, unsafe.Pointer(uintptr(0)), 0) - - // If there are no swap devices, nothing to do here. - if nswap == 0 { - return swapData, nil - } - - swdev := make([]Swapent, nswap) - - rnswap := C.swapctl(C.SWAP_STATS, unsafe.Pointer(&swdev[0]), nswap) - if rnswap == 0 { - return swapData, fmt.Errorf("error in SWAP_STATS sysctl, swapctl returned %d", rnswap) - } - - for i := 0; i < int(nswap); i++ { - if swdev[i].se_flags&C.SWF_ENABLE == 2 { - swapData.Used.Bytes = opt.UintWith(swapData.Used.Bytes.ValueOr(0) + uint64(swdev[i].se_inuse/(1024/C.DEV_BSIZE))) - swapData.Total = opt.UintWith(swapData.Total.ValueOr(0) + uint64(swdev[i].se_nblks/(1024/C.DEV_BSIZE))) - } - } - - swapData.Free = opt.UintWith(swapData.Total.ValueOr(0) - swapData.Used.Bytes.ValueOr(0)) - - return swapData, nil -} diff --git a/metric/memory/memory_test.go b/metric/memory/memory_test.go deleted file mode 100644 index bc621473ef..0000000000 --- a/metric/memory/memory_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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. - -//go:build !integration && (darwin || freebsd || linux || openbsd || windows) -// +build !integration -// +build darwin freebsd linux openbsd windows - -package memory - -import ( - "runtime" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/elastic/elastic-agent-libs/opt" - "github.com/elastic/elastic-agent-system-metrics/metric/system/resolve" -) - -func TestGetMemory(t *testing.T) { - mem, err := Get(resolve.NewTestResolver("")) - - assert.NotNil(t, mem) - assert.NoError(t, err) - - assert.True(t, mem.Total.Exists()) - assert.True(t, (mem.Total.ValueOr(0) > 0)) - - assert.True(t, mem.Used.Bytes.Exists()) - assert.True(t, (mem.Used.Bytes.ValueOr(0) > 0)) - - assert.True(t, mem.Free.Exists()) - assert.True(t, (mem.Free.ValueOr(0) >= 0)) //nolint:staticcheck // we can return with zero - - assert.True(t, mem.Actual.Free.Exists()) - assert.True(t, (mem.Actual.Free.ValueOr(0) >= 0)) //nolint:staticcheck // we can return with zero - - assert.True(t, mem.Actual.Used.Bytes.Exists()) - assert.True(t, (mem.Actual.Used.Bytes.ValueOr(0) > 0)) -} - -func TestGetSwap(t *testing.T) { - if runtime.GOOS == "freebsd" { - return //no load data on freebsd - } - - mem, err := Get(resolve.NewTestResolver("")) - - assert.NotNil(t, mem) - assert.NoError(t, err) - - assert.True(t, mem.Swap.Total.Exists()) - assert.True(t, (mem.Swap.Total.ValueOr(0) >= 0)) //nolint:staticcheck // we can return with zero - - assert.True(t, mem.Swap.Used.Bytes.Exists()) - assert.True(t, (mem.Swap.Used.Bytes.ValueOr(0) >= 0)) //nolint:staticcheck // we can return with zero - - assert.True(t, mem.Swap.Free.Exists()) - assert.True(t, (mem.Swap.Free.ValueOr(0) >= 0)) //nolint:staticcheck // we can return with zero -} - -func TestMemPercentage(t *testing.T) { - m := Memory{ - Total: opt.UintWith(7), - Used: UsedMemStats{Bytes: opt.UintWith(5)}, - Free: opt.UintWith(2), - } - m.fillPercentages() - assert.Equal(t, m.Used.Pct.ValueOr(0), 0.7143) - - m = Memory{ - Total: opt.UintWith(0), - } - m.fillPercentages() - assert.Equal(t, m.Used.Pct.ValueOr(0), 0.0) -} - -func TestActualMemPercentage(t *testing.T) { - m := Memory{ - Total: opt.UintWith(7), - Actual: ActualMemoryMetrics{ - Used: UsedMemStats{Bytes: opt.UintWith(5)}, - Free: opt.UintWith(2), - }, - } - - m.fillPercentages() - assert.Equal(t, m.Actual.Used.Pct.ValueOr(0), 0.7143) - -} - -func TestMeminfoParse(t *testing.T) { - // Make sure we're manually calculating Actual correctly on linux - if runtime.GOOS == "linux" { - mem, err := Get(resolve.NewTestResolver("./oldkern")) - assert.NoError(t, err) - - assert.Equal(t, uint64(27307106304), mem.Cached.ValueOr(0)) - assert.Equal(t, uint64(52983070720), mem.Actual.Free.ValueOr(0)) - assert.Equal(t, uint64(10137726976), mem.Actual.Used.Bytes.ValueOr(0)) - } -} - -func TestMeminfoPct(t *testing.T) { - if runtime.GOOS == "linux" { - memRaw, err := Get(resolve.NewTestResolver("./oldkern")) - assert.NoError(t, err) - assert.Equal(t, float64(0.1606), memRaw.Actual.Used.Pct.ValueOr(0)) - assert.Equal(t, float64(0.5933), memRaw.Used.Pct.ValueOr(0)) - } -} diff --git a/metric/memory/memory_windows.go b/metric/memory/memory_windows.go deleted file mode 100644 index 151cfecc75..0000000000 --- a/metric/memory/memory_windows.go +++ /dev/null @@ -1,52 +0,0 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you 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 memory - -import ( - "fmt" - - "github.com/elastic/elastic-agent-libs/opt" - "github.com/elastic/elastic-agent-system-metrics/metric/system/resolve" - "github.com/elastic/go-windows" -) - -// get is the windows implementation of get for memory metrics -func get(_ resolve.Resolver) (Memory, error) { - - memData := Memory{} - - memoryStatusEx, err := windows.GlobalMemoryStatusEx() - if err != nil { - return memData, fmt.Errorf("error fetching global memory status: %w", err) - } - memData.Total = opt.UintWith(memoryStatusEx.TotalPhys) - memData.Free = opt.UintWith(memoryStatusEx.AvailPhys) - - memData.Used.Bytes = opt.UintWith(memoryStatusEx.TotalPhys - memoryStatusEx.AvailPhys) - - // We shouldn't really be doing this, but we also don't want to make breaking changes right now, - // and memory.actual is used by quite a few visualizations - memData.Actual.Free = memData.Free - memData.Actual.Used.Bytes = memData.Used.Bytes - - memData.Swap.Free = opt.UintWith(memoryStatusEx.AvailPageFile) - memData.Swap.Total = opt.UintWith(memoryStatusEx.TotalPageFile) - memData.Swap.Used.Bytes = opt.UintWith(memoryStatusEx.TotalPageFile - memoryStatusEx.AvailPageFile) - - return memData, nil -} diff --git a/metric/memory/oldkern/proc/meminfo b/metric/memory/oldkern/proc/meminfo deleted file mode 100644 index 504a1e4b80..0000000000 --- a/metric/memory/oldkern/proc/meminfo +++ /dev/null @@ -1,48 +0,0 @@ -MemTotal: 61641404 kB -MemFree: 25071456 kB -Buffers: 2728 kB -Cached: 26667096 kB -SwapCached: 0 kB -Active: 7766692 kB -Inactive: 25447972 kB -Active(anon): 3332 kB -Inactive(anon): 6526672 kB -Active(file): 7763360 kB -Inactive(file): 18921300 kB -Unevictable: 3072 kB -Mlocked: 0 kB -SwapTotal: 8388604 kB -SwapFree: 8386812 kB -Dirty: 4576 kB -Writeback: 0 kB -AnonPages: 6396352 kB -Mapped: 863432 kB -Shmem: 9504 kB -KReclaimable: 1539312 kB -Slab: 2387096 kB -SReclaimable: 1539312 kB -SUnreclaim: 847784 kB -KernelStack: 14880 kB -PageTables: 59592 kB -NFS_Unstable: 0 kB -Bounce: 0 kB -WritebackTmp: 0 kB -CommitLimit: 39209304 kB -Committed_AS: 11220776 kB -VmallocTotal: 34359738367 kB -VmallocUsed: 87056 kB -VmallocChunk: 0 kB -Percpu: 70272 kB -HardwareCorrupted: 0 kB -AnonHugePages: 235520 kB -ShmemHugePages: 0 kB -ShmemPmdMapped: 0 kB -FileHugePages: 0 kB -FilePmdMapped: 0 kB -CmaTotal: 0 kB -CmaFree: 0 kB -Hugepagesize: 2048 kB -Hugetlb: 0 kB -DirectMap4k: 2092268 kB -DirectMap2M: 51320832 kB -DirectMap1G: 9437184 kB \ No newline at end of file