From 87579e0947542b3e8522ca2f77d2f221a2226797 Mon Sep 17 00:00:00 2001 From: "Wisniewski, Krzysztof2" Date: Wed, 30 Sep 2020 13:48:23 +0200 Subject: [PATCH] Add zoneinfo collector Signed-off-by: Wisniewski, Krzysztof2 --- README.md | 2 +- collector/fixtures/e2e-output.txt | 319 ++++++++++++++++++++++++++++++ collector/fixtures/proc/zoneinfo | 265 +++++++++++++++++++++++++ collector/zoneinfo_linux.go | 301 ++++++++++++++++++++++++++++ collector/zoneinfo_linux_test.go | 83 ++++++++ end-to-end-test.sh | 2 + 6 files changed, 971 insertions(+), 1 deletion(-) create mode 100644 collector/fixtures/proc/zoneinfo create mode 100644 collector/zoneinfo_linux.go create mode 100644 collector/zoneinfo_linux_test.go diff --git a/README.md b/README.md index 17a4b1fd6f..bc755c5f6a 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ systemd | Exposes service and system status from [systemd](http://www.freedeskto tcpstat | Exposes TCP connection status information from `/proc/net/tcp` and `/proc/net/tcp6`. (Warning: the current version has potential performance issues in high load situations.) | Linux wifi | Exposes WiFi device and station statistics. | Linux perf | Exposes perf based metrics (Warning: Metrics are dependent on kernel configuration and settings). | Linux - +zoneinfo | Exposes zone statistics from `proc/zoneinfo`. |Linux ### Textfile Collector The textfile collector is similar to the [Pushgateway](https://github.com/prometheus/pushgateway), diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index ef501f048d..1d3ded72e2 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -2687,6 +2687,7 @@ node_scrape_collector_success{collector="vmstat"} 1 node_scrape_collector_success{collector="wifi"} 1 node_scrape_collector_success{collector="xfs"} 1 node_scrape_collector_success{collector="zfs"} 1 +node_scrape_collector_success{collector="zoneinfo"} 1 # HELP node_sockstat_FRAG6_inuse Number of FRAG6 sockets in state inuse. # TYPE node_sockstat_FRAG6_inuse gauge node_sockstat_FRAG6_inuse 0 @@ -3799,6 +3800,324 @@ node_zfs_zpool_wtime{zpool="poolz1"} 9.673715628e+09 # TYPE node_zfs_zpool_wupdate untyped node_zfs_zpool_wupdate{zpool="pool1"} 7.9210489694949e+13 node_zfs_zpool_wupdate{zpool="poolz1"} 1.10734831833266e+14 +# HELP node_zoneinfo_node_unreclaimable Zone information field node_unreclaimable. +# TYPE node_zoneinfo_node_unreclaimable untyped +node_zoneinfo_node_unreclaimable{node="0",zone="DMA"} 0 +node_zoneinfo_node_unreclaimable{node="0",zone="DMA32"} 0 +node_zoneinfo_node_unreclaimable{node="0",zone="Device"} 0 +node_zoneinfo_node_unreclaimable{node="0",zone="Movable"} 0 +node_zoneinfo_node_unreclaimable{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_nr_active_anon Zone information field nr_active_anon. +# TYPE node_zoneinfo_nr_active_anon untyped +node_zoneinfo_nr_active_anon{node="0",zone="DMA"} 1.175853e+06 +# HELP node_zoneinfo_nr_active_file Zone information field nr_active_file. +# TYPE node_zoneinfo_nr_active_file untyped +node_zoneinfo_nr_active_file{node="0",zone="DMA"} 688810 +# HELP node_zoneinfo_nr_anon_pages Zone information field nr_anon_pages. +# TYPE node_zoneinfo_nr_anon_pages untyped +node_zoneinfo_nr_anon_pages{node="0",zone="DMA"} 1.156608e+06 +# HELP node_zoneinfo_nr_anon_transparent_hugepages Zone information field nr_anon_transparent_hugepages. +# TYPE node_zoneinfo_nr_anon_transparent_hugepages untyped +node_zoneinfo_nr_anon_transparent_hugepages{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_bounce Zone information field nr_bounce. +# TYPE node_zoneinfo_nr_bounce untyped +node_zoneinfo_nr_bounce{node="0",zone="DMA"} 0 +node_zoneinfo_nr_bounce{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_bounce{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_nr_dirtied Zone information field nr_dirtied. +# TYPE node_zoneinfo_nr_dirtied untyped +node_zoneinfo_nr_dirtied{node="0",zone="DMA"} 1.189097e+06 +# HELP node_zoneinfo_nr_dirty Zone information field nr_dirty. +# TYPE node_zoneinfo_nr_dirty untyped +node_zoneinfo_nr_dirty{node="0",zone="DMA"} 103 +# HELP node_zoneinfo_nr_file_hugepages Zone information field nr_file_hugepages. +# TYPE node_zoneinfo_nr_file_hugepages untyped +node_zoneinfo_nr_file_hugepages{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_file_pages Zone information field nr_file_pages. +# TYPE node_zoneinfo_nr_file_pages untyped +node_zoneinfo_nr_file_pages{node="0",zone="DMA"} 1.740118e+06 +# HELP node_zoneinfo_nr_file_pmdmapped Zone information field nr_file_pmdmapped. +# TYPE node_zoneinfo_nr_file_pmdmapped untyped +node_zoneinfo_nr_file_pmdmapped{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_foll_pin_acquired Zone information field nr_foll_pin_acquired. +# TYPE node_zoneinfo_nr_foll_pin_acquired untyped +node_zoneinfo_nr_foll_pin_acquired{node="0",zone="DMA"} 3 +# HELP node_zoneinfo_nr_foll_pin_released Zone information field nr_foll_pin_released. +# TYPE node_zoneinfo_nr_foll_pin_released untyped +node_zoneinfo_nr_foll_pin_released{node="0",zone="DMA"} 3 +# HELP node_zoneinfo_nr_free_cma Zone information field nr_free_cma. +# TYPE node_zoneinfo_nr_free_cma untyped +node_zoneinfo_nr_free_cma{node="0",zone="DMA"} 0 +node_zoneinfo_nr_free_cma{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_free_cma{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_nr_free_pages Zone information field nr_free_pages. +# TYPE node_zoneinfo_nr_free_pages untyped +node_zoneinfo_nr_free_pages{node="0",zone="DMA"} 2949 +node_zoneinfo_nr_free_pages{node="0",zone="DMA32"} 528427 +node_zoneinfo_nr_free_pages{node="0",zone="Normal"} 4.539739e+06 +# HELP node_zoneinfo_nr_inactive_anon Zone information field nr_inactive_anon. +# TYPE node_zoneinfo_nr_inactive_anon untyped +node_zoneinfo_nr_inactive_anon{node="0",zone="DMA"} 95612 +# HELP node_zoneinfo_nr_inactive_file Zone information field nr_inactive_file. +# TYPE node_zoneinfo_nr_inactive_file untyped +node_zoneinfo_nr_inactive_file{node="0",zone="DMA"} 723339 +# HELP node_zoneinfo_nr_isolated_anon Zone information field nr_isolated_anon. +# TYPE node_zoneinfo_nr_isolated_anon untyped +node_zoneinfo_nr_isolated_anon{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_isolated_file Zone information field nr_isolated_file. +# TYPE node_zoneinfo_nr_isolated_file untyped +node_zoneinfo_nr_isolated_file{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_kernel_misc_reclaimable Zone information field nr_kernel_misc_reclaimable. +# TYPE node_zoneinfo_nr_kernel_misc_reclaimable untyped +node_zoneinfo_nr_kernel_misc_reclaimable{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_kernel_stack Zone information field nr_kernel_stack. +# TYPE node_zoneinfo_nr_kernel_stack untyped +node_zoneinfo_nr_kernel_stack{node="0",zone="DMA"} 0 +node_zoneinfo_nr_kernel_stack{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_kernel_stack{node="0",zone="Normal"} 18864 +# HELP node_zoneinfo_nr_mapped Zone information field nr_mapped. +# TYPE node_zoneinfo_nr_mapped untyped +node_zoneinfo_nr_mapped{node="0",zone="DMA"} 423143 +# HELP node_zoneinfo_nr_mlock Zone information field nr_mlock. +# TYPE node_zoneinfo_nr_mlock untyped +node_zoneinfo_nr_mlock{node="0",zone="DMA"} 0 +node_zoneinfo_nr_mlock{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_mlock{node="0",zone="Normal"} 12 +# HELP node_zoneinfo_nr_page_table_pages Zone information field nr_page_table_pages. +# TYPE node_zoneinfo_nr_page_table_pages untyped +node_zoneinfo_nr_page_table_pages{node="0",zone="DMA"} 0 +node_zoneinfo_nr_page_table_pages{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_page_table_pages{node="0",zone="Normal"} 13921 +# HELP node_zoneinfo_nr_shmem Zone information field nr_shmem. +# TYPE node_zoneinfo_nr_shmem untyped +node_zoneinfo_nr_shmem{node="0",zone="DMA"} 330517 +# HELP node_zoneinfo_nr_shmem_hugepages Zone information field nr_shmem_hugepages. +# TYPE node_zoneinfo_nr_shmem_hugepages untyped +node_zoneinfo_nr_shmem_hugepages{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_shmem_pmdmapped Zone information field nr_shmem_pmdmapped. +# TYPE node_zoneinfo_nr_shmem_pmdmapped untyped +node_zoneinfo_nr_shmem_pmdmapped{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_slab_reclaimable Zone information field nr_slab_reclaimable. +# TYPE node_zoneinfo_nr_slab_reclaimable untyped +node_zoneinfo_nr_slab_reclaimable{node="0",zone="DMA"} 121763 +# HELP node_zoneinfo_nr_slab_unreclaimable Zone information field nr_slab_unreclaimable. +# TYPE node_zoneinfo_nr_slab_unreclaimable untyped +node_zoneinfo_nr_slab_unreclaimable{node="0",zone="DMA"} 56182 +# HELP node_zoneinfo_nr_unevictable Zone information field nr_unevictable. +# TYPE node_zoneinfo_nr_unevictable untyped +node_zoneinfo_nr_unevictable{node="0",zone="DMA"} 213111 +# HELP node_zoneinfo_nr_vmscan_immediate_reclaim Zone information field nr_vmscan_immediate_reclaim. +# TYPE node_zoneinfo_nr_vmscan_immediate_reclaim untyped +node_zoneinfo_nr_vmscan_immediate_reclaim{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_vmscan_write Zone information field nr_vmscan_write. +# TYPE node_zoneinfo_nr_vmscan_write untyped +node_zoneinfo_nr_vmscan_write{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_writeback Zone information field nr_writeback. +# TYPE node_zoneinfo_nr_writeback untyped +node_zoneinfo_nr_writeback{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_writeback_temp Zone information field nr_writeback_temp. +# TYPE node_zoneinfo_nr_writeback_temp untyped +node_zoneinfo_nr_writeback_temp{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_nr_written Zone information field nr_written. +# TYPE node_zoneinfo_nr_written untyped +node_zoneinfo_nr_written{node="0",zone="DMA"} 1.181554e+06 +# HELP node_zoneinfo_nr_zone_active_anon Zone information field nr_zone_active_anon. +# TYPE node_zoneinfo_nr_zone_active_anon untyped +node_zoneinfo_nr_zone_active_anon{node="0",zone="DMA"} 0 +node_zoneinfo_nr_zone_active_anon{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_zone_active_anon{node="0",zone="Normal"} 1.175853e+06 +# HELP node_zoneinfo_nr_zone_active_file Zone information field nr_zone_active_file. +# TYPE node_zoneinfo_nr_zone_active_file untyped +node_zoneinfo_nr_zone_active_file{node="0",zone="DMA"} 0 +node_zoneinfo_nr_zone_active_file{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_zone_active_file{node="0",zone="Normal"} 688810 +# HELP node_zoneinfo_nr_zone_inactive_anon Zone information field nr_zone_inactive_anon. +# TYPE node_zoneinfo_nr_zone_inactive_anon untyped +node_zoneinfo_nr_zone_inactive_anon{node="0",zone="DMA"} 0 +node_zoneinfo_nr_zone_inactive_anon{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_zone_inactive_anon{node="0",zone="Normal"} 95612 +# HELP node_zoneinfo_nr_zone_inactive_file Zone information field nr_zone_inactive_file. +# TYPE node_zoneinfo_nr_zone_inactive_file untyped +node_zoneinfo_nr_zone_inactive_file{node="0",zone="DMA"} 0 +node_zoneinfo_nr_zone_inactive_file{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_zone_inactive_file{node="0",zone="Normal"} 723339 +# HELP node_zoneinfo_nr_zone_unevictable Zone information field nr_zone_unevictable. +# TYPE node_zoneinfo_nr_zone_unevictable untyped +node_zoneinfo_nr_zone_unevictable{node="0",zone="DMA"} 0 +node_zoneinfo_nr_zone_unevictable{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_zone_unevictable{node="0",zone="Normal"} 213111 +# HELP node_zoneinfo_nr_zone_write_pending Zone information field nr_zone_write_pending. +# TYPE node_zoneinfo_nr_zone_write_pending untyped +node_zoneinfo_nr_zone_write_pending{node="0",zone="DMA"} 0 +node_zoneinfo_nr_zone_write_pending{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_zone_write_pending{node="0",zone="Normal"} 103 +# HELP node_zoneinfo_nr_zspages Zone information field nr_zspages. +# TYPE node_zoneinfo_nr_zspages untyped +node_zoneinfo_nr_zspages{node="0",zone="DMA"} 0 +node_zoneinfo_nr_zspages{node="0",zone="DMA32"} 0 +node_zoneinfo_nr_zspages{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_numa_foreign Zone information field numa_foreign. +# TYPE node_zoneinfo_numa_foreign untyped +node_zoneinfo_numa_foreign{node="0",zone="DMA"} 0 +node_zoneinfo_numa_foreign{node="0",zone="DMA32"} 0 +node_zoneinfo_numa_foreign{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_numa_hit Zone information field numa_hit. +# TYPE node_zoneinfo_numa_hit untyped +node_zoneinfo_numa_hit{node="0",zone="DMA"} 1 +node_zoneinfo_numa_hit{node="0",zone="DMA32"} 13 +node_zoneinfo_numa_hit{node="0",zone="Normal"} 6.2836441e+07 +# HELP node_zoneinfo_numa_interleave Zone information field numa_interleave. +# TYPE node_zoneinfo_numa_interleave untyped +node_zoneinfo_numa_interleave{node="0",zone="DMA"} 1 +node_zoneinfo_numa_interleave{node="0",zone="DMA32"} 1 +node_zoneinfo_numa_interleave{node="0",zone="Normal"} 23174 +# HELP node_zoneinfo_numa_local Zone information field numa_local. +# TYPE node_zoneinfo_numa_local untyped +node_zoneinfo_numa_local{node="0",zone="DMA"} 1 +node_zoneinfo_numa_local{node="0",zone="DMA32"} 13 +node_zoneinfo_numa_local{node="0",zone="Normal"} 6.2836441e+07 +# HELP node_zoneinfo_numa_miss Zone information field numa_miss. +# TYPE node_zoneinfo_numa_miss untyped +node_zoneinfo_numa_miss{node="0",zone="DMA"} 0 +node_zoneinfo_numa_miss{node="0",zone="DMA32"} 0 +node_zoneinfo_numa_miss{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_numa_other Zone information field numa_other. +# TYPE node_zoneinfo_numa_other untyped +node_zoneinfo_numa_other{node="0",zone="DMA"} 0 +node_zoneinfo_numa_other{node="0",zone="DMA32"} 0 +node_zoneinfo_numa_other{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_page_free Zone information field page_free. +# TYPE node_zoneinfo_page_free untyped +node_zoneinfo_page_free{node="0",zone="DMA"} 2949 +node_zoneinfo_page_free{node="0",zone="DMA32"} 528427 +node_zoneinfo_page_free{node="0",zone="Device"} 0 +node_zoneinfo_page_free{node="0",zone="Movable"} 0 +node_zoneinfo_page_free{node="0",zone="Normal"} 4.539739e+06 +# HELP node_zoneinfo_page_high Zone information field page_high. +# TYPE node_zoneinfo_page_high untyped +node_zoneinfo_page_high{node="0",zone="DMA"} 14 +node_zoneinfo_page_high{node="0",zone="DMA32"} 2122 +node_zoneinfo_page_high{node="0",zone="Device"} 0 +node_zoneinfo_page_high{node="0",zone="Movable"} 0 +node_zoneinfo_page_high{node="0",zone="Normal"} 31113 +# HELP node_zoneinfo_page_low Zone information field page_low. +# TYPE node_zoneinfo_page_low untyped +node_zoneinfo_page_low{node="0",zone="DMA"} 11 +node_zoneinfo_page_low{node="0",zone="DMA32"} 1600 +node_zoneinfo_page_low{node="0",zone="Device"} 0 +node_zoneinfo_page_low{node="0",zone="Movable"} 0 +node_zoneinfo_page_low{node="0",zone="Normal"} 23461 +# HELP node_zoneinfo_page_managed Zone information field page_managed. +# TYPE node_zoneinfo_page_managed untyped +node_zoneinfo_page_managed{node="0",zone="DMA"} 3973 +node_zoneinfo_page_managed{node="0",zone="DMA32"} 530339 +node_zoneinfo_page_managed{node="0",zone="Device"} 0 +node_zoneinfo_page_managed{node="0",zone="Movable"} 0 +node_zoneinfo_page_managed{node="0",zone="Normal"} 7.654794e+06 +# HELP node_zoneinfo_page_min Zone information field page_min. +# TYPE node_zoneinfo_page_min untyped +node_zoneinfo_page_min{node="0",zone="DMA"} 8 +node_zoneinfo_page_min{node="0",zone="DMA32"} 1078 +node_zoneinfo_page_min{node="0",zone="Device"} 0 +node_zoneinfo_page_min{node="0",zone="Movable"} 0 +node_zoneinfo_page_min{node="0",zone="Normal"} 15809 +# HELP node_zoneinfo_page_present Zone information field page_present. +# TYPE node_zoneinfo_page_present untyped +node_zoneinfo_page_present{node="0",zone="DMA"} 3997 +node_zoneinfo_page_present{node="0",zone="DMA32"} 546847 +node_zoneinfo_page_present{node="0",zone="Device"} 0 +node_zoneinfo_page_present{node="0",zone="Movable"} 0 +node_zoneinfo_page_present{node="0",zone="Normal"} 7.806976e+06 +# HELP node_zoneinfo_page_protection_0 Zone information field page_protection_0. +# TYPE node_zoneinfo_page_protection_0 untyped +node_zoneinfo_page_protection_0{node="0",zone="DMA"} 0 +node_zoneinfo_page_protection_0{node="0",zone="DMA32"} 0 +node_zoneinfo_page_protection_0{node="0",zone="Device"} 0 +node_zoneinfo_page_protection_0{node="0",zone="Movable"} 0 +node_zoneinfo_page_protection_0{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_page_protection_1 Zone information field page_protection_1. +# TYPE node_zoneinfo_page_protection_1 untyped +node_zoneinfo_page_protection_1{node="0",zone="DMA"} 2039 +node_zoneinfo_page_protection_1{node="0",zone="DMA32"} 0 +node_zoneinfo_page_protection_1{node="0",zone="Device"} 0 +node_zoneinfo_page_protection_1{node="0",zone="Movable"} 0 +node_zoneinfo_page_protection_1{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_page_protection_2 Zone information field page_protection_2. +# TYPE node_zoneinfo_page_protection_2 untyped +node_zoneinfo_page_protection_2{node="0",zone="DMA"} 31932 +node_zoneinfo_page_protection_2{node="0",zone="DMA32"} 29893 +node_zoneinfo_page_protection_2{node="0",zone="Device"} 0 +node_zoneinfo_page_protection_2{node="0",zone="Movable"} 0 +node_zoneinfo_page_protection_2{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_page_protection_3 Zone information field page_protection_3. +# TYPE node_zoneinfo_page_protection_3 untyped +node_zoneinfo_page_protection_3{node="0",zone="DMA"} 31932 +node_zoneinfo_page_protection_3{node="0",zone="DMA32"} 29893 +node_zoneinfo_page_protection_3{node="0",zone="Device"} 0 +node_zoneinfo_page_protection_3{node="0",zone="Movable"} 0 +node_zoneinfo_page_protection_3{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_page_protection_4 Zone information field page_protection_4. +# TYPE node_zoneinfo_page_protection_4 untyped +node_zoneinfo_page_protection_4{node="0",zone="DMA"} 31932 +node_zoneinfo_page_protection_4{node="0",zone="DMA32"} 29893 +node_zoneinfo_page_protection_4{node="0",zone="Device"} 0 +node_zoneinfo_page_protection_4{node="0",zone="Movable"} 0 +node_zoneinfo_page_protection_4{node="0",zone="Normal"} 0 +# HELP node_zoneinfo_page_spanned Zone information field page_spanned. +# TYPE node_zoneinfo_page_spanned untyped +node_zoneinfo_page_spanned{node="0",zone="DMA"} 4095 +node_zoneinfo_page_spanned{node="0",zone="DMA32"} 1.04448e+06 +node_zoneinfo_page_spanned{node="0",zone="Device"} 0 +node_zoneinfo_page_spanned{node="0",zone="Movable"} 0 +node_zoneinfo_page_spanned{node="0",zone="Normal"} 7.806976e+06 +# HELP node_zoneinfo_pageset Zone information field PageSet. +# TYPE node_zoneinfo_pageset untyped +node_zoneinfo_pageset{batch="1",cpu="0",high="0",node="0",vm_stat_threshold="8",zone="DMA"} 0 +node_zoneinfo_pageset{batch="1",cpu="1",high="0",node="0",vm_stat_threshold="8",zone="DMA"} 0 +node_zoneinfo_pageset{batch="1",cpu="2",high="0",node="0",vm_stat_threshold="8",zone="DMA"} 0 +node_zoneinfo_pageset{batch="1",cpu="3",high="0",node="0",vm_stat_threshold="8",zone="DMA"} 0 +node_zoneinfo_pageset{batch="1",cpu="4",high="0",node="0",vm_stat_threshold="8",zone="DMA"} 0 +node_zoneinfo_pageset{batch="1",cpu="5",high="0",node="0",vm_stat_threshold="8",zone="DMA"} 0 +node_zoneinfo_pageset{batch="1",cpu="6",high="0",node="0",vm_stat_threshold="8",zone="DMA"} 0 +node_zoneinfo_pageset{batch="1",cpu="7",high="0",node="0",vm_stat_threshold="8",zone="DMA"} 0 +node_zoneinfo_pageset{batch="63",cpu="0",high="378",node="0",vm_stat_threshold="48",zone="DMA32"} 357 +node_zoneinfo_pageset{batch="63",cpu="0",high="378",node="0",vm_stat_threshold="72",zone="Normal"} 351 +node_zoneinfo_pageset{batch="63",cpu="1",high="378",node="0",vm_stat_threshold="48",zone="DMA32"} 0 +node_zoneinfo_pageset{batch="63",cpu="1",high="378",node="0",vm_stat_threshold="72",zone="Normal"} 112 +node_zoneinfo_pageset{batch="63",cpu="2",high="378",node="0",vm_stat_threshold="48",zone="DMA32"} 338 +node_zoneinfo_pageset{batch="63",cpu="2",high="378",node="0",vm_stat_threshold="72",zone="Normal"} 368 +node_zoneinfo_pageset{batch="63",cpu="3",high="378",node="0",vm_stat_threshold="48",zone="DMA32"} 0 +node_zoneinfo_pageset{batch="63",cpu="3",high="378",node="0",vm_stat_threshold="72",zone="Normal"} 358 +node_zoneinfo_pageset{batch="63",cpu="4",high="378",node="0",vm_stat_threshold="48",zone="DMA32"} 62 +node_zoneinfo_pageset{batch="63",cpu="4",high="378",node="0",vm_stat_threshold="72",zone="Normal"} 304 +node_zoneinfo_pageset{batch="63",cpu="5",high="378",node="0",vm_stat_threshold="48",zone="DMA32"} 63 +node_zoneinfo_pageset{batch="63",cpu="5",high="378",node="0",vm_stat_threshold="72",zone="Normal"} 112 +node_zoneinfo_pageset{batch="63",cpu="6",high="378",node="0",vm_stat_threshold="48",zone="DMA32"} 0 +node_zoneinfo_pageset{batch="63",cpu="6",high="378",node="0",vm_stat_threshold="72",zone="Normal"} 488 +node_zoneinfo_pageset{batch="63",cpu="7",high="378",node="0",vm_stat_threshold="48",zone="DMA32"} 63 +node_zoneinfo_pageset{batch="63",cpu="7",high="378",node="0",vm_stat_threshold="72",zone="Normal"} 342 +# HELP node_zoneinfo_start_pfn Zone information field start_pfn. +# TYPE node_zoneinfo_start_pfn untyped +node_zoneinfo_start_pfn{node="0",zone="DMA"} 1 +node_zoneinfo_start_pfn{node="0",zone="DMA32"} 4096 +node_zoneinfo_start_pfn{node="0",zone="Device"} 0 +node_zoneinfo_start_pfn{node="0",zone="Movable"} 0 +node_zoneinfo_start_pfn{node="0",zone="Normal"} 1.048576e+06 +# HELP node_zoneinfo_workingset_activate Zone information field workingset_activate. +# TYPE node_zoneinfo_workingset_activate untyped +node_zoneinfo_workingset_activate{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_workingset_nodereclaim Zone information field workingset_nodereclaim. +# TYPE node_zoneinfo_workingset_nodereclaim untyped +node_zoneinfo_workingset_nodereclaim{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_workingset_nodes Zone information field workingset_nodes. +# TYPE node_zoneinfo_workingset_nodes untyped +node_zoneinfo_workingset_nodes{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_workingset_refault Zone information field workingset_refault. +# TYPE node_zoneinfo_workingset_refault untyped +node_zoneinfo_workingset_refault{node="0",zone="DMA"} 0 +# HELP node_zoneinfo_workingset_restore Zone information field workingset_restore. +# TYPE node_zoneinfo_workingset_restore untyped +node_zoneinfo_workingset_restore{node="0",zone="DMA"} 0 # HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. # TYPE process_cpu_seconds_total counter # HELP process_max_fds Maximum number of open file descriptors. diff --git a/collector/fixtures/proc/zoneinfo b/collector/fixtures/proc/zoneinfo new file mode 100644 index 0000000000..ef0ce903e8 --- /dev/null +++ b/collector/fixtures/proc/zoneinfo @@ -0,0 +1,265 @@ +Node 0, zone DMA + per-node stats + nr_inactive_anon 95612 + nr_active_anon 1175853 + nr_inactive_file 723339 + nr_active_file 688810 + nr_unevictable 213111 + nr_slab_reclaimable 121763 + nr_slab_unreclaimable 56182 + nr_isolated_anon 0 + nr_isolated_file 0 + workingset_nodes 0 + workingset_refault 0 + workingset_activate 0 + workingset_restore 0 + workingset_nodereclaim 0 + nr_anon_pages 1156608 + nr_mapped 423143 + nr_file_pages 1740118 + nr_dirty 103 + nr_writeback 0 + nr_writeback_temp 0 + nr_shmem 330517 + nr_shmem_hugepages 0 + nr_shmem_pmdmapped 0 + nr_file_hugepages 0 + nr_file_pmdmapped 0 + nr_anon_transparent_hugepages 0 + nr_vmscan_write 0 + nr_vmscan_immediate_reclaim 0 + nr_dirtied 1189097 + nr_written 1181554 + nr_kernel_misc_reclaimable 0 + nr_foll_pin_acquired 3 + nr_foll_pin_released 3 + pages free 2949 + min 8 + low 11 + high 14 + spanned 4095 + present 3997 + managed 3973 + protection: (0, 2039, 31932, 31932, 31932) + nr_free_pages 2949 + nr_zone_inactive_anon 0 + nr_zone_active_anon 0 + nr_zone_inactive_file 0 + nr_zone_active_file 0 + nr_zone_unevictable 0 + nr_zone_write_pending 0 + nr_mlock 0 + nr_page_table_pages 0 + nr_kernel_stack 0 + nr_bounce 0 + nr_zspages 0 + nr_free_cma 0 + numa_hit 1 + numa_miss 0 + numa_foreign 0 + numa_interleave 1 + numa_local 1 + numa_other 0 + pagesets + cpu: 0 + count: 0 + high: 0 + batch: 1 + vm stats threshold: 8 + cpu: 1 + count: 0 + high: 0 + batch: 1 + vm stats threshold: 8 + cpu: 2 + count: 0 + high: 0 + batch: 1 + vm stats threshold: 8 + cpu: 3 + count: 0 + high: 0 + batch: 1 + vm stats threshold: 8 + cpu: 4 + count: 0 + high: 0 + batch: 1 + vm stats threshold: 8 + cpu: 5 + count: 0 + high: 0 + batch: 1 + vm stats threshold: 8 + cpu: 6 + count: 0 + high: 0 + batch: 1 + vm stats threshold: 8 + cpu: 7 + count: 0 + high: 0 + batch: 1 + vm stats threshold: 8 + node_unreclaimable: 0 + start_pfn: 1 +Node 0, zone DMA32 + pages free 528427 + min 1078 + low 1600 + high 2122 + spanned 1044480 + present 546847 + managed 530339 + protection: (0, 0, 29893, 29893, 29893) + nr_free_pages 528427 + nr_zone_inactive_anon 0 + nr_zone_active_anon 0 + nr_zone_inactive_file 0 + nr_zone_active_file 0 + nr_zone_unevictable 0 + nr_zone_write_pending 0 + nr_mlock 0 + nr_page_table_pages 0 + nr_kernel_stack 0 + nr_bounce 0 + nr_zspages 0 + nr_free_cma 0 + numa_hit 13 + numa_miss 0 + numa_foreign 0 + numa_interleave 1 + numa_local 13 + numa_other 0 + pagesets + cpu: 0 + count: 357 + high: 378 + batch: 63 + vm stats threshold: 48 + cpu: 1 + count: 0 + high: 378 + batch: 63 + vm stats threshold: 48 + cpu: 2 + count: 338 + high: 378 + batch: 63 + vm stats threshold: 48 + cpu: 3 + count: 0 + high: 378 + batch: 63 + vm stats threshold: 48 + cpu: 4 + count: 62 + high: 378 + batch: 63 + vm stats threshold: 48 + cpu: 5 + count: 63 + high: 378 + batch: 63 + vm stats threshold: 48 + cpu: 6 + count: 0 + high: 378 + batch: 63 + vm stats threshold: 48 + cpu: 7 + count: 63 + high: 378 + batch: 63 + vm stats threshold: 48 + node_unreclaimable: 0 + start_pfn: 4096 +Node 0, zone Normal + pages free 4539739 + min 15809 + low 23461 + high 31113 + spanned 7806976 + present 7806976 + managed 7654794 + protection: (0, 0, 0, 0, 0) + nr_free_pages 4539739 + nr_zone_inactive_anon 95612 + nr_zone_active_anon 1175853 + nr_zone_inactive_file 723339 + nr_zone_active_file 688810 + nr_zone_unevictable 213111 + nr_zone_write_pending 103 + nr_mlock 12 + nr_page_table_pages 13921 + nr_kernel_stack 18864 + nr_bounce 0 + nr_zspages 0 + nr_free_cma 0 + numa_hit 62836441 + numa_miss 0 + numa_foreign 0 + numa_interleave 23174 + numa_local 62836441 + numa_other 0 + pagesets + cpu: 0 + count: 351 + high: 378 + batch: 63 + vm stats threshold: 72 + cpu: 1 + count: 112 + high: 378 + batch: 63 + vm stats threshold: 72 + cpu: 2 + count: 368 + high: 378 + batch: 63 + vm stats threshold: 72 + cpu: 3 + count: 358 + high: 378 + batch: 63 + vm stats threshold: 72 + cpu: 4 + count: 304 + high: 378 + batch: 63 + vm stats threshold: 72 + cpu: 5 + count: 112 + high: 378 + batch: 63 + vm stats threshold: 72 + cpu: 6 + count: 488 + high: 378 + batch: 63 + vm stats threshold: 72 + cpu: 7 + count: 342 + high: 378 + batch: 63 + vm stats threshold: 72 + node_unreclaimable: 0 + start_pfn: 1048576 +Node 0, zone Movable + pages free 0 + min 0 + low 0 + high 0 + spanned 0 + present 0 + managed 0 + protection: (0, 0, 0, 0, 0) +Node 0, zone Device + pages free 0 + min 0 + low 0 + high 0 + spanned 0 + present 0 + managed 0 + protection: (0, 0, 0, 0, 0) diff --git a/collector/zoneinfo_linux.go b/collector/zoneinfo_linux.go new file mode 100644 index 0000000000..0ced10d703 --- /dev/null +++ b/collector/zoneinfo_linux.go @@ -0,0 +1,301 @@ +// 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 !nozoneinfo + +package collector + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" + + "github.com/go-kit/kit/log/level" + "gopkg.in/alecthomas/kingpin.v2" + + "github.com/go-kit/kit/log" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + zoneinfoSubsystem = "zoneinfo" + badLengthErrorMessage = "cannot parse %s. Skipping" + convertionErrorMessage = "cannot parse %s: %v. Skipping" +) + +var ( + zoneinfoPath = kingpin.Flag("collector.zoneinfo.path", "path to zoneinfo").Default("/proc/zoneinfo").String() +) + +type zoneinfoCollector struct { + metricDescs map[string]*prometheus.Desc + logger log.Logger +} + +type Zone struct { + Node string + Zone string + PerNodeStats map[string]uint64 + Pages map[string]uint64 + PageSets []PageSet + NodeUnreclaimable uint64 + StartPfm uint64 +} + +type PageSet struct { + CPU uint64 + Count uint64 + High uint64 + Batch uint64 + VMStatThreshold uint64 +} + +func init() { + registerCollector("zoneinfo", defaultDisabled, NewZoneinfoCollector) +} + +// NewZoneinfoCollector returns a new Collector exposing zone info metrics. +func NewZoneinfoCollector(logger log.Logger) (Collector, error) { + return &zoneinfoCollector{ + metricDescs: map[string]*prometheus.Desc{}, + logger: logger, + }, nil +} + +func (c *zoneinfoCollector) Update(ch chan<- prometheus.Metric) error { + zones, err := getZoneInfo(c.logger) + if err != nil { + return fmt.Errorf("couldn't get zoneinfo: %v", err) + } + for _, zone := range zones { + for metric, value := range zone.PerNodeStats { + desc, ok := c.metricDescs[metric] + if !ok { + desc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, zoneinfoSubsystem, metric), + fmt.Sprintf("Zone information field %s.", metric), + []string{"node", "zone"}, nil) + c.metricDescs[metric] = desc + } + ch <- prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, float64(value), zone.Node, zone.Zone) + } + for metric, value := range zone.Pages { + metricName := "page_" + metric + desc, ok := c.metricDescs[metric] + if !ok { + desc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, zoneinfoSubsystem, metricName), + fmt.Sprintf("Zone information field %s.", metricName), + []string{"node", "zone"}, nil) + c.metricDescs[metricName] = desc + } + ch <- prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, float64(value), zone.Node, zone.Zone) + } + for _, pageSet := range zone.PageSets { + desc, ok := c.metricDescs["PageSet"] + if !ok { + desc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, zoneinfoSubsystem, "pageset"), + fmt.Sprintf("Zone information field %s.", "PageSet"), + []string{"node", "zone", "cpu", "high", "batch", "vm_stat_threshold"}, nil) + c.metricDescs["PageSet"] = desc + } + ch <- prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, float64(pageSet.Count), + zone.Node, zone.Zone, strconv.Itoa(int(pageSet.CPU)), strconv.Itoa(int(pageSet.High)), + strconv.Itoa(int(pageSet.Batch)), strconv.Itoa(int(pageSet.VMStatThreshold))) + } + metricName := "node_unreclaimable" + desc, ok := c.metricDescs[metricName] + if !ok { + desc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, zoneinfoSubsystem, metricName), + fmt.Sprintf("Zone information field %s.", metricName), + []string{"node", "zone"}, nil) + c.metricDescs[metricName] = desc + } + ch <- prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, float64(zone.NodeUnreclaimable), zone.Node, zone.Zone) + + metricName = "start_pfn" + desc, ok = c.metricDescs[metricName] + if !ok { + desc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, zoneinfoSubsystem, metricName), + fmt.Sprintf("Zone information field %s.", metricName), + []string{"node", "zone"}, nil) + c.metricDescs[metricName] = desc + } + ch <- prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, float64(zone.StartPfm), zone.Node, zone.Zone) + } + + return nil +} + +func getZoneInfo(logger log.Logger) ([]Zone, error) { + file, err := os.Open(*zoneinfoPath) + if err != nil { + return nil, err + } + scanner := bufio.NewScanner(file) + var ( + zones []Zone + zone Zone + lastPageSet PageSet + currentSection string + ) + for scanner.Scan() { + line := scanner.Text() + switch { + case strings.HasPrefix(line, "Node"): + splittedLine := strings.SplitN(line, ",", 2) + if len(splittedLine) != 2 { + return nil, fmt.Errorf(badLengthErrorMessage, line) + } + nodeNumber := strings.Fields(splittedLine[0])[1] + zoneName := strings.Fields(splittedLine[1])[1] + zones = append(zones, zone) + zone = Zone{ + Node: nodeNumber, + Zone: zoneName, + PerNodeStats: map[string]uint64{}, + Pages: map[string]uint64{}, + } + currentSection = "Node" + continue + + case strings.HasPrefix(line, " per-node stats"): + currentSection = "per-node stats" + continue + + case strings.HasPrefix(line, " pages "): + currentSection = "pages" + // This case will look like: `pages free ` where pages is section name and free is key + splittedLine := strings.Fields(line) + if len(splittedLine) != 3 { + level.Error(logger).Log("msg", fmt.Sprintf(badLengthErrorMessage, line)) + continue + } + value, err := strconv.Atoi(splittedLine[2]) + if err != nil { + level.Error(logger).Log("msg", fmt.Sprintf(convertionErrorMessage, line, err)) + continue + } + zone.Pages[splittedLine[1]] = uint64(value) + continue + + case strings.HasPrefix(line, " pagesets"): + currentSection = "pagesets" + continue + + case strings.HasPrefix(line, " node_unreclaimable:"): + _, value, err := parseLine(line, 2) + if err != nil { + level.Error(logger).Log("msg", err) + continue + } + zone.NodeUnreclaimable = uint64(value) + continue + + case strings.HasPrefix(line, " start_pfn:"): + _, value, err := parseLine(line, 2) + if err != nil { + level.Error(logger).Log("msg", err) + continue + } + zone.StartPfm = uint64(value) + continue + } + + switch currentSection { + case "per-node stats": + key, value, err := parseLine(line, 2) + if err != nil { + level.Error(logger).Log("msg", err) + continue + } + zone.PerNodeStats[key] = uint64(value) + + case "pages": + splittedLine := strings.Fields(line) + // special case, value is list instead of uint and after that it goes back to per-node stats section + if splittedLine[0] == "protection:" { + for i, value := range splittedLine[1:] { + intValue, err := strconv.Atoi(strings.Trim(value, "(),")) + if err != nil { + level.Error(logger).Log("msg", fmt.Sprintf(convertionErrorMessage, line, err)) + } + zone.Pages["protection_"+strconv.Itoa(i)] = uint64(intValue) + } + currentSection = "per-node stats" + continue + } + key, value, err := parseLine(line, 2) + if err != nil { + level.Error(logger).Log("msg", err) + continue + } + zone.Pages[key] = uint64(value) + case "pagesets": + // special case, stat name might have spaces in it + splittedLine := strings.Fields(line) + if len(splittedLine) > 1 { + if splittedLine[0] == "vm" && len(splittedLine) != 4 || splittedLine[0] != "vm" && len(splittedLine) != 2 { + level.Error(logger).Log("msg", fmt.Sprintf(badLengthErrorMessage, line)) + continue + } + } else { + level.Error(logger).Log("msg", fmt.Sprintf(badLengthErrorMessage, line)) + continue + } + value, err := strconv.Atoi(splittedLine[len(splittedLine)-1]) + if err != nil { + level.Error(logger).Log("msg", fmt.Sprintf(convertionErrorMessage, line, err)) + continue + } + switch splittedLine[0] { + case "cpu:": + lastPageSet = PageSet{ + CPU: uint64(value), + } + case "count:": + lastPageSet.Count = uint64(value) + + case "high:": + lastPageSet.High = uint64(value) + + case "batch:": + lastPageSet.Batch = uint64(value) + + case "vm": + lastPageSet.VMStatThreshold = uint64(value) + zone.PageSets = append(zone.PageSets, lastPageSet) + } + } + } + zones = append(zones, zone) + return zones[1:], nil +} + +func parseLine(line string, expectedLength int) (string, int, error) { + splittedLine := strings.Fields(line) + if len(splittedLine) != expectedLength { + return "", 0, fmt.Errorf(badLengthErrorMessage, line) + } + value, err := strconv.Atoi(splittedLine[expectedLength-1]) + if err != nil { + return "", 0, fmt.Errorf(convertionErrorMessage, line, err) + } + key := strings.Join(splittedLine[:expectedLength-1], "_") + return key, value, nil +} diff --git a/collector/zoneinfo_linux_test.go b/collector/zoneinfo_linux_test.go new file mode 100644 index 0000000000..3629eaec2e --- /dev/null +++ b/collector/zoneinfo_linux_test.go @@ -0,0 +1,83 @@ +// 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 ( + "fmt" + "testing" +) + +type Logger struct { + messages []string +} + +func (l Logger) Log(keyvals ...interface{}) error { + for _, value := range keyvals { + l.messages = append(l.messages, fmt.Sprintf("%s", value)) + } + return nil +} + +func TestParseLineSimple(t *testing.T) { + key, value, err := parseLine("some_metric 12", 2) + if err != nil { + t.Fatal(err) + } + if want, got := "some_metric", key; want != got { + t.Errorf("want %s, got %s", want, got) + } + if want, got := 12, value; want != got { + t.Errorf("want %d, got %d", want, got) + } +} + +func TestParseLine(t *testing.T) { + key, value, err := parseLine(" some multi word metric 15", 5) + if err != nil { + t.Fatal(err) + } + if want, got := "some_multi_word_metric", key; want != got { + t.Errorf("want %s, got %s", want, got) + } + if want, got := 15, value; want != got { + t.Errorf("want %d, got %d", want, got) + } +} + +func TestGetZoneInfo(t *testing.T) { + *zoneinfoPath = "fixtures/proc/zoneinfo" + logger := Logger{} + zones, err := getZoneInfo(logger) + if err != nil { + t.Fatal(err) + } + if want, got := 0, len(logger.messages); want != got { + t.Errorf("Logger has %d messages, wanted %d", got, want) + } + if want, got := 5, len(zones); want != got { + t.Errorf("got %d zones , wanted %d", got, want) + } + if want, got := uint64(95612), zones[0].PerNodeStats["nr_inactive_anon"]; want != got { + t.Errorf("got nr_inactive_anon %d , wanted %d", got, want) + } + if want, got := uint64(528427), zones[1].Pages["free"]; want != got { + t.Errorf("got pages free %d , wanted %d", got, want) + } + if want, got := uint64(357), zones[1].PageSets[0].Count; want != got { + t.Errorf("got pageset cpu 0 %d , wanted %d", got, want) + } + if want, got := 8, len(zones[1].PageSets); want != got { + t.Errorf("got pagesets %d , wanted %d", got, want) + } +} diff --git a/end-to-end-test.sh b/end-to-end-test.sh index 24060611b1..fa1dfacae4 100755 --- a/end-to-end-test.sh +++ b/end-to-end-test.sh @@ -44,6 +44,7 @@ enabled_collectors=$(cat << COLLECTORS xfs zfs processes + zoneinfo COLLECTORS ) disabled_collectors=$(cat << COLLECTORS @@ -105,6 +106,7 @@ fi --collector.textfile.directory="collector/fixtures/textfile/two_metric_files/" \ --collector.wifi.fixtures="collector/fixtures/wifi" \ --collector.qdisc.fixtures="collector/fixtures/qdisc/" \ + --collector.zoneinfo.path="collector/fixtures/proc/zoneinfo" \ --collector.netclass.ignored-devices="(bond0|dmz|int)" \ --collector.bcache.priorityStats \ --collector.cpu.info \