diff --git a/CHANGELOG.md b/CHANGELOG.md index f1727d20..b74c7642 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add `VMStat` interface for Linux. [#59](https://github.com/elastic/go-sysinfo/pull/59) + ### Changed ### Deprecated diff --git a/README.md b/README.md index 3a657a4b..958f11c2 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ that are implemented. | `Info()` | x | x | x | | `Memory()` | x | x | x | | `CPUTimer` | x | x | x | +| `VMStat` | | x | | | `Process` Features | Darwin | Linux | Windows | |------------------------|--------|-------|---------| diff --git a/providers/linux/host_linux.go b/providers/linux/host_linux.go index 9b09ddff..19325b02 100644 --- a/providers/linux/host_linux.go +++ b/providers/linux/host_linux.go @@ -71,6 +71,16 @@ func (h *host) Memory() (*types.HostMemoryInfo, error) { return parseMemInfo(content) } +// VMStat reports data from /proc/vmstat on linux. +func (h *host) VMStat() (*types.VMStatInfo, error) { + content, err := ioutil.ReadFile(h.procFS.path("vmstat")) + if err != nil { + return nil, err + } + + return parseVMStat(content) +} + func (h *host) CPUTime() (types.CPUTimes, error) { stat, err := h.procFS.NewStat() if err != nil { diff --git a/providers/linux/host_linux_test.go b/providers/linux/host_linux_test.go index 98ad62c3..17bb4ade 100644 --- a/providers/linux/host_linux_test.go +++ b/providers/linux/host_linux_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/elastic/go-sysinfo/internal/registry" + "github.com/elastic/go-sysinfo/types" ) var _ registry.HostProvider = linuxSystem{} @@ -53,3 +54,20 @@ func TestHostMemoryInfo(t *testing.T) { assert.NotContains(t, m.Metrics, "MemTotal") assert.Contains(t, m.Metrics, "Slab") } + +func TestHostVMStat(t *testing.T) { + host, err := newLinuxSystem("testdata/ubuntu1710").Host() + if err != nil { + t.Fatal(err) + } + s, err := host.(types.VMStat).VMStat() + if err != nil { + t.Fatal(err) + } + + data, err := json.MarshalIndent(s, "", " ") + if err != nil { + t.Fatal(err) + } + t.Log(string(data)) +} diff --git a/providers/linux/memory_linux.go b/providers/linux/memory_linux.go index 30357430..758caaba 100644 --- a/providers/linux/memory_linux.go +++ b/providers/linux/memory_linux.go @@ -18,9 +18,6 @@ package linux import ( - "bytes" - "strconv" - "github.com/pkg/errors" "github.com/elastic/go-sysinfo/types" @@ -73,28 +70,3 @@ func parseMemInfo(content []byte) (*types.HostMemoryInfo, error) { return memInfo, nil } - -func parseBytesOrNumber(data []byte) (uint64, error) { - parts := bytes.Fields(data) - - if len(parts) == 0 { - return 0, errors.New("empty value") - } - - num, err := strconv.ParseUint(string(parts[0]), 10, 64) - if err != nil { - return 0, errors.Wrap(err, "failed to parse value") - } - - var multiplier uint64 = 1 - if len(parts) >= 2 { - switch string(parts[1]) { - case "kB": - multiplier = 1024 - default: - return 0, errors.Errorf("unhandled unit %v", string(parts[1])) - } - } - - return num * multiplier, nil -} diff --git a/providers/linux/testdata/ubuntu1710/proc/vmstat b/providers/linux/testdata/ubuntu1710/proc/vmstat new file mode 100644 index 00000000..7ff1d855 --- /dev/null +++ b/providers/linux/testdata/ubuntu1710/proc/vmstat @@ -0,0 +1,133 @@ +nr_free_pages 50545 +nr_zone_inactive_anon 66 +nr_zone_active_anon 26799 +nr_zone_inactive_file 31849 +nr_zone_active_file 94164 +nr_zone_unevictable 0 +nr_zone_write_pending 7 +nr_mlock 0 +nr_page_table_pages 1225 +nr_kernel_stack 2496 +nr_bounce 0 +nr_zspages 0 +nr_free_cma 0 +numa_hit 44470329 +numa_miss 0 +numa_foreign 0 +numa_interleave 16296 +numa_local 44470329 +numa_other 0 +nr_inactive_anon 66 +nr_active_anon 26799 +nr_inactive_file 31849 +nr_active_file 94164 +nr_unevictable 0 +nr_slab_reclaimable 31763 +nr_slab_unreclaimable 10329 +nr_isolated_anon 0 +nr_isolated_file 0 +workingset_refault 302914 +workingset_activate 108959 +workingset_nodereclaim 6422 +nr_anon_pages 26218 +nr_mapped 8641 +nr_file_pages 126182 +nr_dirty 7 +nr_writeback 0 +nr_writeback_temp 0 +nr_shmem 169 +nr_shmem_hugepages 0 +nr_shmem_pmdmapped 0 +nr_anon_transparent_hugepages 0 +nr_unstable 0 +nr_vmscan_write 35 +nr_vmscan_immediate_reclaim 9832 +nr_dirtied 7188920 +nr_written 6479005 +nr_dirty_threshold 31736 +nr_dirty_background_threshold 15848 +pgpgin 17010697 +pgpgout 27734292 +pswpin 0 +pswpout 0 +pgalloc_dma 241378 +pgalloc_dma32 45788683 +pgalloc_normal 0 +pgalloc_movable 0 +allocstall_dma 0 +allocstall_dma32 0 +allocstall_normal 5 +allocstall_movable 8 +pgskip_dma 0 +pgskip_dma32 0 +pgskip_normal 0 +pgskip_movable 0 +pgfree 46085578 +pgactivate 2475069 +pgdeactivate 636658 +pglazyfree 9426 +pgfault 46777498 +pgmajfault 19204 +pglazyfreed 0 +pgrefill 707817 +pgsteal_kswapd 3798890 +pgsteal_direct 1466 +pgscan_kswapd 3868525 +pgscan_direct 1483 +pgscan_direct_throttle 0 +zone_reclaim_failed 0 +pginodesteal 1710 +slabs_scanned 8348560 +kswapd_inodesteal 3142001 +kswapd_low_wmark_hit_quickly 541 +kswapd_high_wmark_hit_quickly 332 +pageoutrun 1492 +pgrotated 29725 +drop_pagecache 0 +drop_slab 0 +oom_kill 0 +numa_pte_updates 0 +numa_huge_pte_updates 0 +numa_hint_faults 0 +numa_hint_faults_local 0 +numa_pages_migrated 0 +pgmigrate_success 4539 +pgmigrate_fail 156 +compact_migrate_scanned 9331 +compact_free_scanned 136266 +compact_isolated 9407 +compact_stall 2 +compact_fail 0 +compact_success 2 +compact_daemon_wake 21 +compact_daemon_migrate_scanned 8311 +compact_daemon_free_scanned 107086 +htlb_buddy_alloc_success 0 +htlb_buddy_alloc_fail 0 +unevictable_pgs_culled 19 +unevictable_pgs_scanned 0 +unevictable_pgs_rescued 304 +unevictable_pgs_mlocked 304 +unevictable_pgs_munlocked 304 +unevictable_pgs_cleared 0 +unevictable_pgs_stranded 0 +thp_fault_alloc 2 +thp_fault_fallback 0 +thp_collapse_alloc 2 +thp_collapse_alloc_failed 0 +thp_file_alloc 0 +thp_file_mapped 0 +thp_split_page 0 +thp_split_page_failed 0 +thp_deferred_split_page 4 +thp_split_pmd 1 +thp_split_pud 0 +thp_zero_page_alloc 0 +thp_zero_page_alloc_failed 0 +thp_swpout 0 +thp_swpout_fallback 0 +balloon_inflate 0 +balloon_deflate 0 +balloon_migrate 0 +swap_ra 0 +swap_ra_hit 0 \ No newline at end of file diff --git a/providers/linux/util.go b/providers/linux/util.go index 066fef6a..0be3f6b0 100644 --- a/providers/linux/util.go +++ b/providers/linux/util.go @@ -84,3 +84,28 @@ func decodeBitMap(s string, lookupName func(int) string) ([]string, error) { return names, nil } + +func parseBytesOrNumber(data []byte) (uint64, error) { + parts := bytes.Fields(data) + + if len(parts) == 0 { + return 0, errors.New("empty value") + } + + num, err := strconv.ParseUint(string(parts[0]), 10, 64) + if err != nil { + return 0, errors.Wrap(err, "failed to parse value") + } + + var multiplier uint64 = 1 + if len(parts) >= 2 { + switch string(parts[1]) { + case "kB": + multiplier = 1024 + default: + return 0, errors.Errorf("unhandled unit %v", string(parts[1])) + } + } + + return num * multiplier, nil +} diff --git a/providers/linux/vmstat.go b/providers/linux/vmstat.go new file mode 100644 index 00000000..0a228678 --- /dev/null +++ b/providers/linux/vmstat.go @@ -0,0 +1,70 @@ +// 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 linux + +import ( + "reflect" + + "github.com/pkg/errors" + + "github.com/elastic/go-sysinfo/types" +) + +// vmstatTagToFieldIndex contains a mapping of json struct tags to struct field indices. +var vmstatTagToFieldIndex = make(map[string]int) + +func init() { + var vmstat types.VMStatInfo + val := reflect.ValueOf(vmstat) + typ := reflect.TypeOf(vmstat) + + for i := 0; i < val.NumField(); i++ { + field := typ.Field(i) + if tag := field.Tag.Get("json"); tag != "" { + vmstatTagToFieldIndex[tag] = i + } + } +} + +// parseVMStat parses the contents of /proc/vmstat. +func parseVMStat(content []byte) (*types.VMStatInfo, error) { + var vmStat types.VMStatInfo + refValues := reflect.ValueOf(&vmStat).Elem() + + err := parseKeyValue(content, " ", func(key, value []byte) error { + // turn our []byte value into an int + val, err := parseBytesOrNumber(value) + if err != nil { + return errors.Wrapf(err, "failed to parse %v value of %v", string(key), string(value)) + } + + idx, ok := vmstatTagToFieldIndex[string(key)] + if !ok { + return nil + } + + sval := refValues.Field(idx) + + if sval.CanSet() { + sval.SetUint(val) + } + return nil + }) + + return &vmStat, err +} diff --git a/providers/linux/vmstat_test.go b/providers/linux/vmstat_test.go new file mode 100644 index 00000000..1e44cb9f --- /dev/null +++ b/providers/linux/vmstat_test.go @@ -0,0 +1,171 @@ +// 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 linux + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +var rawInput = ` +nr_free_pages 50545 +nr_zone_inactive_anon 66 +nr_zone_active_anon 26799 +nr_zone_inactive_file 31849 +nr_zone_active_file 94164 +nr_zone_unevictable 0 +nr_zone_write_pending 7 +nr_mlock 0 +nr_page_table_pages 1225 +nr_kernel_stack 2496 +nr_bounce 0 +nr_zspages 0 +nr_free_cma 0 +numa_hit 44470329 +numa_miss 0 +numa_foreign 0 +numa_interleave 16296 +numa_local 44470329 +numa_other 0 +nr_inactive_anon 66 +nr_active_anon 26799 +nr_inactive_file 31849 +nr_active_file 94164 +nr_unevictable 0 +nr_slab_reclaimable 31763 +nr_slab_unreclaimable 10329 +nr_isolated_anon 0 +nr_isolated_file 0 +workingset_refault 302914 +workingset_activate 108959 +workingset_nodereclaim 6422 +nr_anon_pages 26218 +nr_mapped 8641 +nr_file_pages 126182 +nr_dirty 7 +nr_writeback 0 +nr_writeback_temp 0 +nr_shmem 169 +nr_shmem_hugepages 0 +nr_shmem_pmdmapped 0 +nr_anon_transparent_hugepages 0 +nr_unstable 0 +nr_vmscan_write 35 +nr_vmscan_immediate_reclaim 9832 +nr_dirtied 7188920 +nr_written 6479005 +nr_dirty_threshold 31736 +nr_dirty_background_threshold 15848 +pgpgin 17010697 +pgpgout 27734292 +pswpin 0 +pswpout 0 +pgalloc_dma 241378 +pgalloc_dma32 45788683 +pgalloc_normal 0 +pgalloc_movable 0 +allocstall_dma 0 +allocstall_dma32 0 +allocstall_normal 5 +allocstall_movable 8 +pgskip_dma 0 +pgskip_dma32 0 +pgskip_normal 0 +pgskip_movable 0 +pgfree 46085578 +pgactivate 2475069 +pgdeactivate 636658 +pglazyfree 9426 +pgfault 46777498 +pgmajfault 19204 +pglazyfreed 0 +pgrefill 707817 +pgsteal_kswapd 3798890 +pgsteal_direct 1466 +pgscan_kswapd 3868525 +pgscan_direct 1483 +pgscan_direct_throttle 0 +zone_reclaim_failed 0 +pginodesteal 1710 +slabs_scanned 8348560 +kswapd_inodesteal 3142001 +kswapd_low_wmark_hit_quickly 541 +kswapd_high_wmark_hit_quickly 332 +pageoutrun 1492 +pgrotated 29725 +drop_pagecache 0 +drop_slab 0 +oom_kill 0 +numa_pte_updates 0 +numa_huge_pte_updates 0 +numa_hint_faults 0 +numa_hint_faults_local 0 +numa_pages_migrated 0 +pgmigrate_success 4539 +pgmigrate_fail 156 +compact_migrate_scanned 9331 +compact_free_scanned 136266 +compact_isolated 9407 +compact_stall 2 +compact_fail 0 +compact_success 2 +compact_daemon_wake 21 +compact_daemon_migrate_scanned 8311 +compact_daemon_free_scanned 107086 +htlb_buddy_alloc_success 0 +htlb_buddy_alloc_fail 0 +unevictable_pgs_culled 19 +unevictable_pgs_scanned 0 +unevictable_pgs_rescued 304 +unevictable_pgs_mlocked 304 +unevictable_pgs_munlocked 304 +unevictable_pgs_cleared 0 +unevictable_pgs_stranded 0 +thp_fault_alloc 2 +thp_fault_fallback 0 +thp_collapse_alloc 2 +thp_collapse_alloc_failed 0 +thp_file_alloc 0 +thp_file_mapped 0 +thp_split_page 0 +thp_split_page_failed 0 +thp_deferred_split_page 4 +thp_split_pmd 1 +thp_split_pud 0 +thp_zero_page_alloc 0 +thp_zero_page_alloc_failed 0 +thp_swpout 0 +thp_swpout_fallback 0 +balloon_inflate 0 +balloon_deflate 0 +balloon_migrate 0 +swap_ra 0 +swap_ra_hit 0 +` + +func TestVmStatParse(t *testing.T) { + data, err := parseVMStat([]byte(rawInput)) + if err != nil { + t.Fatal(err) + } + // Check a few values + assert.Equal(t, uint64(8348560), data.SlabsScanned) + assert.Equal(t, uint64(0), data.SwapRa) + assert.Equal(t, uint64(108959), data.WorkingsetActivate) +} diff --git a/system_test.go b/system_test.go index 62b4ab29..5daabb01 100644 --- a/system_test.go +++ b/system_test.go @@ -290,5 +290,4 @@ func TestProcesses(t *testing.T) { info.PID, info.Name, info.Exe, info.Args, info.PPID, info.CWD, info.StartTime) } - } diff --git a/types/host.go b/types/host.go index 198dac1c..bf5b80cd 100644 --- a/types/host.go +++ b/types/host.go @@ -26,7 +26,12 @@ type Host interface { Memory() (*HostMemoryInfo, error) } -// HostInfo contains basic host information +// VMStat is the interface wrapper for platforms that support /proc/vmstat. +type VMStat interface { + VMStat() (*VMStatInfo, error) +} + +// HostInfo contains basic host information. type HostInfo struct { Architecture string `json:"architecture"` // Hardware architecture (e.g. x86_64, arm, ppc, mips). BootTime time.Time `json:"boot_time"` // Host boot time. @@ -83,3 +88,181 @@ type HostMemoryInfo struct { VirtualFree uint64 `json:"virtual_free_bytes"` // Virtual memory that is not used. Metrics map[string]uint64 `json:"raw,omitempty"` // Other memory related metrics. } + +// VMStatInfo contains parsed info from /proc/vmstat. +// This procfs file has expanded much over the years +// with different kernel versions. If we don't have a field in vmstat, +// the field in the struct will just be blank. The comments represent kernel versions. +type VMStatInfo struct { + NrFreePages uint64 `json:"nr_free_pages"` // (since Linux 2.6.31) + NrAllocBatch uint64 `json:"nr_alloc_batch"` // (since Linux 3.12) + NrInactiveAnon uint64 `json:"nr_inactive_anon"` // (since Linux 2.6.28) + NrActiveAnon uint64 `json:"nr_active_anon"` // (since Linux 2.6.28) + NrInactiveFile uint64 `json:"nr_inactive_file"` // (since Linux 2.6.28) + NrActiveFile uint64 `json:"nr_active_file"` // (since Linux 2.6.28) + NrUnevictable uint64 `json:"nr_unevictable"` // (since Linux 2.6.28) + NrMlock uint64 `json:"nr_mlock"` // (since Linux 2.6.28) + NrAnonPages uint64 `json:"nr_anon_pages"` // (since Linux 2.6.18) + NrMapped uint64 `json:"nr_mapped"` // (since Linux 2.6.0) + NrFilePages uint64 `json:"nr_file_pages"` // (since Linux 2.6.18) + NrDirty uint64 `json:"nr_dirty"` // (since Linux 2.6.0) + NrWriteback uint64 `json:"nr_writeback"` // (since Linux 2.6.0) + NrSlabReclaimable uint64 `json:"nr_slab_reclaimable"` // (since Linux 2.6.19) + NrSlabUnreclaimable uint64 `json:"nr_slab_unreclaimable"` // (since Linux 2.6.19) + NrPageTablePages uint64 `json:"nr_page_table_pages"` // (since Linux 2.6.0) + NrKernelStack uint64 `json:"nr_kernel_stack"` // (since Linux 2.6.32) Amount of memory allocated to kernel stacks. + NrUnstable uint64 `json:"nr_unstable"` // (since Linux 2.6.0) + NrBounce uint64 `json:"nr_bounce"` // (since Linux 2.6.12) + NrVmscanWrite uint64 `json:"nr_vmscan_write"` // (since Linux 2.6.19) + NrVmscanImmediateReclaim uint64 `json:"nr_vmscan_immediate_reclaim"` // (since Linux 3.2) + NrWritebackTemp uint64 `json:"nr_writeback_temp"` // (since Linux 2.6.26) + NrIsolatedAnon uint64 `json:"nr_isolated_anon"` // (since Linux 2.6.32) + NrIsolatedFile uint64 `json:"nr_isolated_file"` // (since Linux 2.6.32) + NrShmem uint64 `json:"nr_shmem"` // (since Linux 2.6.32) Pages used by shmem and tmpfs(5). + NrDirtied uint64 `json:"nr_dirtied"` // (since Linux 2.6.37) + NrWritten uint64 `json:"nr_written"` // (since Linux 2.6.37) + NrPagesScanned uint64 `json:"nr_pages_scanned"` // (since Linux 3.17) + NumaHit uint64 `json:"numa_hit"` // (since Linux 2.6.18) + NumaMiss uint64 `json:"numa_miss"` // (since Linux 2.6.18) + NumaForeign uint64 `json:"numa_foreign"` // (since Linux 2.6.18) + NumaInterleave uint64 `json:"numa_interleave"` // (since Linux 2.6.18) + NumaLocal uint64 `json:"numa_local"` // (since Linux 2.6.18) + NumaOther uint64 `json:"numa_other"` // (since Linux 2.6.18) + WorkingsetRefault uint64 `json:"workingset_refault"` // (since Linux 3.15) + WorkingsetActivate uint64 `json:"workingset_activate"` // (since Linux 3.15) + WorkingsetNodereclaim uint64 `json:"workingset_nodereclaim"` // (since Linux 3.15) + NrAnonTransparentHugepages uint64 `json:"nr_anon_transparent_hugepages"` // (since Linux 2.6.38) + NrFreeCma uint64 `json:"nr_free_cma"` // (since Linux 3.7) Number of free CMA (Contiguous Memory Allocator) pages. + NrDirtyThreshold uint64 `json:"nr_dirty_threshold"` // (since Linux 2.6.37) + NrDirtyBackgroundThreshold uint64 `json:"nr_dirty_background_threshold"` // (since Linux 2.6.37) + Pgpgin uint64 `json:"pgpgin"` // (since Linux 2.6.0) + Pgpgout uint64 `json:"pgpgout"` // (since Linux 2.6.0) + Pswpin uint64 `json:"pswpin"` // (since Linux 2.6.0) + Pswpout uint64 `json:"pswpout"` // (since Linux 2.6.0) + PgallocDma uint64 `json:"pgalloc_dma"` // (since Linux 2.6.5) + PgallocDma32 uint64 `json:"pgalloc_dma32"` // (since Linux 2.6.16) + PgallocNormal uint64 `json:"pgalloc_normal"` // (since Linux 2.6.5) + PgallocHigh uint64 `json:"pgalloc_high"` // (since Linux 2.6.5) + PgallocMovable uint64 `json:"pgalloc_movable"` // (since Linux 2.6.23) + Pgfree uint64 `json:"pgfree"` // (since Linux 2.6.0) + Pgactivate uint64 `json:"pgactivate"` // (since Linux 2.6.0) + Pgdeactivate uint64 `json:"pgdeactivate"` // (since Linux 2.6.0) + Pgfault uint64 `json:"pgfault"` // (since Linux 2.6.0) + Pgmajfault uint64 `json:"pgmajfault"` // (since Linux 2.6.0) + PgrefillDma uint64 `json:"pgrefill_dma"` // (since Linux 2.6.5) + PgrefillDma32 uint64 `json:"pgrefill_dma32"` // (since Linux 2.6.16) + PgrefillNormal uint64 `json:"pgrefill_normal"` // (since Linux 2.6.5) + PgrefillHigh uint64 `json:"pgrefill_high"` // (since Linux 2.6.5) + PgrefillMovable uint64 `json:"pgrefill_movable"` // (since Linux 2.6.23) + PgstealKswapdDma uint64 `json:"pgsteal_kswapd_dma"` // (since Linux 3.4) + PgstealKswapdDma32 uint64 `json:"pgsteal_kswapd_dma32"` // (since Linux 3.4) + PgstealKswapdNormal uint64 `json:"pgsteal_kswapd_normal"` // (since Linux 3.4) + PgstealKswapdHigh uint64 `json:"pgsteal_kswapd_high"` // (since Linux 3.4) + PgstealKswapdMovable uint64 `json:"pgsteal_kswapd_movable"` // (since Linux 3.4) + PgstealDirectDma uint64 `json:"pgsteal_direct_dma"` + PgstealDirectDma32 uint64 `json:"pgsteal_direct_dma32"` // (since Linux 3.4) + PgstealDirectNormal uint64 `json:"pgsteal_direct_normal"` // (since Linux 3.4) + PgstealDirectHigh uint64 `json:"pgsteal_direct_high"` // (since Linux 3.4) + PgstealDirectMovable uint64 `json:"pgsteal_direct_movable"` // (since Linux 2.6.23) + PgscanKswapdDma uint64 `json:"pgscan_kswapd_dma"` + PgscanKswapdDma32 uint64 `json:"pgscan_kswapd_dma32"` // (since Linux 2.6.16) + PgscanKswapdNormal uint64 `json:"pgscan_kswapd_normal"` // (since Linux 2.6.5) + PgscanKswapdHigh uint64 `json:"pgscan_kswapd_high"` + PgscanKswapdMovable uint64 `json:"pgscan_kswapd_movable"` // (since Linux 2.6.23) + PgscanDirectDma uint64 `json:"pgscan_direct_dma"` // + PgscanDirectDma32 uint64 `json:"pgscan_direct_dma32"` // (since Linux 2.6.16) + PgscanDirectNormal uint64 `json:"pgscan_direct_normal"` + PgscanDirectHigh uint64 `json:"pgscan_direct_high"` + PgscanDirectMovable uint64 `json:"pgscan_direct_movable"` // (since Linux 2.6.23) + PgscanDirectThrottle uint64 `json:"pgscan_direct_throttle"` // (since Linux 3.6) + ZoneReclaimFailed uint64 `json:"zone_reclaim_failed"` // (since linux 2.6.31) + Pginodesteal uint64 `json:"pginodesteal"` // (since linux 2.6.0) + SlabsScanned uint64 `json:"slabs_scanned"` // (since linux 2.6.5) + KswapdInodesteal uint64 `json:"kswapd_inodesteal"` // (since linux 2.6.0) + KswapdLowWmarkHitQuickly uint64 `json:"kswapd_low_wmark_hit_quickly"` // (since 2.6.33) + KswapdHighWmarkHitQuickly uint64 `json:"kswapd_high_wmark_hit_quickly"` // (since 2.6.33) + Pageoutrun uint64 `json:"pageoutrun"` // (since Linux 2.6.0) + Allocstall uint64 `json:"allocstall"` // (since Linux 2.6.0) + Pgrotated uint64 `json:"pgrotated"` // (since Linux 2.6.0) + DropPagecache uint64 `json:"drop_pagecache"` // (since Linux 3.15) + DropSlab uint64 `json:"drop_slab"` // (since Linux 3.15) + NumaPteUpdates uint64 `json:"numa_pte_updates"` // (since Linux 3.8) + NumaHugePteUpdates uint64 `json:"numa_huge_pte_updates"` // (since Linux 3.13) + NumaHintFaults uint64 `json:"numa_hint_faults"` // (since Linux 3.8) + NumaHintFaultsLocal uint64 `json:"numa_hint_faults_local"` // (since Linux 3.8) + NumaPagesMigrated uint64 `json:"numa_pages_migrated"` // (since Linux 3.8) + PgmigrateSuccess uint64 `json:"pgmigrate_success"` // (since Linux 3.8) + PgmigrateFail uint64 `json:"pgmigrate_fail"` // (since Linux 3.8) + CompactMigrateScanned uint64 `json:"compact_migrate_scanned"` // (since Linux 3.8) + CompactFreeScanned uint64 `json:"compact_free_scanned"` // (since Linux 3.8) + CompactIsolated uint64 `json:"compact_isolated"` // (since Linux 3.8) + CompactStall uint64 `json:"compact_stall"` // (since Linux 2.6.35) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + CompactFail uint64 `json:"compact_fail"` // (since Linux 2.6.35) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + CompactSuccess uint64 `json:"compact_success"` // (since Linux 2.6.35) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + HtlbBuddyAllocSuccess uint64 `json:"htlb_buddy_alloc_success"` // (since Linux 2.6.26) + HtlbBuddyAllocFail uint64 `json:"htlb_buddy_alloc_fail"` // (since Linux 2.6.26) + UnevictablePgsCulled uint64 `json:"unevictable_pgs_culled"` // (since Linux 2.6.28) + UnevictablePgsScanned uint64 `json:"unevictable_pgs_scanned"` // (since Linux 2.6.28) + UnevictablePgsRescued uint64 `json:"unevictable_pgs_rescued"` // (since Linux 2.6.28) + UnevictablePgsMlocked uint64 `json:"unevictable_pgs_mlocked"` // (since Linux 2.6.28) + UnevictablePgsMunlocked uint64 `json:"unevictable_pgs_munlocked"` // (since Linux 2.6.28) + UnevictablePgsCleared uint64 `json:"unevictable_pgs_cleared"` // (since Linux 2.6.28) + UnevictablePgsStranded uint64 `json:"unevictable_pgs_stranded"` // (since Linux 2.6.28) + ThpFaultAlloc uint64 `json:"thp_fault_alloc"` // (since Linux 2.6.39) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + ThpFaultFallback uint64 `json:"thp_fault_fallback"` // (since Linux 2.6.39) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + ThpCollapseAlloc uint64 `json:"thp_collapse_alloc"` // (since Linux 2.6.39) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + ThpCollapseAllocFailed uint64 `json:"thp_collapse_alloc_failed"` // (since Linux 2.6.39) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + ThpSplit uint64 `json:"thp_split"` // (since Linux 2.6.39) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + ThpZeroPageAlloc uint64 `json:"thp_zero_page_alloc"` // (since Linux 3.8) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + ThpZeroPageAllocFailed uint64 `json:"thp_zero_page_alloc_failed"` // (since Linux 3.8) See the kernel source file Documentation/admin-guide/mm/transhuge.rst. + BalloonInflate uint64 `json:"balloon_inflate"` // (since Linux 3.18) + BalloonDeflate uint64 `json:"balloon_deflate"` // (since Linux 3.18) + BalloonMigrate uint64 `json:"balloon_migrate"` // (since Linux 3.18) + NrTlbRemoteFlush uint64 `json:"nr_tlb_remote_flush"` // (since Linux 3.12) + NrTlbRemoteFlushReceived uint64 `json:"nr_tlb_remote_flush_received"` // (since Linux 3.12) + NrTlbLocalFlushAll uint64 `json:"nr_tlb_local_flush_all"` // (since Linux 3.12) + NrTlbLocalFlushOne uint64 `json:"nr_tlb_local_flush_one"` // (since Linux 3.12) + VmacacheFindCalls uint64 `json:"vmacache_find_calls"` // (since Linux 3.16) + VmacacheFindHits uint64 `json:"vmacache_find_hits"` // (since Linux 3.16) + VmacacheFullFlushes uint64 `json:"vmacache_full_flushes"` // (since Linux 3.19) + // the following fields are not documented in `man 5 proc` as of 4.15 + NrZoneInactiveAnon uint64 `json:"nr_zone_inactive_anon"` + NrZoneActiveAnon uint64 `json:"nr_zone_active_anon"` + NrZoneInactiveFile uint64 `json:"nr_zone_inactive_file"` + NrZoneActiveFile uint64 `json:"nr_zone_active_file"` + NrZoneUnevictable uint64 `json:"nr_zone_unevictable"` + NrZoneWritePending uint64 `json:"nr_zone_write_pending"` + NrZspages uint64 `json:"nr_zspages"` + NrShmemHugepages uint64 `json:"nr_shmem_hugepages"` + NrShmemPmdmapped uint64 `json:"nr_shmem_pmdmapped"` + AllocstallDma uint64 `json:"allocstall_dma"` + AllocstallDma32 uint64 `json:"allocstall_dma32"` + AllocstallNormal uint64 `json:"allocstall_normal"` + AllocstallMovable uint64 `json:"allocstall_movable"` + PgskipDma uint64 `json:"pgskip_dma"` + PgskipDma32 uint64 `json:"pgskip_dma32"` + PgskipNormal uint64 `json:"pgskip_normal"` + PgskipMovable uint64 `json:"pgskip_movable"` + Pglazyfree uint64 `json:"pglazyfree"` + Pglazyfreed uint64 `json:"pglazyfreed"` + Pgrefill uint64 `json:"pgrefill"` + PgstealKswapd uint64 `json:"pgsteal_kswapd"` + PgstealDirect uint64 `json:"pgsteal_direct"` + PgscanKswapd uint64 `json:"pgscan_kswapd"` + PgscanDirect uint64 `json:"pgscan_direct"` + OomKill uint64 `json:"oom_kill"` + CompactDaemonWake uint64 `json:"compact_daemon_wake"` + CompactDaemonMigrateScanned uint64 `json:"compact_daemon_migrate_scanned"` + CompactDaemonFreeScanned uint64 `json:"compact_daemon_free_scanned"` + ThpFileAlloc uint64 `json:"thp_file_alloc"` + ThpFileMapped uint64 `json:"thp_file_mapped"` + ThpSplitPage uint64 `json:"thp_split_page"` + ThpSplitPageFailed uint64 `json:"thp_split_page_failed"` + ThpDeferredSplitPage uint64 `json:"thp_deferred_split_page"` + ThpSplitPmd uint64 `json:"thp_split_pmd"` + ThpSplitPud uint64 `json:"thp_split_pud"` + ThpSwpout uint64 `json:"thp_swpout"` + ThpSwpoutFallback uint64 `json:"thp_swpout_fallback"` + SwapRa uint64 `json:"swap_ra"` + SwapRaHit uint64 `json:"swap_ra_hit"` +}