diff --git a/AUTHORS.md b/AUTHORS.md index bc6c4c16..030d6171 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -15,6 +15,8 @@ The following individuals have contributed code to this repository * Benjamin Staffin * Björn Rabenstein * Brian Brazil +* Christian Schwarz +* Corey Stewart * Daniel Speichert * Ed Schouten * Eric Ripa @@ -23,6 +25,7 @@ The following individuals have contributed code to this repository * Ian Hansen * Ilia Choly * Jari Takkala +* Joe Handzik * Johannes 'fish' Ziemke * Jonas Große Sundrup * Julius Volz diff --git a/README.md b/README.md index 7092a17c..ba0b74bb 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ stat | Exposes various statistics from `/proc/stat`. This includes CPU usage, bo textfile | Exposes statistics read from local disk. The `--collector.textfile.directory` flag must be set. | _any_ time | Exposes the current system time. | _any_ vmstat | Exposes statistics from `/proc/vmstat`. | Linux - +zfs | Exposes [ZFS](http://open-zfs.org/) performance statistics.
Linux (ARC) | [Linux](http://zfsonlinux.org/) ### Disabled by default diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index b1e65d5d..08a7e744 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -1934,6 +1934,279 @@ node_sockstat_sockets_used 229 # HELP node_textfile_scrape_error 1 if there was an error opening or reading a file, 0 otherwise # TYPE node_textfile_scrape_error gauge node_textfile_scrape_error 0 +# HELP node_zfsArc_anon_evictable_data kstat.zfs.misc.arcstats.anon_evictable_data +# TYPE node_zfsArc_anon_evictable_data untyped +node_zfsArc_anon_evictable_data 0 +# HELP node_zfsArc_anon_evictable_metadata kstat.zfs.misc.arcstats.anon_evictable_metadata +# TYPE node_zfsArc_anon_evictable_metadata untyped +node_zfsArc_anon_evictable_metadata 0 +# HELP node_zfsArc_anon_size kstat.zfs.misc.arcstats.anon_size +# TYPE node_zfsArc_anon_size untyped +node_zfsArc_anon_size 1.91744e+06 +# HELP node_zfsArc_arc_loaned_bytes kstat.zfs.misc.arcstats.arc_loaned_bytes +# TYPE node_zfsArc_arc_loaned_bytes untyped +node_zfsArc_arc_loaned_bytes 0 +# HELP node_zfsArc_arc_meta_limit kstat.zfs.misc.arcstats.arc_meta_limit +# TYPE node_zfsArc_arc_meta_limit untyped +node_zfsArc_arc_meta_limit 6.275982336e+09 +# HELP node_zfsArc_arc_meta_max kstat.zfs.misc.arcstats.arc_meta_max +# TYPE node_zfsArc_arc_meta_max untyped +node_zfsArc_arc_meta_max 4.49286096e+08 +# HELP node_zfsArc_arc_meta_min kstat.zfs.misc.arcstats.arc_meta_min +# TYPE node_zfsArc_arc_meta_min untyped +node_zfsArc_arc_meta_min 1.6777216e+07 +# HELP node_zfsArc_arc_meta_used kstat.zfs.misc.arcstats.arc_meta_used +# TYPE node_zfsArc_arc_meta_used untyped +node_zfsArc_arc_meta_used 3.08103632e+08 +# HELP node_zfsArc_arc_need_free kstat.zfs.misc.arcstats.arc_need_free +# TYPE node_zfsArc_arc_need_free untyped +node_zfsArc_arc_need_free 0 +# HELP node_zfsArc_arc_no_grow kstat.zfs.misc.arcstats.arc_no_grow +# TYPE node_zfsArc_arc_no_grow untyped +node_zfsArc_arc_no_grow 0 +# HELP node_zfsArc_arc_prune kstat.zfs.misc.arcstats.arc_prune +# TYPE node_zfsArc_arc_prune untyped +node_zfsArc_arc_prune 0 +# HELP node_zfsArc_arc_sys_free kstat.zfs.misc.arcstats.arc_sys_free +# TYPE node_zfsArc_arc_sys_free untyped +node_zfsArc_arc_sys_free 2.61496832e+08 +# HELP node_zfsArc_arc_tempreserve kstat.zfs.misc.arcstats.arc_tempreserve +# TYPE node_zfsArc_arc_tempreserve untyped +node_zfsArc_arc_tempreserve 0 +# HELP node_zfsArc_c kstat.zfs.misc.arcstats.c +# TYPE node_zfsArc_c untyped +node_zfsArc_c 1.643208777e+09 +# HELP node_zfsArc_c_max kstat.zfs.misc.arcstats.c_max +# TYPE node_zfsArc_c_max untyped +node_zfsArc_c_max 8.367976448e+09 +# HELP node_zfsArc_c_min kstat.zfs.misc.arcstats.c_min +# TYPE node_zfsArc_c_min untyped +node_zfsArc_c_min 3.3554432e+07 +# HELP node_zfsArc_data_size kstat.zfs.misc.arcstats.data_size +# TYPE node_zfsArc_data_size untyped +node_zfsArc_data_size 1.29583616e+09 +# HELP node_zfsArc_deleted kstat.zfs.misc.arcstats.deleted +# TYPE node_zfsArc_deleted untyped +node_zfsArc_deleted 60403 +# HELP node_zfsArc_demand_data_hits kstat.zfs.misc.arcstats.demand_data_hits +# TYPE node_zfsArc_demand_data_hits untyped +node_zfsArc_demand_data_hits 7.221032e+06 +# HELP node_zfsArc_demand_data_misses kstat.zfs.misc.arcstats.demand_data_misses +# TYPE node_zfsArc_demand_data_misses untyped +node_zfsArc_demand_data_misses 73300 +# HELP node_zfsArc_demand_metadata_hits kstat.zfs.misc.arcstats.demand_metadata_hits +# TYPE node_zfsArc_demand_metadata_hits untyped +node_zfsArc_demand_metadata_hits 1.464353e+06 +# HELP node_zfsArc_demand_metadata_misses kstat.zfs.misc.arcstats.demand_metadata_misses +# TYPE node_zfsArc_demand_metadata_misses untyped +node_zfsArc_demand_metadata_misses 498170 +# HELP node_zfsArc_duplicate_buffers kstat.zfs.misc.arcstats.duplicate_buffers +# TYPE node_zfsArc_duplicate_buffers untyped +node_zfsArc_duplicate_buffers 0 +# HELP node_zfsArc_duplicate_buffers_size kstat.zfs.misc.arcstats.duplicate_buffers_size +# TYPE node_zfsArc_duplicate_buffers_size untyped +node_zfsArc_duplicate_buffers_size 0 +# HELP node_zfsArc_duplicate_reads kstat.zfs.misc.arcstats.duplicate_reads +# TYPE node_zfsArc_duplicate_reads untyped +node_zfsArc_duplicate_reads 0 +# HELP node_zfsArc_evict_l2_cached kstat.zfs.misc.arcstats.evict_l2_cached +# TYPE node_zfsArc_evict_l2_cached untyped +node_zfsArc_evict_l2_cached 0 +# HELP node_zfsArc_evict_l2_eligible kstat.zfs.misc.arcstats.evict_l2_eligible +# TYPE node_zfsArc_evict_l2_eligible untyped +node_zfsArc_evict_l2_eligible 8.99251456e+09 +# HELP node_zfsArc_evict_l2_ineligible kstat.zfs.misc.arcstats.evict_l2_ineligible +# TYPE node_zfsArc_evict_l2_ineligible untyped +node_zfsArc_evict_l2_ineligible 9.92552448e+08 +# HELP node_zfsArc_evict_l2_skip kstat.zfs.misc.arcstats.evict_l2_skip +# TYPE node_zfsArc_evict_l2_skip untyped +node_zfsArc_evict_l2_skip 0 +# HELP node_zfsArc_evict_not_enough kstat.zfs.misc.arcstats.evict_not_enough +# TYPE node_zfsArc_evict_not_enough untyped +node_zfsArc_evict_not_enough 680 +# HELP node_zfsArc_evict_skip kstat.zfs.misc.arcstats.evict_skip +# TYPE node_zfsArc_evict_skip untyped +node_zfsArc_evict_skip 2.265729e+06 +# HELP node_zfsArc_hash_chain_max kstat.zfs.misc.arcstats.hash_chain_max +# TYPE node_zfsArc_hash_chain_max untyped +node_zfsArc_hash_chain_max 3 +# HELP node_zfsArc_hash_chains kstat.zfs.misc.arcstats.hash_chains +# TYPE node_zfsArc_hash_chains untyped +node_zfsArc_hash_chains 412 +# HELP node_zfsArc_hash_collisions kstat.zfs.misc.arcstats.hash_collisions +# TYPE node_zfsArc_hash_collisions untyped +node_zfsArc_hash_collisions 50564 +# HELP node_zfsArc_hash_elements kstat.zfs.misc.arcstats.hash_elements +# TYPE node_zfsArc_hash_elements untyped +node_zfsArc_hash_elements 42359 +# HELP node_zfsArc_hash_elements_max kstat.zfs.misc.arcstats.hash_elements_max +# TYPE node_zfsArc_hash_elements_max untyped +node_zfsArc_hash_elements_max 88245 +# HELP node_zfsArc_hdr_size kstat.zfs.misc.arcstats.hdr_size +# TYPE node_zfsArc_hdr_size untyped +node_zfsArc_hdr_size 1.636108e+07 +# HELP node_zfsArc_hits kstat.zfs.misc.arcstats.hits +# TYPE node_zfsArc_hits untyped +node_zfsArc_hits 8.772612e+06 +# HELP node_zfsArc_l2_abort_lowmem kstat.zfs.misc.arcstats.l2_abort_lowmem +# TYPE node_zfsArc_l2_abort_lowmem untyped +node_zfsArc_l2_abort_lowmem 0 +# HELP node_zfsArc_l2_asize kstat.zfs.misc.arcstats.l2_asize +# TYPE node_zfsArc_l2_asize untyped +node_zfsArc_l2_asize 0 +# HELP node_zfsArc_l2_cdata_free_on_write kstat.zfs.misc.arcstats.l2_cdata_free_on_write +# TYPE node_zfsArc_l2_cdata_free_on_write untyped +node_zfsArc_l2_cdata_free_on_write 0 +# HELP node_zfsArc_l2_cksum_bad kstat.zfs.misc.arcstats.l2_cksum_bad +# TYPE node_zfsArc_l2_cksum_bad untyped +node_zfsArc_l2_cksum_bad 0 +# HELP node_zfsArc_l2_compress_failures kstat.zfs.misc.arcstats.l2_compress_failures +# TYPE node_zfsArc_l2_compress_failures untyped +node_zfsArc_l2_compress_failures 0 +# HELP node_zfsArc_l2_compress_successes kstat.zfs.misc.arcstats.l2_compress_successes +# TYPE node_zfsArc_l2_compress_successes untyped +node_zfsArc_l2_compress_successes 0 +# HELP node_zfsArc_l2_compress_zeros kstat.zfs.misc.arcstats.l2_compress_zeros +# TYPE node_zfsArc_l2_compress_zeros untyped +node_zfsArc_l2_compress_zeros 0 +# HELP node_zfsArc_l2_evict_l1cached kstat.zfs.misc.arcstats.l2_evict_l1cached +# TYPE node_zfsArc_l2_evict_l1cached untyped +node_zfsArc_l2_evict_l1cached 0 +# HELP node_zfsArc_l2_evict_lock_retry kstat.zfs.misc.arcstats.l2_evict_lock_retry +# TYPE node_zfsArc_l2_evict_lock_retry untyped +node_zfsArc_l2_evict_lock_retry 0 +# HELP node_zfsArc_l2_evict_reading kstat.zfs.misc.arcstats.l2_evict_reading +# TYPE node_zfsArc_l2_evict_reading untyped +node_zfsArc_l2_evict_reading 0 +# HELP node_zfsArc_l2_feeds kstat.zfs.misc.arcstats.l2_feeds +# TYPE node_zfsArc_l2_feeds untyped +node_zfsArc_l2_feeds 0 +# HELP node_zfsArc_l2_free_on_write kstat.zfs.misc.arcstats.l2_free_on_write +# TYPE node_zfsArc_l2_free_on_write untyped +node_zfsArc_l2_free_on_write 0 +# HELP node_zfsArc_l2_hdr_size kstat.zfs.misc.arcstats.l2_hdr_size +# TYPE node_zfsArc_l2_hdr_size untyped +node_zfsArc_l2_hdr_size 0 +# HELP node_zfsArc_l2_hits kstat.zfs.misc.arcstats.l2_hits +# TYPE node_zfsArc_l2_hits untyped +node_zfsArc_l2_hits 0 +# HELP node_zfsArc_l2_io_error kstat.zfs.misc.arcstats.l2_io_error +# TYPE node_zfsArc_l2_io_error untyped +node_zfsArc_l2_io_error 0 +# HELP node_zfsArc_l2_misses kstat.zfs.misc.arcstats.l2_misses +# TYPE node_zfsArc_l2_misses untyped +node_zfsArc_l2_misses 0 +# HELP node_zfsArc_l2_read_bytes kstat.zfs.misc.arcstats.l2_read_bytes +# TYPE node_zfsArc_l2_read_bytes untyped +node_zfsArc_l2_read_bytes 0 +# HELP node_zfsArc_l2_rw_clash kstat.zfs.misc.arcstats.l2_rw_clash +# TYPE node_zfsArc_l2_rw_clash untyped +node_zfsArc_l2_rw_clash 0 +# HELP node_zfsArc_l2_size kstat.zfs.misc.arcstats.l2_size +# TYPE node_zfsArc_l2_size untyped +node_zfsArc_l2_size 0 +# HELP node_zfsArc_l2_write_bytes kstat.zfs.misc.arcstats.l2_write_bytes +# TYPE node_zfsArc_l2_write_bytes untyped +node_zfsArc_l2_write_bytes 0 +# HELP node_zfsArc_l2_writes_done kstat.zfs.misc.arcstats.l2_writes_done +# TYPE node_zfsArc_l2_writes_done untyped +node_zfsArc_l2_writes_done 0 +# HELP node_zfsArc_l2_writes_error kstat.zfs.misc.arcstats.l2_writes_error +# TYPE node_zfsArc_l2_writes_error untyped +node_zfsArc_l2_writes_error 0 +# HELP node_zfsArc_l2_writes_lock_retry kstat.zfs.misc.arcstats.l2_writes_lock_retry +# TYPE node_zfsArc_l2_writes_lock_retry untyped +node_zfsArc_l2_writes_lock_retry 0 +# HELP node_zfsArc_l2_writes_sent kstat.zfs.misc.arcstats.l2_writes_sent +# TYPE node_zfsArc_l2_writes_sent untyped +node_zfsArc_l2_writes_sent 0 +# HELP node_zfsArc_memory_direct_count kstat.zfs.misc.arcstats.memory_direct_count +# TYPE node_zfsArc_memory_direct_count untyped +node_zfsArc_memory_direct_count 542 +# HELP node_zfsArc_memory_indirect_count kstat.zfs.misc.arcstats.memory_indirect_count +# TYPE node_zfsArc_memory_indirect_count untyped +node_zfsArc_memory_indirect_count 3006 +# HELP node_zfsArc_memory_throttle_count kstat.zfs.misc.arcstats.memory_throttle_count +# TYPE node_zfsArc_memory_throttle_count untyped +node_zfsArc_memory_throttle_count 0 +# HELP node_zfsArc_metadata_size kstat.zfs.misc.arcstats.metadata_size +# TYPE node_zfsArc_metadata_size untyped +node_zfsArc_metadata_size 1.7529856e+08 +# HELP node_zfsArc_mfu_evictable_data kstat.zfs.misc.arcstats.mfu_evictable_data +# TYPE node_zfsArc_mfu_evictable_data untyped +node_zfsArc_mfu_evictable_data 1.017613824e+09 +# HELP node_zfsArc_mfu_evictable_metadata kstat.zfs.misc.arcstats.mfu_evictable_metadata +# TYPE node_zfsArc_mfu_evictable_metadata untyped +node_zfsArc_mfu_evictable_metadata 9.163776e+06 +# HELP node_zfsArc_mfu_ghost_evictable_data kstat.zfs.misc.arcstats.mfu_ghost_evictable_data +# TYPE node_zfsArc_mfu_ghost_evictable_data untyped +node_zfsArc_mfu_ghost_evictable_data 9.6731136e+07 +# HELP node_zfsArc_mfu_ghost_evictable_metadata kstat.zfs.misc.arcstats.mfu_ghost_evictable_metadata +# TYPE node_zfsArc_mfu_ghost_evictable_metadata untyped +node_zfsArc_mfu_ghost_evictable_metadata 8.205312e+06 +# HELP node_zfsArc_mfu_ghost_hits kstat.zfs.misc.arcstats.mfu_ghost_hits +# TYPE node_zfsArc_mfu_ghost_hits untyped +node_zfsArc_mfu_ghost_hits 821 +# HELP node_zfsArc_mfu_ghost_size kstat.zfs.misc.arcstats.mfu_ghost_size +# TYPE node_zfsArc_mfu_ghost_size untyped +node_zfsArc_mfu_ghost_size 1.04936448e+08 +# HELP node_zfsArc_mfu_hits kstat.zfs.misc.arcstats.mfu_hits +# TYPE node_zfsArc_mfu_hits untyped +node_zfsArc_mfu_hits 7.829854e+06 +# HELP node_zfsArc_mfu_size kstat.zfs.misc.arcstats.mfu_size +# TYPE node_zfsArc_mfu_size untyped +node_zfsArc_mfu_size 1.066623488e+09 +# HELP node_zfsArc_misses kstat.zfs.misc.arcstats.misses +# TYPE node_zfsArc_misses untyped +node_zfsArc_misses 604635 +# HELP node_zfsArc_mru_evictable_data kstat.zfs.misc.arcstats.mru_evictable_data +# TYPE node_zfsArc_mru_evictable_data untyped +node_zfsArc_mru_evictable_data 2.78091264e+08 +# HELP node_zfsArc_mru_evictable_metadata kstat.zfs.misc.arcstats.mru_evictable_metadata +# TYPE node_zfsArc_mru_evictable_metadata untyped +node_zfsArc_mru_evictable_metadata 1.8606592e+07 +# HELP node_zfsArc_mru_ghost_evictable_data kstat.zfs.misc.arcstats.mru_ghost_evictable_data +# TYPE node_zfsArc_mru_ghost_evictable_data untyped +node_zfsArc_mru_ghost_evictable_data 8.83765248e+08 +# HELP node_zfsArc_mru_ghost_evictable_metadata kstat.zfs.misc.arcstats.mru_ghost_evictable_metadata +# TYPE node_zfsArc_mru_ghost_evictable_metadata untyped +node_zfsArc_mru_ghost_evictable_metadata 1.1596288e+08 +# HELP node_zfsArc_mru_ghost_hits kstat.zfs.misc.arcstats.mru_ghost_hits +# TYPE node_zfsArc_mru_ghost_hits untyped +node_zfsArc_mru_ghost_hits 21100 +# HELP node_zfsArc_mru_ghost_size kstat.zfs.misc.arcstats.mru_ghost_size +# TYPE node_zfsArc_mru_ghost_size untyped +node_zfsArc_mru_ghost_size 9.99728128e+08 +# HELP node_zfsArc_mru_hits kstat.zfs.misc.arcstats.mru_hits +# TYPE node_zfsArc_mru_hits untyped +node_zfsArc_mru_hits 855535 +# HELP node_zfsArc_mru_size kstat.zfs.misc.arcstats.mru_size +# TYPE node_zfsArc_mru_size untyped +node_zfsArc_mru_size 4.02593792e+08 +# HELP node_zfsArc_mutex_miss kstat.zfs.misc.arcstats.mutex_miss +# TYPE node_zfsArc_mutex_miss untyped +node_zfsArc_mutex_miss 2 +# HELP node_zfsArc_other_size kstat.zfs.misc.arcstats.other_size +# TYPE node_zfsArc_other_size untyped +node_zfsArc_other_size 1.16443992e+08 +# HELP node_zfsArc_p kstat.zfs.misc.arcstats.p +# TYPE node_zfsArc_p untyped +node_zfsArc_p 5.16395305e+08 +# HELP node_zfsArc_prefetch_data_hits kstat.zfs.misc.arcstats.prefetch_data_hits +# TYPE node_zfsArc_prefetch_data_hits untyped +node_zfsArc_prefetch_data_hits 3615 +# HELP node_zfsArc_prefetch_data_misses kstat.zfs.misc.arcstats.prefetch_data_misses +# TYPE node_zfsArc_prefetch_data_misses untyped +node_zfsArc_prefetch_data_misses 17094 +# HELP node_zfsArc_prefetch_metadata_hits kstat.zfs.misc.arcstats.prefetch_metadata_hits +# TYPE node_zfsArc_prefetch_metadata_hits untyped +node_zfsArc_prefetch_metadata_hits 83612 +# HELP node_zfsArc_prefetch_metadata_misses kstat.zfs.misc.arcstats.prefetch_metadata_misses +# TYPE node_zfsArc_prefetch_metadata_misses untyped +node_zfsArc_prefetch_metadata_misses 16071 +# HELP node_zfsArc_size kstat.zfs.misc.arcstats.size +# TYPE node_zfsArc_size untyped +node_zfsArc_size 1.603939792e+09 # 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/spl/kstat/zfs/arcstats b/collector/fixtures/proc/spl/kstat/zfs/arcstats new file mode 100644 index 00000000..48a73a2c --- /dev/null +++ b/collector/fixtures/proc/spl/kstat/zfs/arcstats @@ -0,0 +1,93 @@ +6 1 0x01 91 4368 5266997922 97951858082072 +name type data +hits 4 8772612 +misses 4 604635 +demand_data_hits 4 7221032 +demand_data_misses 4 73300 +demand_metadata_hits 4 1464353 +demand_metadata_misses 4 498170 +prefetch_data_hits 4 3615 +prefetch_data_misses 4 17094 +prefetch_metadata_hits 4 83612 +prefetch_metadata_misses 4 16071 +mru_hits 4 855535 +mru_ghost_hits 4 21100 +mfu_hits 4 7829854 +mfu_ghost_hits 4 821 +deleted 4 60403 +mutex_miss 4 2 +evict_skip 4 2265729 +evict_not_enough 4 680 +evict_l2_cached 4 0 +evict_l2_eligible 4 8992514560 +evict_l2_ineligible 4 992552448 +evict_l2_skip 4 0 +hash_elements 4 42359 +hash_elements_max 4 88245 +hash_collisions 4 50564 +hash_chains 4 412 +hash_chain_max 4 3 +p 4 516395305 +c 4 1643208777 +c_min 4 33554432 +c_max 4 8367976448 +size 4 1603939792 +hdr_size 4 16361080 +data_size 4 1295836160 +metadata_size 4 175298560 +other_size 4 116443992 +anon_size 4 1917440 +anon_evictable_data 4 0 +anon_evictable_metadata 4 0 +mru_size 4 402593792 +mru_evictable_data 4 278091264 +mru_evictable_metadata 4 18606592 +mru_ghost_size 4 999728128 +mru_ghost_evictable_data 4 883765248 +mru_ghost_evictable_metadata 4 115962880 +mfu_size 4 1066623488 +mfu_evictable_data 4 1017613824 +mfu_evictable_metadata 4 9163776 +mfu_ghost_size 4 104936448 +mfu_ghost_evictable_data 4 96731136 +mfu_ghost_evictable_metadata 4 8205312 +l2_hits 4 0 +l2_misses 4 0 +l2_feeds 4 0 +l2_rw_clash 4 0 +l2_read_bytes 4 0 +l2_write_bytes 4 0 +l2_writes_sent 4 0 +l2_writes_done 4 0 +l2_writes_error 4 0 +l2_writes_lock_retry 4 0 +l2_evict_lock_retry 4 0 +l2_evict_reading 4 0 +l2_evict_l1cached 4 0 +l2_free_on_write 4 0 +l2_cdata_free_on_write 4 0 +l2_abort_lowmem 4 0 +l2_cksum_bad 4 0 +l2_io_error 4 0 +l2_size 4 0 +l2_asize 4 0 +l2_hdr_size 4 0 +l2_compress_successes 4 0 +l2_compress_zeros 4 0 +l2_compress_failures 4 0 +memory_throttle_count 4 0 +duplicate_buffers 4 0 +duplicate_buffers_size 4 0 +duplicate_reads 4 0 +memory_direct_count 4 542 +memory_indirect_count 4 3006 +arc_no_grow 4 0 +arc_tempreserve 4 0 +arc_loaned_bytes 4 0 +arc_prune 4 0 +arc_meta_used 4 308103632 +arc_meta_limit 4 6275982336 +arc_meta_max 4 449286096 +arc_meta_min 4 16777216 +arc_need_free 4 0 +arc_sys_free 4 261496832 diff --git a/collector/zfs.go b/collector/zfs.go new file mode 100644 index 00000000..b9c19536 --- /dev/null +++ b/collector/zfs.go @@ -0,0 +1,100 @@ +// Copyright 2016 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 linux +// +build !nozfs + +package collector + +import ( + "errors" + "strings" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +type zfsMetricValue int + +const zfsErrorValue = zfsMetricValue(-1) + +var zfsNotAvailableError = errors.New("ZFS / ZFS statistics are not available") + +type zfsSysctl string +type zfsSubsystemName string + +const ( + arc = zfsSubsystemName("zfsArc") + zpoolSubsystem = zfsSubsystemName("zfsPool") +) + +// Metrics + +type zfsMetric struct { + subsystem zfsSubsystemName // The Prometheus subsystem name. + name string // The Prometheus name of the metric. + sysctl zfsSysctl // The sysctl of the ZFS metric. +} + +// Collector + +func init() { + Factories["zfs"] = NewZFSCollector +} + +type zfsCollector struct { + zfsMetrics []zfsMetric +} + +func NewZFSCollector() (Collector, error) { + return &zfsCollector{}, nil +} + +func (c *zfsCollector) Update(ch chan<- prometheus.Metric) (err error) { + // Arcstats + err = c.updateArcstats(ch) + if err != nil { + return err + } + + switch { + case err == zfsNotAvailableError: + log.Debug(err) + return nil + case err != nil: + return err + } + + // Pool stats + return c.updatePoolStats(ch) +} + +func (s zfsSysctl) metricName() string { + parts := strings.Split(string(s), ".") + return parts[len(parts)-1] +} + +func (c *zfsCollector) constSysctlMetric(subsystem zfsSubsystemName, sysctl zfsSysctl, value zfsMetricValue) prometheus.Metric { + metricName := sysctl.metricName() + + return prometheus.MustNewConstMetric( + prometheus.NewDesc( + prometheus.BuildFQName(Namespace, string(subsystem), metricName), + string(sysctl), + nil, + nil, + ), + prometheus.UntypedValue, + float64(value), + ) +} diff --git a/collector/zfs_linux.go b/collector/zfs_linux.go new file mode 100644 index 00000000..17cfcaed --- /dev/null +++ b/collector/zfs_linux.go @@ -0,0 +1,90 @@ +// Copyright 2016 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 ( + "bufio" + "errors" + "fmt" + "io" + "os" + "strconv" + "strings" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/log" +) + +const ( + zfsArcstatsProcpath = "spl/kstat/zfs/arcstats" +) + +func (c *zfsCollector) openArcstatsFile() (file *os.File, err error) { + file, err = os.Open(procFilePath(zfsArcstatsProcpath)) + if err != nil { + log.Debugf("Cannot open %q for reading. Is the kernel module loaded?", procFilePath(zfsArcstatsProcpath)) + err = zfsNotAvailableError + } + return +} + +func (c *zfsCollector) updateArcstats(ch chan<- prometheus.Metric) (err error) { + file, err := c.openArcstatsFile() + if err != nil { + return err + } + defer file.Close() + + return c.parseArcstatsProcfsFile(file, func(s zfsSysctl, v zfsMetricValue) { + ch <- c.constSysctlMetric(arc, s, v) + }) +} + +func (c *zfsCollector) parseArcstatsProcfsFile(reader io.Reader, handler func(zfsSysctl, zfsMetricValue)) (err error) { + scanner := bufio.NewScanner(reader) + + parseLine := false + for scanner.Scan() { + + parts := strings.Fields(scanner.Text()) + + if !parseLine && len(parts) == 3 && parts[0] == "name" && parts[1] == "type" && parts[2] == "data" { + // Start parsing from here. + parseLine = true + continue + } + + if !parseLine || len(parts) < 3 { + continue + } + + key := fmt.Sprintf("kstat.zfs.misc.arcstats.%s", parts[0]) + + value, err := strconv.Atoi(parts[2]) + if err != nil { + return fmt.Errorf("could not parse expected integer value for %q", key) + } + handler(zfsSysctl(key), zfsMetricValue(value)) + + } + if !parseLine { + return errors.New("did not parse a single arcstat metric") + } + + return scanner.Err() +} + +func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) (err error) { + return nil +} diff --git a/collector/zfs_linux_test.go b/collector/zfs_linux_test.go new file mode 100644 index 00000000..7583281d --- /dev/null +++ b/collector/zfs_linux_test.go @@ -0,0 +1,55 @@ +// Copyright 2016 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 ( + "os" + "testing" +) + +func TestArcstatsParsing(t *testing.T) { + arcstatsFile, err := os.Open("fixtures/proc/spl/kstat/zfs/arcstats") + if err != nil { + t.Fatal(err) + } + defer arcstatsFile.Close() + + c := zfsCollector{} + if err != nil { + t.Fatal(err) + } + + handlerCalled := false + err = c.parseArcstatsProcfsFile(arcstatsFile, func(s zfsSysctl, v zfsMetricValue) { + + if s != zfsSysctl("kstat.zfs.misc.arcstats.hits") { + return + } + + handlerCalled = true + + if v != zfsMetricValue(8772612) { + t.Fatalf("Incorrect value parsed from procfs data") + } + + }) + + if err != nil { + t.Fatal(err) + } + + if !handlerCalled { + t.Fatal("Arcstats parsing handler was not called for some expected sysctls") + } +} diff --git a/end-to-end-test.sh b/end-to-end-test.sh index 5c17e75b..fe2061af 100755 --- a/end-to-end-test.sh +++ b/end-to-end-test.sh @@ -23,6 +23,7 @@ collectors=$(cat << COLLECTORS textfile bonding megacli + zfs COLLECTORS ) cd "$(dirname $0)" diff --git a/node_exporter.go b/node_exporter.go index 011199d7..e737232c 100644 --- a/node_exporter.go +++ b/node_exporter.go @@ -32,7 +32,7 @@ import ( ) const ( - defaultCollectors = "conntrack,cpu,diskstats,entropy,filefd,filesystem,hwmon,loadavg,mdadm,meminfo,netdev,netstat,sockstat,stat,textfile,time,uname,vmstat" + defaultCollectors = "conntrack,cpu,diskstats,entropy,filefd,filesystem,hwmon,loadavg,mdadm,meminfo,netdev,netstat,sockstat,stat,textfile,time,uname,vmstat,zfs" ) var (