1
0
Fork 0

Adding upstream version 1.34.4.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 07:26:29 +02:00
parent e393c3af3f
commit 4978089aab
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
4963 changed files with 677545 additions and 0 deletions

View file

@ -0,0 +1,418 @@
# ZFS Input Plugin
This ZFS plugin provides metrics from your ZFS filesystems. It supports ZFS on
Linux and FreeBSD. It gets ZFS stat from `/proc/spl/kstat/zfs` on Linux and
from `sysctl`, 'zfs' and `zpool` on FreeBSD.
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
In addition to the plugin-specific configuration settings, plugins support
additional global and plugin configuration settings. These settings are used to
modify metrics, tags, and field or create aliases and configure ordering, etc.
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
## Configuration
```toml @sample.conf
# Read metrics of ZFS from arcstats, zfetchstats, vdev_cache_stats, pools and datasets
# This plugin ONLY supports Linux & FreeBSD
[[inputs.zfs]]
## ZFS kstat path. Ignored on FreeBSD
## If not specified, then default is:
# kstatPath = "/proc/spl/kstat/zfs"
## By default, telegraf gather all zfs stats
## Override the stats list using the kstatMetrics array:
## For FreeBSD, the default is:
# kstatMetrics = ["arcstats", "zfetchstats", "vdev_cache_stats"]
## For Linux, the default is:
# kstatMetrics = ["abdstats", "arcstats", "dnodestats", "dbufcachestats",
# "dmu_tx", "fm", "vdev_mirror_stats", "zfetchstats", "zil"]
## By default, don't gather zpool stats
# poolMetrics = false
## By default, don't gather dataset stats
# datasetMetrics = false
```
## Metrics
By default this plugin collects metrics about ZFS internals pool and dataset.
These metrics are either counters or measure sizes
in bytes. These metrics will be in the `zfs` measurement with the field
names listed below.
If `poolMetrics` is enabled then additional metrics will be gathered for
each pool.
If `datasetMetrics` is enabled then additional metrics will be gathered for
each dataset.
- zfs
With fields listed below.
### ARC Stats (FreeBSD and Linux)
- arcstats_allocated (FreeBSD only)
- arcstats_anon_evict_data (Linux only)
- arcstats_anon_evict_metadata (Linux only)
- arcstats_anon_evictable_data (FreeBSD only)
- arcstats_anon_evictable_metadata (FreeBSD only)
- arcstats_anon_size
- arcstats_arc_loaned_bytes (Linux only)
- arcstats_arc_meta_limit
- arcstats_arc_meta_max
- arcstats_arc_meta_min (FreeBSD only)
- arcstats_arc_meta_used
- arcstats_arc_no_grow (Linux only)
- arcstats_arc_prune (Linux only)
- arcstats_arc_tempreserve (Linux only)
- arcstats_c
- arcstats_c_max
- arcstats_c_min
- arcstats_data_size
- arcstats_deleted
- arcstats_demand_data_hits
- arcstats_demand_data_misses
- arcstats_demand_hit_predictive_prefetch (FreeBSD only)
- arcstats_demand_metadata_hits
- arcstats_demand_metadata_misses
- arcstats_duplicate_buffers
- arcstats_duplicate_buffers_size
- arcstats_duplicate_reads
- arcstats_evict_l2_cached
- arcstats_evict_l2_eligible
- arcstats_evict_l2_ineligible
- arcstats_evict_l2_skip (FreeBSD only)
- arcstats_evict_not_enough (FreeBSD only)
- arcstats_evict_skip
- arcstats_hash_chain_max
- arcstats_hash_chains
- arcstats_hash_collisions
- arcstats_hash_elements
- arcstats_hash_elements_max
- arcstats_hdr_size
- arcstats_hits
- arcstats_l2_abort_lowmem
- arcstats_l2_asize
- arcstats_l2_cdata_free_on_write
- arcstats_l2_cksum_bad
- arcstats_l2_compress_failures
- arcstats_l2_compress_successes
- arcstats_l2_compress_zeros
- arcstats_l2_evict_l1cached (FreeBSD only)
- arcstats_l2_evict_lock_retry
- arcstats_l2_evict_reading
- arcstats_l2_feeds
- arcstats_l2_free_on_write
- arcstats_l2_hdr_size
- arcstats_l2_hits
- arcstats_l2_io_error
- arcstats_l2_misses
- arcstats_l2_read_bytes
- arcstats_l2_rw_clash
- arcstats_l2_size
- arcstats_l2_write_buffer_bytes_scanned (FreeBSD only)
- arcstats_l2_write_buffer_iter (FreeBSD only)
- arcstats_l2_write_buffer_list_iter (FreeBSD only)
- arcstats_l2_write_buffer_list_null_iter (FreeBSD only)
- arcstats_l2_write_bytes
- arcstats_l2_write_full (FreeBSD only)
- arcstats_l2_write_in_l2 (FreeBSD only)
- arcstats_l2_write_io_in_progress (FreeBSD only)
- arcstats_l2_write_not_cacheable (FreeBSD only)
- arcstats_l2_write_passed_headroom (FreeBSD only)
- arcstats_l2_write_pios (FreeBSD only)
- arcstats_l2_write_spa_mismatch (FreeBSD only)
- arcstats_l2_write_trylock_fail (FreeBSD only)
- arcstats_l2_writes_done
- arcstats_l2_writes_error
- arcstats_l2_writes_hdr_miss (Linux only)
- arcstats_l2_writes_lock_retry (FreeBSD only)
- arcstats_l2_writes_sent
- arcstats_memory_direct_count (Linux only)
- arcstats_memory_indirect_count (Linux only)
- arcstats_memory_throttle_count
- arcstats_meta_size (Linux only)
- arcstats_mfu_evict_data (Linux only)
- arcstats_mfu_evict_metadata (Linux only)
- arcstats_mfu_ghost_evict_data (Linux only)
- arcstats_mfu_ghost_evict_metadata (Linux only)
- arcstats_metadata_size (FreeBSD only)
- arcstats_mfu_evictable_data (FreeBSD only)
- arcstats_mfu_evictable_metadata (FreeBSD only)
- arcstats_mfu_ghost_evictable_data (FreeBSD only)
- arcstats_mfu_ghost_evictable_metadata (FreeBSD only)
- arcstats_mfu_ghost_hits
- arcstats_mfu_ghost_size
- arcstats_mfu_hits
- arcstats_mfu_size
- arcstats_misses
- arcstats_mru_evict_data (Linux only)
- arcstats_mru_evict_metadata (Linux only)
- arcstats_mru_ghost_evict_data (Linux only)
- arcstats_mru_ghost_evict_metadata (Linux only)
- arcstats_mru_evictable_data (FreeBSD only)
- arcstats_mru_evictable_metadata (FreeBSD only)
- arcstats_mru_ghost_evictable_data (FreeBSD only)
- arcstats_mru_ghost_evictable_metadata (FreeBSD only)
- arcstats_mru_ghost_hits
- arcstats_mru_ghost_size
- arcstats_mru_hits
- arcstats_mru_size
- arcstats_mutex_miss
- arcstats_other_size
- arcstats_p
- arcstats_prefetch_data_hits
- arcstats_prefetch_data_misses
- arcstats_prefetch_metadata_hits
- arcstats_prefetch_metadata_misses
- arcstats_recycle_miss (Linux only)
- arcstats_size
- arcstats_sync_wait_for_async (FreeBSD only)
### Zfetch Stats (FreeBSD and Linux)
- zfetchstats_bogus_streams (Linux only)
- zfetchstats_colinear_hits (Linux only)
- zfetchstats_colinear_misses (Linux only)
- zfetchstats_hits
- zfetchstats_max_streams (FreeBSD only)
- zfetchstats_misses
- zfetchstats_reclaim_failures (Linux only)
- zfetchstats_reclaim_successes (Linux only)
- zfetchstats_streams_noresets (Linux only)
- zfetchstats_streams_resets (Linux only)
- zfetchstats_stride_hits (Linux only)
- zfetchstats_stride_misses (Linux only)
### Vdev Cache Stats (FreeBSD)
- vdev_cache_stats_delegations
- vdev_cache_stats_hits
- vdev_cache_stats_misses
### Pool Metrics (optional)
On Linux (reference: kstat accumulated time and queue length statistics):
- zfs_pool
- nread (integer, bytes)
- nwritten (integer, bytes)
- reads (integer, count)
- writes (integer, count)
- wtime (integer, nanoseconds)
- wlentime (integer, queuelength * nanoseconds)
- wupdate (integer, timestamp)
- rtime (integer, nanoseconds)
- rlentime (integer, queuelength * nanoseconds)
- rupdate (integer, timestamp)
- wcnt (integer, count)
- rcnt (integer, count)
For ZFS >= 2.1.x the format has changed significantly:
- zfs_pool
- writes (integer, count)
- nwritten (integer, bytes)
- reads (integer, count)
- nread (integer, bytes)
- nunlinks (integer, count)
- nunlinked (integer, count)
For ZFS >= 2.2.x the following additional fields are available:
- additional fields for ZFS > 2.2.x
- zil_commit_count (integer, count)
- zil_commit_writer_count (integer, count)
- zil_itx_count (integer, count)
- zil_itx_indirect_count (integer, count)
- zil_itx_indirect_bytes (integer, bytes)
- zil_itx_copied_count (integer, count)
- zil_itx_copied_bytes (integer, bytes)
- zil_itx_needcopy_count (integer, count)
- zil_itx_needcopy_bytes (integer, bytes)
- zil_itx_metaslab_normal_count (integer, count)
- zil_itx_metaslab_normal_bytes (integer, bytes)
- zil_itx_metaslab_normal_write (integer, bytes)
- zil_itx_metaslab_normal_alloc (integer, bytes)
- zil_itx_metaslab_slog_count (integer, count)
- zil_itx_metaslab_slog_bytes (integer, bytes)
- zil_itx_metaslab_slog_write (integer, bytes)
- zil_itx_metaslab_slog_alloc (integer, bytes)
On FreeBSD:
- zfs_pool
- allocated (integer, bytes)
- capacity (integer, bytes)
- dedupratio (float, ratio)
- free (integer, bytes)
- size (integer, bytes)
- fragmentation (integer, percent)
### Dataset Metrics (optional, only on FreeBSD)
- zfs_dataset
- avail (integer, bytes)
- used (integer, bytes)
- usedsnap (integer, bytes
- usedds (integer, bytes)
### Tags
- ZFS stats (`zfs`) will have the following tag:
- pools - A `::` concatenated list of all ZFS pools on the machine.
- datasets - A `::` concatenated list of all ZFS datasets on the machine.
- Pool metrics (`zfs_pool`) will have the following tag:
- pool - with the name of the pool which the metrics are for.
- health - the health status of the pool. (FreeBSD only)
- dataset - ZFS >= 2.1.x only. (Linux only)
- Dataset metrics (`zfs_dataset`) will have the following tag:
- dataset - with the name of the dataset which the metrics are for.
## Example Output
```text
zfs_pool,health=ONLINE,pool=zroot allocated=1578590208i,capacity=2i,dedupratio=1,fragmentation=1i,free=64456531968i,size=66035122176i 1464473103625653908
zfs_dataset,dataset=zata avail=10741741326336,used=8564135526400,usedsnap=0,usedds=90112
zfs,pools=zroot arcstats_allocated=4167764i,arcstats_anon_evictable_data=0i,arcstats_anon_evictable_metadata=0i,arcstats_anon_size=16896i,arcstats_arc_meta_limit=10485760i,arcstats_arc_meta_max=115269568i,arcstats_arc_meta_min=8388608i,arcstats_arc_meta_used=51977456i,arcstats_c=16777216i,arcstats_c_max=41943040i,arcstats_c_min=16777216i,arcstats_data_size=0i,arcstats_deleted=1699340i,arcstats_demand_data_hits=14836131i,arcstats_demand_data_misses=2842945i,arcstats_demand_hit_predictive_prefetch=0i,arcstats_demand_metadata_hits=1655006i,arcstats_demand_metadata_misses=830074i,arcstats_duplicate_buffers=0i,arcstats_duplicate_buffers_size=0i,arcstats_duplicate_reads=123i,arcstats_evict_l2_cached=0i,arcstats_evict_l2_eligible=332172623872i,arcstats_evict_l2_ineligible=6168576i,arcstats_evict_l2_skip=0i,arcstats_evict_not_enough=12189444i,arcstats_evict_skip=195190764i,arcstats_hash_chain_max=2i,arcstats_hash_chains=10i,arcstats_hash_collisions=43134i,arcstats_hash_elements=2268i,arcstats_hash_elements_max=6136i,arcstats_hdr_size=565632i,arcstats_hits=16515778i,arcstats_l2_abort_lowmem=0i,arcstats_l2_asize=0i,arcstats_l2_cdata_free_on_write=0i,arcstats_l2_cksum_bad=0i,arcstats_l2_compress_failures=0i,arcstats_l2_compress_successes=0i,arcstats_l2_compress_zeros=0i,arcstats_l2_evict_l1cached=0i,arcstats_l2_evict_lock_retry=0i,arcstats_l2_evict_reading=0i,arcstats_l2_feeds=0i,arcstats_l2_free_on_write=0i,arcstats_l2_hdr_size=0i,arcstats_l2_hits=0i,arcstats_l2_io_error=0i,arcstats_l2_misses=0i,arcstats_l2_read_bytes=0i,arcstats_l2_rw_clash=0i,arcstats_l2_size=0i,arcstats_l2_write_buffer_bytes_scanned=0i,arcstats_l2_write_buffer_iter=0i,arcstats_l2_write_buffer_list_iter=0i,arcstats_l2_write_buffer_list_null_iter=0i,arcstats_l2_write_bytes=0i,arcstats_l2_write_full=0i,arcstats_l2_write_in_l2=0i,arcstats_l2_write_io_in_progress=0i,arcstats_l2_write_not_cacheable=380i,arcstats_l2_write_passed_headroom=0i,arcstats_l2_write_pios=0i,arcstats_l2_write_spa_mismatch=0i,arcstats_l2_write_trylock_fail=0i,arcstats_l2_writes_done=0i,arcstats_l2_writes_error=0i,arcstats_l2_writes_lock_retry=0i,arcstats_l2_writes_sent=0i,arcstats_memory_throttle_count=0i,arcstats_metadata_size=17014784i,arcstats_mfu_evictable_data=0i,arcstats_mfu_evictable_metadata=16384i,arcstats_mfu_ghost_evictable_data=5723648i,arcstats_mfu_ghost_evictable_metadata=10709504i,arcstats_mfu_ghost_hits=1315619i,arcstats_mfu_ghost_size=16433152i,arcstats_mfu_hits=7646611i,arcstats_mfu_size=305152i,arcstats_misses=3676993i,arcstats_mru_evictable_data=0i,arcstats_mru_evictable_metadata=0i,arcstats_mru_ghost_evictable_data=0i,arcstats_mru_ghost_evictable_metadata=80896i,arcstats_mru_ghost_hits=324250i,arcstats_mru_ghost_size=80896i,arcstats_mru_hits=8844526i,arcstats_mru_size=16693248i,arcstats_mutex_miss=354023i,arcstats_other_size=34397040i,arcstats_p=4172800i,arcstats_prefetch_data_hits=0i,arcstats_prefetch_data_misses=0i,arcstats_prefetch_metadata_hits=24641i,arcstats_prefetch_metadata_misses=3974i,arcstats_size=51977456i,arcstats_sync_wait_for_async=0i,vdev_cache_stats_delegations=779i,vdev_cache_stats_hits=323123i,vdev_cache_stats_misses=59929i,zfetchstats_hits=0i,zfetchstats_max_streams=0i,zfetchstats_misses=0i 1464473103634124908
```
## Description
A short description for some of the metrics.
### ARC Stats
`arcstats_hits` Total amount of cache hits in the arc.
`arcstats_misses` Total amount of cache misses in the arc.
`arcstats_demand_data_hits` Amount of cache hits for demand data, this is what
matters (is good) for your application/share.
`arcstats_demand_data_misses` Amount of cache misses for demand data, this is
what matters (is bad) for your application/share.
`arcstats_demand_metadata_hits` Amount of cache hits for demand metadata, this
matters (is good) for getting filesystem data (ls,find,…)
`arcstats_demand_metadata_misses` Amount of cache misses for demand metadata,
this matters (is bad) for getting filesystem data (ls,find,…)
`arcstats_prefetch_data_hits` The zfs prefetcher tried to prefetch something,
but it was already cached (boring)
`arcstats_prefetch_data_misses` The zfs prefetcher prefetched something which
was not in the cache (good job, could become a demand hit in the future)
`arcstats_prefetch_metadata_hits` Same as above, but for metadata
`arcstats_prefetch_metadata_misses` Same as above, but for metadata
`arcstats_mru_hits` Cache hit in the “most recently used cache”, we move this to
the mfu cache.
`arcstats_mru_ghost_hits` Cache hit in the “most recently used ghost list” we
had this item in the cache, but evicted it, maybe we should increase the mru
cache size.
`arcstats_mfu_hits` Cache hit in the “most frequently used cache” we move this
to the beginning of the mfu cache.
`arcstats_mfu_ghost_hits` Cache hit in the “most frequently used ghost list” we
had this item in the cache, but evicted it, maybe we should increase the mfu
cache size.
`arcstats_allocated` New data is written to the cache.
`arcstats_deleted` Old data is evicted (deleted) from the cache.
`arcstats_evict_l2_cached` We evicted something from the arc, but its still
cached in the l2 if we need it.
`arcstats_evict_l2_eligible` We evicted something from the arc, and its not in
the l2 this is sad. (maybe we hadnt had enough time to store it there)
`arcstats_evict_l2_ineligible` We evicted something which cannot be stored in
the l2. Reasons could be:
- We have multiple pools, we evicted something from a pool without an l2 device.
- The zfs property secondary cache.
`arcstats_c` Arc target size, this is the size the system thinks the arc should
have.
`arcstats_size` Total size of the arc.
`arcstats_l2_hits` Hits to the L2 cache. (It was not in the arc, but in the l2
cache)
`arcstats_l2_misses` Miss to the L2 cache. (It was not in the arc, and not in
the l2 cache)
`arcstats_l2_size` Size of the l2 cache.
`arcstats_l2_hdr_size` Size of the metadata in the arc (ram) used to manage
(lookup if something is in the l2) the l2 cache.
### Zfetch Stats
`zfetchstats_hits` Counts the number of cache hits, to items which are in the
cache because of the prefetcher.
`zfetchstats_misses` Counts the number of prefetch cache misses.
`zfetchstats_colinear_hits` Counts the number of cache hits, to items which are
in the cache because of the prefetcher (prefetched linear reads)
`zfetchstats_stride_hits` Counts the number of cache hits, to items which are in
the cache because of the prefetcher (prefetched stride reads)
### Vdev Cache Stats (FreeBSD only)
note: the vdev cache is deprecated in some ZFS implementations
`vdev_cache_stats_hits` Hits to the vdev (device level) cache.
`vdev_cache_stats_misses` Misses to the vdev (device level) cache.
### ABD Stats (Linux Only)
ABD is a linear/scatter dual typed buffer for ARC
`abdstats_linear_cnt` number of linear ABDs which are currently allocated
`abdstats_linear_data_size` amount of data stored in all linear ABDs
`abdstats_scatter_cnt` number of scatter ABDs which are currently allocated
`abdstats_scatter_data_size` amount of data stored in all scatter ABDs
### DMU Stats (Linux Only)
`dmu_tx_dirty_throttle` counts when writes are throttled due to the amount of
dirty data growing too large
`dmu_tx_memory_reclaim` counts when memory is low and throttling activity
`dmu_tx_memory_reserve` counts when memory footprint of the txg exceeds the ARC
size
### Fault Management Ereport errors (Linux Only)
`fm_erpt-dropped` counts when an error report cannot be created (eg available
memory is too low)
### ZIL (Linux Only)
note: `zil` measurements in `kstatMetrics` are system-wide, in `poolMetrics`
they are pool-wide
`zil_commit_count` counts when ZFS transactions are committed to a ZIL

View file

@ -0,0 +1,20 @@
# Read metrics of ZFS from arcstats, zfetchstats, vdev_cache_stats, pools and datasets
# This plugin ONLY supports Linux & FreeBSD
[[inputs.zfs]]
## ZFS kstat path. Ignored on FreeBSD
## If not specified, then default is:
# kstatPath = "/proc/spl/kstat/zfs"
## By default, telegraf gather all zfs stats
## Override the stats list using the kstatMetrics array:
## For FreeBSD, the default is:
# kstatMetrics = ["arcstats", "zfetchstats", "vdev_cache_stats"]
## For Linux, the default is:
# kstatMetrics = ["abdstats", "arcstats", "dnodestats", "dbufcachestats",
# "dmu_tx", "fm", "vdev_mirror_stats", "zfetchstats", "zil"]
## By default, don't gather zpool stats
# poolMetrics = false
## By default, don't gather dataset stats
# datasetMetrics = false

View file

@ -0,0 +1 @@
zfs,pools=freenas-boot::red1::temp1::temp2 vdev_cache_stats_delegations=6952i,vdev_cache_stats_hits=465583i,vdev_cache_stats_misses=87789i 1698097327984312950

View file

@ -0,0 +1,12 @@
{
"vdev_cache_stats": [
"kstat.zfs.misc.vdev_cache_stats.misses: 87789",
"kstat.zfs.misc.vdev_cache_stats.hits: 465583",
"kstat.zfs.misc.vdev_cache_stats.delegations: 6952"
],
"zfetchstats": [
"kstat.zfs.misc.zfetchstats.max_streams: 0",
"kstat.zfs.misc.zfetchstats.misses: 0",
"kstat.zfs.misc.zfetchstats.hits: 0"
]
}

View file

@ -0,0 +1,2 @@
[[inputs.zfs]]
kstatMetrics = ["vdev_cache_stats"]

View file

@ -0,0 +1,4 @@
freenas-boot ONLINE 30601641984 2022177280 28579464704 - 6 1.00x
red1 ONLINE 8933531975680 1126164848640 7807367127040 8% 12 1.83x
temp1 ONLINE 2989297238016 1626309320704 1362987917312 38% 54 1.28x
temp2 ONLINE 2989297238016 626958278656 2362338959360 12% 20 1.00x

View file

@ -0,0 +1,5 @@
zfs_pool,health=ONLINE,pool=freenas-boot allocated=2022177280i,capacity=6i,dedupratio=1,fragmentation=0i,free=28579464704i,size=30601641984i 1698097244832121819
zfs_pool,health=ONLINE,pool=red1 allocated=1126164848640i,capacity=12i,dedupratio=1.8300000429153442,fragmentation=8i,free=7807367127040i,size=8933531975680i 1698097244832126568
zfs_pool,health=ONLINE,pool=temp1 allocated=1626309320704i,capacity=54i,dedupratio=1.2799999713897705,fragmentation=38i,free=1362987917312i,size=2989297238016i 1698097244832130759
zfs_pool,health=ONLINE,pool=temp2 allocated=626958278656i,capacity=20i,dedupratio=1,fragmentation=12i,free=2362338959360i,size=2989297238016i 1698097244832134111
zfs,pools=freenas-boot::red1::temp1::temp2 vdev_cache_stats_delegations=6952i,vdev_cache_stats_hits=465583i,vdev_cache_stats_misses=87789i 1698097244832209819

View file

@ -0,0 +1,12 @@
{
"vdev_cache_stats": [
"kstat.zfs.misc.vdev_cache_stats.misses: 87789",
"kstat.zfs.misc.vdev_cache_stats.hits: 465583",
"kstat.zfs.misc.vdev_cache_stats.delegations: 6952"
],
"zfetchstats": [
"kstat.zfs.misc.zfetchstats.max_streams: 0",
"kstat.zfs.misc.zfetchstats.misses: 0",
"kstat.zfs.misc.zfetchstats.hits: 0"
]
}

View file

@ -0,0 +1,3 @@
[[inputs.zfs]]
kstatMetrics = ["vdev_cache_stats"]
poolMetrics = true

View file

@ -0,0 +1,4 @@
freenas-boot ONLINE 30601641984 2022177280 28579464704 - 6 1.00x
red1 ONLINE 8933531975680 1126164848640 7807367127040 8% 12 1.83x
temp1 ONLINE 2989297238016 1626309320704 1362987917312 38% 54 1.28x
temp2 ONLINE 2989297238016 626958278656 2362338959360 12% 20 1.00x

View file

@ -0,0 +1 @@
zfs,datasets=zata::zata/home::zata/import::zata/storage vdev_cache_stats_delegations=6952i,vdev_cache_stats_hits=465583i,vdev_cache_stats_misses=87789i 1698161813995801840

View file

@ -0,0 +1,12 @@
{
"vdev_cache_stats": [
"kstat.zfs.misc.vdev_cache_stats.misses: 87789",
"kstat.zfs.misc.vdev_cache_stats.hits: 465583",
"kstat.zfs.misc.vdev_cache_stats.delegations: 6952"
],
"zfetchstats": [
"kstat.zfs.misc.zfetchstats.max_streams: 0",
"kstat.zfs.misc.zfetchstats.misses: 0",
"kstat.zfs.misc.zfetchstats.hits: 0"
]
}

View file

@ -0,0 +1,2 @@
[[inputs.zfs]]
kstatMetrics = ["vdev_cache_stats"]

View file

@ -0,0 +1,4 @@
zata 10741741326336 8564135526400 0 90112
zata/home 10741741326336 2498560 212992 2285568
zata/import 10741741326336 196608 81920 114688
zata/storage 10741741326336 8556084379648 3601138999296 4954945380352

View file

@ -0,0 +1,5 @@
zfs_dataset,dataset=zata avail=10741741326336i,used=8564135526400i,usedds=90112i,usedsnap=0i 1698161697336342048
zfs_dataset,dataset=zata/home avail=10741741326336i,used=2498560i,usedds=2285568i,usedsnap=212992i 1698161697336345401
zfs_dataset,dataset=zata/import avail=10741741326336i,used=196608i,usedds=114688i,usedsnap=81920i 1698161697336348474
zfs_dataset,dataset=zata/storage avail=10741741326336i,used=8556084379648i,usedds=4954945380352i,usedsnap=3601138999296i 1698161697336352944
zfs,datasets=zata::zata/home::zata/import::zata/storage vdev_cache_stats_delegations=6952i,vdev_cache_stats_hits=465583i,vdev_cache_stats_misses=87789i 1698161697336357134

View file

@ -0,0 +1,12 @@
{
"vdev_cache_stats": [
"kstat.zfs.misc.vdev_cache_stats.misses: 87789",
"kstat.zfs.misc.vdev_cache_stats.hits: 465583",
"kstat.zfs.misc.vdev_cache_stats.delegations: 6952"
],
"zfetchstats": [
"kstat.zfs.misc.zfetchstats.max_streams: 0",
"kstat.zfs.misc.zfetchstats.misses: 0",
"kstat.zfs.misc.zfetchstats.hits: 0"
]
}

View file

@ -0,0 +1,3 @@
[[inputs.zfs]]
kstatMetrics = ["vdev_cache_stats"]
datasetMetrics = true

View file

@ -0,0 +1,4 @@
zata 10741741326336 8564135526400 0 90112
zata/home 10741741326336 2498560 212992 2285568
zata/import 10741741326336 196608 81920 114688
zata/storage 10741741326336 8556084379648 3601138999296 4954945380352

View file

@ -0,0 +1,16 @@
zfs_pool,health=ONLINE,pool=zroot allocated=11959578624i,capacity=17i,dedupratio=1,fragmentation=4i,free=55149285376i,size=67108864000i 1698172931876196974
zfs_dataset,dataset=zroot avail=53069045760i,used=11959443456i,usedds=0i,usedsnap=0i 1698172931876204237
zfs_dataset,dataset=zroot/ROOT avail=53069045760i,used=4685123584i,usedds=0i,usedsnap=0i 1698172931876207310
zfs_dataset,dataset=zroot/ROOT/default avail=53069045760i,used=4684689408i,usedds=0i,usedsnap=0i 1698172931876213735
zfs_dataset,dataset=zroot/home avail=53069045760i,used=7263580160i,usedds=0i,usedsnap=0i 1698172931876217926
zfs_dataset,dataset=zroot/tmp avail=53069045760i,used=684032i,usedds=0i,usedsnap=0i 1698172931876220720
zfs_dataset,dataset=zroot/usr avail=53069045760i,used=1724416i,usedds=0i,usedsnap=0i 1698172931876224631
zfs_dataset,dataset=zroot/usr/obj avail=53069045760i,used=430080i,usedds=0i,usedsnap=0i 1698172931876227424
zfs_dataset,dataset=zroot/usr/ports avail=53069045760i,used=430080i,usedds=0i,usedsnap=0i 1698172931876230218
zfs_dataset,dataset=zroot/usr/src avail=53069045760i,used=430080i,usedds=0i,usedsnap=0i 1698172931876233291
zfs_dataset,dataset=zroot/var avail=53069045760i,used=2269184i,usedds=0i,usedsnap=0i 1698172931876237481
zfs_dataset,dataset=zroot/var/audit avail=53069045760i,used=438272i,usedds=0i,usedsnap=0i 1698172931876240554
zfs_dataset,dataset=zroot/var/log avail=53069045760i,used=544768i,usedds=0i,usedsnap=0i 1698172931876243348
zfs_dataset,dataset=zroot/var/mail avail=53069045760i,used=425984i,usedds=0i,usedsnap=0i 1698172931876246980
zfs_dataset,dataset=zroot/var/tmp avail=53069045760i,used=425984i,usedds=0i,usedsnap=0i 1698172931876249774
zfs,datasets=zroot::zroot/ROOT::zroot/ROOT/default::zroot/home::zroot/tmp::zroot/usr::zroot/usr/obj::zroot/usr/ports::zroot/usr/src::zroot/var::zroot/var/audit::zroot/var/log::zroot/var/mail::zroot/var/tmp,pools=zroot zfetchstats_hits=6439i,zfetchstats_io_active=0i,zfetchstats_io_issued=2197i,zfetchstats_max_streams=9411i,zfetchstats_misses=14538i 1698172931876287767

View file

@ -0,0 +1,159 @@
{
"archstats": [
"kstat.zfs.misc.arcstats.abd_chunk_waste_size: 626176",
"kstat.zfs.misc.arcstats.cached_only_in_progress: 0",
"kstat.zfs.misc.arcstats.arc_raw_size: 0",
"kstat.zfs.misc.arcstats.arc_sys_free: 0",
"kstat.zfs.misc.arcstats.arc_need_free: 0",
"kstat.zfs.misc.arcstats.demand_iohit_prescient_prefetch: 1",
"kstat.zfs.misc.arcstats.demand_hit_prescient_prefetch: 14",
"kstat.zfs.misc.arcstats.prescient_prefetch: 15",
"kstat.zfs.misc.arcstats.demand_iohit_predictive_prefetch: 218",
"kstat.zfs.misc.arcstats.demand_hit_predictive_prefetch: 1778",
"kstat.zfs.misc.arcstats.predictive_prefetch: 5099",
"kstat.zfs.misc.arcstats.async_upgrade_sync: 135",
"kstat.zfs.misc.arcstats.arc_dnode_limit: 317881139",
"kstat.zfs.misc.arcstats.arc_meta_used: 80185232",
"kstat.zfs.misc.arcstats.arc_prune: 25",
"kstat.zfs.misc.arcstats.arc_loaned_bytes: 0",
"kstat.zfs.misc.arcstats.arc_tempreserve: 0",
"kstat.zfs.misc.arcstats.arc_no_grow: 0",
"kstat.zfs.misc.arcstats.memory_available_bytes: 3663839232",
"kstat.zfs.misc.arcstats.memory_free_bytes: 3752042496",
"kstat.zfs.misc.arcstats.memory_all_bytes: 4252553216",
"kstat.zfs.misc.arcstats.memory_indirect_count: 0",
"kstat.zfs.misc.arcstats.memory_direct_count: 0",
"kstat.zfs.misc.arcstats.memory_throttle_count: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_log_blks: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_bufs_precached: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_bufs: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_asize: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_size: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_lowmem: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_cksum_lb_errors: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_dh_errors: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_io_errors: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_unsupported: 0",
"kstat.zfs.misc.arcstats.l2_rebuild_success: 0",
"kstat.zfs.misc.arcstats.l2_data_to_meta_ratio: 0",
"kstat.zfs.misc.arcstats.l2_log_blk_count: 0",
"kstat.zfs.misc.arcstats.l2_log_blk_asize: 0",
"kstat.zfs.misc.arcstats.l2_log_blk_avg_asize: 0",
"kstat.zfs.misc.arcstats.l2_log_blk_writes: 0",
"kstat.zfs.misc.arcstats.l2_hdr_size: 0",
"kstat.zfs.misc.arcstats.l2_asize: 0",
"kstat.zfs.misc.arcstats.l2_size: 0",
"kstat.zfs.misc.arcstats.l2_io_error: 0",
"kstat.zfs.misc.arcstats.l2_cksum_bad: 0",
"kstat.zfs.misc.arcstats.l2_abort_lowmem: 0",
"kstat.zfs.misc.arcstats.l2_free_on_write: 0",
"kstat.zfs.misc.arcstats.l2_evict_l1cached: 0",
"kstat.zfs.misc.arcstats.l2_evict_reading: 0",
"kstat.zfs.misc.arcstats.l2_evict_lock_retry: 0",
"kstat.zfs.misc.arcstats.l2_writes_lock_retry: 0",
"kstat.zfs.misc.arcstats.l2_writes_error: 0",
"kstat.zfs.misc.arcstats.l2_writes_done: 0",
"kstat.zfs.misc.arcstats.l2_writes_sent: 0",
"kstat.zfs.misc.arcstats.l2_write_bytes: 0",
"kstat.zfs.misc.arcstats.l2_read_bytes: 0",
"kstat.zfs.misc.arcstats.l2_rw_clash: 0",
"kstat.zfs.misc.arcstats.l2_feeds: 0",
"kstat.zfs.misc.arcstats.l2_bufc_metadata_asize: 0",
"kstat.zfs.misc.arcstats.l2_bufc_data_asize: 0",
"kstat.zfs.misc.arcstats.l2_mfu_asize: 0",
"kstat.zfs.misc.arcstats.l2_mru_asize: 0",
"kstat.zfs.misc.arcstats.l2_prefetch_asize: 0",
"kstat.zfs.misc.arcstats.l2_misses: 0",
"kstat.zfs.misc.arcstats.l2_hits: 0",
"kstat.zfs.misc.arcstats.uncached_evictable_metadata: 0",
"kstat.zfs.misc.arcstats.uncached_evictable_data: 0",
"kstat.zfs.misc.arcstats.uncached_metadata: 0",
"kstat.zfs.misc.arcstats.uncached_data: 0",
"kstat.zfs.misc.arcstats.uncached_size: 0",
"kstat.zfs.misc.arcstats.mfu_ghost_evictable_metadata: 35231232",
"kstat.zfs.misc.arcstats.mfu_ghost_evictable_data: 31780352",
"kstat.zfs.misc.arcstats.mfu_ghost_metadata: 35231232",
"kstat.zfs.misc.arcstats.mfu_ghost_data: 31780352",
"kstat.zfs.misc.arcstats.mfu_ghost_size: 67011584",
"kstat.zfs.misc.arcstats.mfu_evictable_metadata: 648192",
"kstat.zfs.misc.arcstats.mfu_evictable_data: 29985280",
"kstat.zfs.misc.arcstats.mfu_metadata: 9697280",
"kstat.zfs.misc.arcstats.mfu_data: 31448576",
"kstat.zfs.misc.arcstats.mfu_size: 41145856",
"kstat.zfs.misc.arcstats.mru_ghost_evictable_metadata: 27670528",
"kstat.zfs.misc.arcstats.mru_ghost_evictable_data: 39195136",
"kstat.zfs.misc.arcstats.mru_ghost_metadata: 27670528",
"kstat.zfs.misc.arcstats.mru_ghost_data: 39195136",
"kstat.zfs.misc.arcstats.mru_ghost_size: 66865664",
"kstat.zfs.misc.arcstats.mru_evictable_metadata: 4007424",
"kstat.zfs.misc.arcstats.mru_evictable_data: 21310976",
"kstat.zfs.misc.arcstats.mru_metadata: 32238592",
"kstat.zfs.misc.arcstats.mru_data: 25252864",
"kstat.zfs.misc.arcstats.mru_size: 57491456",
"kstat.zfs.misc.arcstats.anon_evictable_metadata: 0",
"kstat.zfs.misc.arcstats.anon_evictable_data: 0",
"kstat.zfs.misc.arcstats.anon_metadata: 0",
"kstat.zfs.misc.arcstats.anon_data: 0",
"kstat.zfs.misc.arcstats.anon_size: 0",
"kstat.zfs.misc.arcstats.other_size: 36376512",
"kstat.zfs.misc.arcstats.bonus_size: 7930560",
"kstat.zfs.misc.arcstats.dnode_size: 20521584",
"kstat.zfs.misc.arcstats.dbuf_size: 7924368",
"kstat.zfs.misc.arcstats.metadata_size: 41935872",
"kstat.zfs.misc.arcstats.data_size: 56701440",
"kstat.zfs.misc.arcstats.hdr_size: 1872848",
"kstat.zfs.misc.arcstats.overhead_size: 29338112",
"kstat.zfs.misc.arcstats.uncompressed_size: 121843712",
"kstat.zfs.misc.arcstats.compressed_size: 69299200",
"kstat.zfs.misc.arcstats.size: 137512848",
"kstat.zfs.misc.arcstats.c_max: 3178811392",
"kstat.zfs.misc.arcstats.c_min: 132892288",
"kstat.zfs.misc.arcstats.c: 176014976",
"kstat.zfs.misc.arcstats.pm: 2306048980",
"kstat.zfs.misc.arcstats.pd: 1302662522",
"kstat.zfs.misc.arcstats.meta: 1110189320",
"kstat.zfs.misc.arcstats.hash_chain_max: 4",
"kstat.zfs.misc.arcstats.hash_chains: 68",
"kstat.zfs.misc.arcstats.hash_collisions: 15034",
"kstat.zfs.misc.arcstats.hash_elements_max: 91215",
"kstat.zfs.misc.arcstats.hash_elements: 7890",
"kstat.zfs.misc.arcstats.evict_l2_skip: 0",
"kstat.zfs.misc.arcstats.evict_l2_ineligible: 65306624",
"kstat.zfs.misc.arcstats.evict_l2_eligible_mru: 1369077760",
"kstat.zfs.misc.arcstats.evict_l2_eligible_mfu: 940835840",
"kstat.zfs.misc.arcstats.evict_l2_eligible: 2309913600",
"kstat.zfs.misc.arcstats.evict_l2_cached: 0",
"kstat.zfs.misc.arcstats.evict_not_enough: 12",
"kstat.zfs.misc.arcstats.evict_skip: 445",
"kstat.zfs.misc.arcstats.access_skip: 0",
"kstat.zfs.misc.arcstats.mutex_miss: 0",
"kstat.zfs.misc.arcstats.deleted: 90151",
"kstat.zfs.misc.arcstats.uncached_hits: 0",
"kstat.zfs.misc.arcstats.mfu_ghost_hits: 6108",
"kstat.zfs.misc.arcstats.mfu_hits: 1240173",
"kstat.zfs.misc.arcstats.mru_ghost_hits: 2692",
"kstat.zfs.misc.arcstats.mru_hits: 233633",
"kstat.zfs.misc.arcstats.prefetch_metadata_misses: 406",
"kstat.zfs.misc.arcstats.prefetch_metadata_iohits: 2315",
"kstat.zfs.misc.arcstats.prefetch_metadata_hits: 196",
"kstat.zfs.misc.arcstats.prefetch_data_misses: 2092",
"kstat.zfs.misc.arcstats.prefetch_data_iohits: 0",
"kstat.zfs.misc.arcstats.prefetch_data_hits: 105",
"kstat.zfs.misc.arcstats.demand_metadata_misses: 12021",
"kstat.zfs.misc.arcstats.demand_metadata_iohits: 87",
"kstat.zfs.misc.arcstats.demand_metadata_hits: 906938",
"kstat.zfs.misc.arcstats.demand_data_misses: 48482",
"kstat.zfs.misc.arcstats.demand_data_iohits: 128",
"kstat.zfs.misc.arcstats.demand_data_hits: 566567",
"kstat.zfs.misc.arcstats.misses: 63001",
"kstat.zfs.misc.arcstats.iohits: 2530",
"kstat.zfs.misc.arcstats.hits: 1473806"
],
"zfetchstats": [
"kstat.zfs.misc.zfetchstats.io_active: 0",
"kstat.zfs.misc.zfetchstats.io_issued: 2197",
"kstat.zfs.misc.zfetchstats.max_streams: 9411",
"kstat.zfs.misc.zfetchstats.misses: 14538",
"kstat.zfs.misc.zfetchstats.hits: 6439"
]
}

View file

@ -0,0 +1,4 @@
[[inputs.zfs]]
kstatMetrics = ["arcstats", "zfetchstats", "vdev_cache_stats"]
poolMetrics = true
datasetMetrics = true

View file

@ -0,0 +1 @@
14.0-RC2

View file

@ -0,0 +1,14 @@
zroot 53069045760 11959443456 - -
zroot/ROOT 53069045760 4685123584 - -
zroot/ROOT/default 53069045760 4684689408 - -
zroot/home 53069045760 7263580160 - -
zroot/tmp 53069045760 684032 - -
zroot/usr 53069045760 1724416 - -
zroot/usr/obj 53069045760 430080 - -
zroot/usr/ports 53069045760 430080 - -
zroot/usr/src 53069045760 430080 - -
zroot/var 53069045760 2269184 - -
zroot/var/audit 53069045760 438272 - -
zroot/var/log 53069045760 544768 - -
zroot/var/mail 53069045760 425984 - -
zroot/var/tmp 53069045760 425984 - -

View file

@ -0,0 +1 @@
zroot ONLINE 67108864000 11959578624 55149285376 4 17 1.00

View file

@ -0,0 +1 @@
zfs,pools=freenas-boot::red1::temp1::temp2 vdev_cache_stats_delegations=6952i,vdev_cache_stats_hits=465583i,vdev_cache_stats_misses=87789i 1698157432411179772

View file

@ -0,0 +1,12 @@
{
"vdev_cache_stats": [
"kstat.zfs.misc.vdev_cache_stats.misses: 87789",
"kstat.zfs.misc.vdev_cache_stats.hits: 465583",
"kstat.zfs.misc.vdev_cache_stats.delegations: 6952"
],
"zfetchstats": [
"kstat.zfs.misc.zfetchstats.max_streams: 0",
"kstat.zfs.misc.zfetchstats.misses: 0",
"kstat.zfs.misc.zfetchstats.hits: 0"
]
}

View file

@ -0,0 +1,2 @@
[[inputs.zfs]]
kstatMetrics = ["vdev_cache_stats"]

View file

@ -0,0 +1,4 @@
freenas-boot ONLINE 30601641984 2022177280 28579464704 - 6 1.00x
red1 ONLINE 8933531975680 1126164848640 7807367127040 8% 12 1.83x
temp1 ONLINE 2989297238016 1626309320704 1362987917312 38% 54 1.28x
temp2 ONLINE 2989297238016 626958278656 2362338959360 12% 20 1.00x

View file

@ -0,0 +1 @@
zfs,pools=freenas-boot::red1::temp1::temp2 vdev_cache_stats_delegations=6952i,vdev_cache_stats_hits=465583i,vdev_cache_stats_misses=87789i,zfetchstats_hits=0i,zfetchstats_max_streams=0i,zfetchstats_misses=0i 1698157264111374629

View file

@ -0,0 +1,12 @@
{
"vdev_cache_stats": [
"kstat.zfs.misc.vdev_cache_stats.misses: 87789",
"kstat.zfs.misc.vdev_cache_stats.hits: 465583",
"kstat.zfs.misc.vdev_cache_stats.delegations: 6952"
],
"zfetchstats": [
"kstat.zfs.misc.zfetchstats.max_streams: 0",
"kstat.zfs.misc.zfetchstats.misses: 0",
"kstat.zfs.misc.zfetchstats.hits: 0"
]
}

View file

@ -0,0 +1,2 @@
[[inputs.zfs]]
kstatMetrics = ["zfetchstats", "vdev_cache_stats"]

View file

@ -0,0 +1,4 @@
freenas-boot ONLINE 30601641984 2022177280 28579464704 - 6 1.00x
red1 ONLINE 8933531975680 1126164848640 7807367127040 8% 12 1.83x
temp1 ONLINE 2989297238016 1626309320704 1362987917312 38% 54 1.28x
temp2 ONLINE 2989297238016 626958278656 2362338959360 12% 20 1.00x

View file

@ -0,0 +1 @@
zfs,pools=temp2 vdev_cache_stats_delegations=6952i,vdev_cache_stats_hits=465583i,vdev_cache_stats_misses=87789i 1698098260907108724

View file

@ -0,0 +1,12 @@
{
"vdev_cache_stats": [
"kstat.zfs.misc.vdev_cache_stats.misses: 87789",
"kstat.zfs.misc.vdev_cache_stats.hits: 465583",
"kstat.zfs.misc.vdev_cache_stats.delegations: 6952"
],
"zfetchstats": [
"kstat.zfs.misc.zfetchstats.max_streams: 0",
"kstat.zfs.misc.zfetchstats.misses: 0",
"kstat.zfs.misc.zfetchstats.hits: 0"
]
}

View file

@ -0,0 +1,2 @@
[[inputs.zfs]]
kstatMetrics = ["vdev_cache_stats"]

View file

@ -0,0 +1 @@
temp2 UNAVAIL - - - - - -

View file

@ -0,0 +1,2 @@
zfs_pool,health=UNAVAIL,pool=temp2 size=0i 1698098260907383061
zfs,pools=temp2 vdev_cache_stats_delegations=6952i,vdev_cache_stats_hits=465583i,vdev_cache_stats_misses=87789i 1698098260907393118

View file

@ -0,0 +1,12 @@
{
"vdev_cache_stats": [
"kstat.zfs.misc.vdev_cache_stats.misses: 87789",
"kstat.zfs.misc.vdev_cache_stats.hits: 465583",
"kstat.zfs.misc.vdev_cache_stats.delegations: 6952"
],
"zfetchstats": [
"kstat.zfs.misc.zfetchstats.max_streams: 0",
"kstat.zfs.misc.zfetchstats.misses: 0",
"kstat.zfs.misc.zfetchstats.hits: 0"
]
}

View file

@ -0,0 +1,3 @@
[[inputs.zfs]]
kstatMetrics = ["vdev_cache_stats"]
poolMetrics = true

View file

@ -0,0 +1 @@
temp2 UNAVAIL - - - - - -

25
plugins/inputs/zfs/zfs.go Normal file
View file

@ -0,0 +1,25 @@
//go:generate ../../../tools/readme_config_includer/generator
package zfs
import (
_ "embed"
"github.com/influxdata/telegraf"
)
//go:embed sample.conf
var sampleConfig string
type Zfs struct {
KstatPath string `toml:"kstatPath"`
KstatMetrics []string `toml:"kstatMetrics"`
PoolMetrics bool `toml:"poolMetrics"`
DatasetMetrics bool `toml:"datasetMetrics"`
Log telegraf.Logger `toml:"-"`
helper //nolint:unused // for OS-specific usage
}
func (*Zfs) SampleConfig() string {
return sampleConfig
}

View file

@ -0,0 +1,274 @@
//go:build freebsd
package zfs
import (
"bytes"
"fmt"
"os/exec"
"strconv"
"strings"
"golang.org/x/sys/unix"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)
type helper struct {
sysctl sysctlF
zpool zpoolF
zdataset zdatasetF
uname unameF
}
type sysctlF func(metric string) ([]string, error)
type zpoolF func() ([]string, error)
type zdatasetF func(properties []string) ([]string, error)
type unameF func() (string, error)
func (z *Zfs) Init() error {
// Determine the kernel version to adapt parsing
release, err := z.uname()
if err != nil {
return fmt.Errorf("determining uname failed: %w", err)
}
parts := strings.SplitN(release, ".", 2)
version, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil {
return fmt.Errorf("determining version from %q failed: %w", release, err)
}
// Setup default metrics if they are not specified.
// Please note that starting from FreeBSD 14 the 'vdev_cache_stats' are
// no longer available.
if len(z.KstatMetrics) == 0 {
if version < 14 {
z.KstatMetrics = []string{"arcstats", "zfetchstats", "vdev_cache_stats"}
} else {
z.KstatMetrics = []string{"arcstats", "zfetchstats"}
}
}
return nil
}
func (z *Zfs) Gather(acc telegraf.Accumulator) error {
tags := map[string]string{}
poolNames, err := z.gatherPoolStats(acc)
if err != nil {
return err
}
if poolNames != "" {
tags["pools"] = poolNames
}
datasetNames, err := z.gatherDatasetStats(acc)
if err != nil {
return err
}
if datasetNames != "" {
tags["datasets"] = datasetNames
}
// Gather information form the kernel using sysctl
fields := make(map[string]interface{})
var removeIndices []int
for i, metric := range z.KstatMetrics {
stdout, err := z.sysctl(metric)
if err != nil {
z.Log.Warnf("sysctl for 'kstat.zfs.misc.%s' failed: %v; removing metric", metric, err)
removeIndices = append(removeIndices, i)
continue
}
for _, line := range stdout {
rawData := strings.Split(line, ": ")
key := metric + "_" + strings.Split(rawData[0], ".")[4]
value, _ := strconv.ParseInt(rawData[1], 10, 64)
fields[key] = value
}
}
acc.AddFields("zfs", fields, tags)
// Remove the invalid kstat metrics
if len(removeIndices) > 0 {
for i := len(removeIndices) - 1; i >= 0; i-- {
idx := removeIndices[i]
z.KstatMetrics = append(z.KstatMetrics[:idx], z.KstatMetrics[idx+1:]...)
}
}
return nil
}
func (z *Zfs) gatherPoolStats(acc telegraf.Accumulator) (string, error) {
lines, err := z.zpool()
if err != nil {
return "", err
}
pools := []string{}
for _, line := range lines {
col := strings.Split(line, "\t")
pools = append(pools, col[0])
}
if !z.PoolMetrics {
return strings.Join(pools, "::"), nil
}
for _, line := range lines {
col := strings.Split(line, "\t")
if len(col) != 8 {
continue
}
tags := map[string]string{"pool": col[0], "health": col[1]}
fields := map[string]interface{}{}
if tags["health"] == "UNAVAIL" {
fields["size"] = int64(0)
} else {
size, err := strconv.ParseInt(col[2], 10, 64)
if err != nil {
return "", fmt.Errorf("Error parsing size: %s", err)
}
fields["size"] = size
alloc, err := strconv.ParseInt(col[3], 10, 64)
if err != nil {
return "", fmt.Errorf("Error parsing allocation: %s", err)
}
fields["allocated"] = alloc
free, err := strconv.ParseInt(col[4], 10, 64)
if err != nil {
return "", fmt.Errorf("Error parsing free: %s", err)
}
fields["free"] = free
frag, err := strconv.ParseInt(strings.TrimSuffix(col[5], "%"), 10, 0)
if err != nil { // This might be - for RO devs
frag = 0
}
fields["fragmentation"] = frag
capval, err := strconv.ParseInt(col[6], 10, 0)
if err != nil {
return "", fmt.Errorf("Error parsing capacity: %s", err)
}
fields["capacity"] = capval
dedup, err := strconv.ParseFloat(strings.TrimSuffix(col[7], "x"), 32)
if err != nil {
return "", fmt.Errorf("Error parsing dedupratio: %s", err)
}
fields["dedupratio"] = dedup
}
acc.AddFields("zfs_pool", fields, tags)
}
return strings.Join(pools, "::"), nil
}
func (z *Zfs) gatherDatasetStats(acc telegraf.Accumulator) (string, error) {
properties := []string{"name", "avail", "used", "usedsnap", "usedds"}
lines, err := z.zdataset(properties)
if err != nil {
return "", err
}
datasets := []string{}
for _, line := range lines {
col := strings.Split(line, "\t")
datasets = append(datasets, col[0])
}
if !z.DatasetMetrics {
return strings.Join(datasets, "::"), nil
}
for _, line := range lines {
col := strings.Split(line, "\t")
if len(col) != len(properties) {
z.Log.Warnf("Invalid number of columns for line: %s", line)
continue
}
tags := map[string]string{"dataset": col[0]}
fields := map[string]interface{}{}
for i, key := range properties[1:] {
// Treat '-' entries as zero
if col[i+1] == "-" {
fields[key] = int64(0)
continue
}
value, err := strconv.ParseInt(col[i+1], 10, 64)
if err != nil {
return "", fmt.Errorf("Error parsing %s %q: %s", key, col[i+1], err)
}
fields[key] = value
}
acc.AddFields("zfs_dataset", fields, tags)
}
return strings.Join(datasets, "::"), nil
}
func run(command string, args ...string) ([]string, error) {
cmd := exec.Command(command, args...)
var outbuf, errbuf bytes.Buffer
cmd.Stdout = &outbuf
cmd.Stderr = &errbuf
err := cmd.Run()
stdout := strings.TrimSpace(outbuf.String())
stderr := strings.TrimSpace(errbuf.String())
if err != nil {
if _, ok := err.(*exec.ExitError); ok {
return nil, fmt.Errorf("%s error: %s", command, stderr)
}
return nil, fmt.Errorf("%s error: %s", command, err)
}
return strings.Split(stdout, "\n"), nil
}
func zpool() ([]string, error) {
return run("zpool", []string{"list", "-Hp", "-o", "name,health,size,alloc,free,fragmentation,capacity,dedupratio"}...)
}
func zdataset(properties []string) ([]string, error) {
return run("zfs", []string{"list", "-Hp", "-t", "filesystem,volume", "-o", strings.Join(properties, ",")}...)
}
func sysctl(metric string) ([]string, error) {
return run("sysctl", []string{"-q", fmt.Sprintf("kstat.zfs.misc.%s", metric)}...)
}
func uname() (string, error) {
var info unix.Utsname
if err := unix.Uname(&info); err != nil {
return "", err
}
release := unix.ByteSliceToString(info.Release[:])
return release, nil
}
func init() {
inputs.Add("zfs", func() telegraf.Input {
return &Zfs{
helper: helper{
sysctl: sysctl,
zpool: zpool,
zdataset: zdataset,
uname: uname,
},
}
})
}

View file

@ -0,0 +1,104 @@
//go:build freebsd
package zfs
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/inputs"
"github.com/influxdata/telegraf/plugins/parsers/influx"
"github.com/influxdata/telegraf/testutil"
)
// Generate testcase-data via
//
// zpool.txt: $ zpool list -Hp -o name,health,size,alloc,free,fragmentation,capacity,dedupratio
// zdataset.txt: $ zfs list -Hp -o name,avail,used,usedsnap,usedds
// sysctl.json: $ sysctl -q kstat.zfs.misc.<kstat metrics>
func TestCases(t *testing.T) {
// Get all testcase directories
testpath := filepath.Join("testcases", "freebsd")
folders, err := os.ReadDir(testpath)
require.NoError(t, err)
// Register the plugin
inputs.Add("zfs", func() telegraf.Input { return &Zfs{} })
for _, f := range folders {
// Only handle folders
if !f.IsDir() {
continue
}
t.Run(f.Name(), func(t *testing.T) {
testcasePath := filepath.Join(testpath, f.Name())
configFilename := filepath.Join(testcasePath, "telegraf.conf")
inputSysctlFilename := filepath.Join(testcasePath, "sysctl.json")
inputZPoolFilename := filepath.Join(testcasePath, "zpool.txt")
inputZDatasetFilename := filepath.Join(testcasePath, "zdataset.txt")
inputUnameFilename := filepath.Join(testcasePath, "uname.txt")
expectedFilename := filepath.Join(testcasePath, "expected.out")
// Load the input data
buf, err := os.ReadFile(inputSysctlFilename)
require.NoError(t, err)
var sysctl map[string][]string
require.NoError(t, json.Unmarshal(buf, &sysctl))
zpool, err := testutil.ParseLinesFromFile(inputZPoolFilename)
require.NoError(t, err)
zdataset, err := testutil.ParseLinesFromFile(inputZDatasetFilename)
require.NoError(t, err)
// Try to read release from file and default to FreeBSD 13 if
// an error occurs.
uname := "13.2-STABLE"
if buf, err := os.ReadFile(inputUnameFilename); err == nil {
uname = string(buf)
}
// Prepare the influx parser for expectations
parser := &influx.Parser{}
require.NoError(t, parser.Init())
// Read the expected output
expected, err := testutil.ParseMetricsFromFile(expectedFilename, parser)
require.NoError(t, err)
// Configure the plugin
cfg := config.NewConfig()
require.NoError(t, cfg.LoadConfig(configFilename))
require.Len(t, cfg.Inputs, 1)
// Setup the plugin
plugin := cfg.Inputs[0].Input.(*Zfs)
plugin.sysctl = func(metric string) ([]string, error) {
if r, found := sysctl[metric]; found {
return r, nil
}
return nil, fmt.Errorf("invalid argument")
}
plugin.zpool = func() ([]string, error) { return zpool, nil }
plugin.zdataset = func(_ []string) ([]string, error) { return zdataset, nil }
plugin.uname = func() (string, error) { return uname, nil }
plugin.Log = testutil.Logger{}
require.NoError(t, plugin.Init())
// Gather and test
var acc testutil.Accumulator
require.NoError(t, plugin.Gather(&acc))
actual := acc.GetTelegrafMetrics()
testutil.RequireMetricsEqual(t, expected, actual, testutil.IgnoreTime())
})
}
}

View file

@ -0,0 +1,245 @@
//go:build linux
package zfs
import (
"errors"
"fmt"
"path/filepath"
"strconv"
"strings"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/internal"
"github.com/influxdata/telegraf/plugins/inputs"
)
const (
unknown metricsVersion = iota
v1
v2
)
type metricsVersion uint8
type poolInfo struct {
name string
ioFilename string
version metricsVersion
}
type helper struct{} //nolint:unused // not used for "linux" OS, needed for Zfs struct
func (z *Zfs) Gather(acc telegraf.Accumulator) error {
kstatMetrics := z.KstatMetrics
if len(kstatMetrics) == 0 {
// vdev_cache_stats is deprecated
// xuio_stats are ignored because as of Sep-2016, no known
// consumers of xuio exist on Linux
kstatMetrics = []string{"abdstats", "arcstats", "dnodestats", "dbufcachestats",
"dmu_tx", "fm", "vdev_mirror_stats", "zfetchstats", "zil"}
}
kstatPath := z.KstatPath
if len(kstatPath) == 0 {
kstatPath = "/proc/spl/kstat/zfs"
}
pools, err := getPools(kstatPath)
tags := getTags(pools)
if z.PoolMetrics && err == nil {
for _, pool := range pools {
err := gatherPoolStats(pool, acc)
if err != nil {
return err
}
}
}
fields := make(map[string]interface{})
for _, metric := range kstatMetrics {
lines, err := internal.ReadLines(kstatPath + "/" + metric)
if err != nil {
continue
}
for i, line := range lines {
if i == 0 || i == 1 {
continue
}
if len(line) < 1 {
continue
}
rawData := strings.Split(line, " ")
key := metric + "_" + rawData[0]
if metric == "zil" || metric == "dmu_tx" || metric == "dnodestats" {
key = rawData[0]
}
rawValue := rawData[len(rawData)-1]
value, err := strconv.ParseInt(rawValue, 10, 64)
if err != nil {
return err
}
fields[key] = value
}
}
acc.AddFields("zfs", fields, tags)
return nil
}
func getPools(kstatPath string) ([]poolInfo, error) {
pools := make([]poolInfo, 0)
version, poolsDirs, err := probeVersion(kstatPath)
if err != nil {
return nil, err
}
for _, poolDir := range poolsDirs {
poolDirSplit := strings.Split(poolDir, "/")
pool := poolDirSplit[len(poolDirSplit)-2]
pools = append(pools, poolInfo{name: pool, ioFilename: poolDir, version: version})
}
return pools, nil
}
func probeVersion(kstatPath string) (metricsVersion, []string, error) {
poolsDirs, err := filepath.Glob(kstatPath + "/*/objset-*")
// From the docs: the only possible returned error is ErrBadPattern, when pattern is malformed.
// Because of this we need to determine how to fallback differently.
if err != nil {
return unknown, poolsDirs, err
}
if len(poolsDirs) > 0 {
return v2, poolsDirs, nil
}
// Fallback to the old kstat in case of an older ZFS version.
poolsDirs, err = filepath.Glob(kstatPath + "/*/io")
if err != nil {
return unknown, poolsDirs, err
}
return v1, poolsDirs, nil
}
func getTags(pools []poolInfo) map[string]string {
poolNames := ""
knownPools := make(map[string]struct{})
for _, entry := range pools {
name := entry.name
if _, ok := knownPools[name]; !ok {
knownPools[name] = struct{}{}
if poolNames != "" {
poolNames += "::"
}
poolNames += name
}
}
return map[string]string{"pools": poolNames}
}
func gatherPoolStats(pool poolInfo, acc telegraf.Accumulator) error {
lines, err := internal.ReadLines(pool.ioFilename)
if err != nil {
return err
}
var fields map[string]interface{}
var gatherErr error
tags := map[string]string{"pool": pool.name}
switch pool.version {
case v1:
fields, gatherErr = gatherV1(lines)
case v2:
fields, gatherErr = gatherV2(lines, tags)
case unknown:
return errors.New("unknown metrics version detected")
}
if gatherErr != nil {
return gatherErr
}
acc.AddFields("zfs_pool", fields, tags)
return nil
}
func gatherV1(lines []string) (map[string]interface{}, error) {
fileLines := 3
keys, values, err := gather(lines, fileLines)
if err != nil {
return nil, err
}
fields := make(map[string]interface{})
for i := 0; i < len(keys); i++ {
value, err := strconv.ParseInt(values[i], 10, 64)
if err != nil {
return nil, err
}
fields[keys[i]] = value
}
return fields, nil
}
func gather(lines []string, fileLines int) (keys, values []string, err error) {
if len(lines) < fileLines {
return nil, nil, errors.New("expected lines in kstat does not match")
}
keys = strings.Fields(lines[1])
values = strings.Fields(lines[2])
if len(keys) != len(values) {
return nil, nil, fmt.Errorf("key and value count don't match Keys:%v Values:%v", keys, values)
}
return keys, values, nil
}
// New way of collection. Each objset-* file in ZFS >= 2.1.x has a format looking like this:
// 36 1 0x01 7 2160 5214787391 73405258558961
// name type data
// dataset_name 7 rpool/ROOT/pve-1
// writes 4 409570
// nwritten 4 2063419969
// reads 4 22108699
// nread 4 63067280992
// nunlinks 4 13849
// nunlinked 4 13848
//
// For explanation of the first line's values see https://github.com/openzfs/zfs/blob/master/module/os/linux/spl/spl-kstat.c#L61
func gatherV2(lines []string, tags map[string]string) (map[string]interface{}, error) {
fileLines := 9
_, _, err := gather(lines, fileLines)
if err != nil {
return nil, err
}
tags["dataset"] = strings.Fields(lines[2])[2]
fields := make(map[string]interface{})
for i := 3; i < len(lines); i++ {
lineFields := strings.Fields(lines[i])
fieldName := lineFields[0]
fieldData := lineFields[2]
value, err := strconv.ParseInt(fieldData, 10, 64)
if err != nil {
return nil, err
}
fields[fieldName] = value
}
return fields, nil
}
func init() {
inputs.Add("zfs", func() telegraf.Input {
return &Zfs{}
})
}

View file

@ -0,0 +1,609 @@
//go:build linux
package zfs
import (
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/testutil"
)
const arcstatsContents = `5 1 0x01 86 4128 23617128247 12081618582809582
name type data
hits 4 5968846374
misses 4 1659178751
demand_data_hits 4 4860247322
demand_data_misses 4 501499535
demand_metadata_hits 4 708608325
demand_metadata_misses 4 156591375
prefetch_data_hits 4 367047144
prefetch_data_misses 4 974529898
prefetch_metadata_hits 4 32943583
prefetch_metadata_misses 4 26557943
mru_hits 4 301176811
mru_ghost_hits 4 47066067
mfu_hits 4 5520612438
mfu_ghost_hits 4 45784009
deleted 4 1718937704
recycle_miss 4 481222994
mutex_miss 4 20575623
evict_skip 4 14655903906543
evict_l2_cached 4 145310202998272
evict_l2_eligible 4 16345402777088
evict_l2_ineligible 4 7437226893312
hash_elements 4 36617980
hash_elements_max 4 36618318
hash_collisions 4 554145157
hash_chains 4 4187651
hash_chain_max 4 26
p 4 13963222064
c 4 16381258376
c_min 4 4194304
c_max 4 16884125696
size 4 16319887096
hdr_size 4 42567864
data_size 4 60066304
meta_size 4 1701534208
other_size 4 1661543168
anon_size 4 94720
anon_evict_data 4 0
anon_evict_metadata 4 0
mru_size 4 973099008
mru_evict_data 4 9175040
mru_evict_metadata 4 32768
mru_ghost_size 4 32768
mru_ghost_evict_data 4 0
mru_ghost_evict_metadata 4 32768
mfu_size 4 788406784
mfu_evict_data 4 50881024
mfu_evict_metadata 4 81920
mfu_ghost_size 4 0
mfu_ghost_evict_data 4 0
mfu_ghost_evict_metadata 4 0
l2_hits 4 573868618
l2_misses 4 1085309718
l2_feeds 4 12182087
l2_rw_clash 4 9610
l2_read_bytes 4 32695938336768
l2_write_bytes 4 2826774778880
l2_writes_sent 4 4267687
l2_writes_done 4 4267687
l2_writes_error 4 0
l2_writes_hdr_miss 4 164
l2_evict_lock_retry 4 5
l2_evict_reading 4 0
l2_free_on_write 4 1606914
l2_cdata_free_on_write 4 1775
l2_abort_lowmem 4 83462
l2_cksum_bad 4 393860640
l2_io_error 4 53881460
l2_size 4 2471466648576
l2_asize 4 2461690072064
l2_hdr_size 4 12854175552
l2_compress_successes 4 12184849
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 5159942
memory_indirect_count 4 3034640
arc_no_grow 4 0
arc_tempreserve 4 0
arc_loaned_bytes 4 0
arc_prune 4 114554259559
arc_meta_used 4 16259820792
arc_meta_limit 4 12663094272
arc_meta_max 4 18327165696
`
const zfetchstatsContents = `3 1 0x01 11 528 23607270446 12081656848148208
name type data
hits 4 7812959060
misses 4 4154484207
colinear_hits 4 1366368
colinear_misses 4 4153117839
stride_hits 4 7309776732
stride_misses 4 222766182
reclaim_successes 4 107788388
reclaim_failures 4 4045329451
streams_resets 4 20989756
streams_noresets 4 503182328
bogus_streams 4 0
`
const poolIoContents = `11 3 0x00 1 80 2225326830828 32953476980628
nread nwritten reads writes wtime wlentime wupdate rtime rlentime rupdate wcnt rcnt
1884160 6450688 22 978 272187126 2850519036 2263669418655 424226814 2850519036 2263669871823 0 0
`
const objsetContents = `36 1 0x01 7 2160 5214787391 74985931356512
name type data
dataset_name 7 HOME
writes 4 978
nwritten 4 6450688
reads 4 22
nread 4 1884160
nunlinks 4 14148
nunlinked 4 14147
`
const objsetV22Contents = `36 1 0x01 7 2160 5214787391 74985931356512
name type data
dataset_name 7 HOMEV22
writes 4 978
nwritten 4 6450688
reads 4 22
nread 4 1884160
nunlinks 4 14148
nunlinked 4 14147
zil_commit_count 4 1
zil_commit_writer_count 4 2
zil_itx_count 4 3
zil_itx_indirect_count 4 4
zil_itx_indirect_bytes 4 5
zil_itx_copied_count 4 6
zil_itx_copied_bytes 4 7
zil_itx_needcopy_count 4 8
zil_itx_needcopy_bytes 4 9
zil_itx_metaslab_normal_count 4 10
zil_itx_metaslab_normal_bytes 4 11
zil_itx_metaslab_normal_write 4 12
zil_itx_metaslab_normal_alloc 4 13
zil_itx_metaslab_slog_count 4 14
zil_itx_metaslab_slog_bytes 4 15
zil_itx_metaslab_slog_write 4 16
zil_itx_metaslab_slog_alloc 4 17
`
const zilContents = `7 1 0x01 14 672 34118481334 437444452158445
name type data
zil_commit_count 4 77
zil_commit_writer_count 4 77
zil_itx_count 4 1
zil_itx_indirect_count 4 2
zil_itx_indirect_bytes 4 3
zil_itx_copied_count 4 4
zil_itx_copied_bytes 4 5
zil_itx_needcopy_count 4 6
zil_itx_needcopy_bytes 4 7
zil_itx_metaslab_normal_count 4 8
zil_itx_metaslab_normal_bytes 4 9
zil_itx_metaslab_slog_count 4 10
zil_itx_metaslab_slog_bytes 4 11
`
const fmContents = `0 1 0x01 4 192 34087340971 437562103532892
name type data
erpt-dropped 4 101
erpt-set-failed 4 202
fmri-set-failed 4 303
payload-set-failed 4 404
`
const dmuTxContents = `5 1 0x01 11 528 34103260832 437683925071438
name type data
dmu_tx_assigned 4 39321636
dmu_tx_delay 4 111
dmu_tx_error 4 222
dmu_tx_suspended 4 333
dmu_tx_group 4 444
dmu_tx_memory_reserve 4 555
dmu_tx_memory_reclaim 4 666
dmu_tx_dirty_throttle 4 777
dmu_tx_dirty_delay 4 888
dmu_tx_dirty_over_max 4 999
dmu_tx_quota 4 101010
`
const abdstatsContents = `7 1 0x01 21 1008 25476602923533 29223577332204
name type data
struct_size 4 33840
linear_cnt 4 834
linear_data_size 4 989696
scatter_cnt 4 12
scatter_data_size 4 187904
scatter_chunk_waste 4 4608
scatter_order_0 4 1
scatter_order_1 4 21
scatter_order_2 4 11
scatter_order_3 4 33
scatter_order_4 4 44
scatter_order_5 4 76
scatter_order_6 4 489
scatter_order_7 4 237483
scatter_order_8 4 233
scatter_order_9 4 4411
scatter_order_10 4 1023
scatter_page_multi_chunk 4 32122
scatter_page_multi_zone 4 9930
scatter_page_alloc_retry 4 99311
scatter_sg_table_retry 4 99221
`
func TestZfsPoolMetrics(t *testing.T) {
tmpDir := t.TempDir()
testKstatPath := tmpDir + "/telegraf/proc/spl/kstat/zfs"
err := os.MkdirAll(testKstatPath, 0750)
require.NoError(t, err)
err = os.MkdirAll(testKstatPath+"/HOME", 0750)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/HOME/io", []byte(poolIoContents), 0640)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/arcstats", []byte(arcstatsContents), 0640)
require.NoError(t, err)
poolMetrics := getPoolMetrics()
var acc testutil.Accumulator
z := &Zfs{KstatPath: testKstatPath, KstatMetrics: []string{"arcstats"}}
err = z.Gather(&acc)
require.NoError(t, err)
require.False(t, acc.HasMeasurement("zfs_pool"))
acc.Metrics = nil
z = &Zfs{KstatPath: testKstatPath, KstatMetrics: []string{"arcstats"}, PoolMetrics: true}
err = z.Gather(&acc)
require.NoError(t, err)
// one pool, all metrics
tags := map[string]string{
"pool": "HOME",
}
acc.AssertContainsTaggedFields(t, "zfs_pool", poolMetrics, tags)
err = os.WriteFile(testKstatPath+"/HOME/objset-0x20a", []byte(objsetContents), 0640)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/HOME/objset-0x20b", []byte(objsetV22Contents), 0640)
require.NoError(t, err)
acc.Metrics = nil
err = z.Gather(&acc)
require.NoError(t, err)
tags["dataset"] = "HOME"
poolMetrics = getPoolMetricsNewFormat()
acc.AssertContainsTaggedFields(t, "zfs_pool", poolMetrics, tags)
tags["dataset"] = "HOMEV22"
poolMetrics = getPoolMetricsNewFormatV22()
acc.AssertContainsTaggedFields(t, "zfs_pool", poolMetrics, tags)
}
func TestZfsGeneratesMetrics(t *testing.T) {
tmpDir := t.TempDir()
testKstatPath := tmpDir + "/telegraf/proc/spl/kstat/zfs"
err := os.MkdirAll(testKstatPath, 0750)
require.NoError(t, err)
err = os.MkdirAll(testKstatPath, 0750)
require.NoError(t, err)
err = os.MkdirAll(testKstatPath+"/HOME", 0750)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/HOME/io", []byte(""), 0640)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/arcstats", []byte(arcstatsContents), 0640)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/zfetchstats", []byte(zfetchstatsContents), 0640)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/zil", []byte(zilContents), 0640)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/fm", []byte(fmContents), 0640)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/dmu_tx", []byte(dmuTxContents), 0640)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/abdstats", []byte(abdstatsContents), 0640)
require.NoError(t, err)
intMetrics := getKstatMetricsAll()
var acc testutil.Accumulator
// one pool, all metrics
tags := map[string]string{
"pools": "HOME",
}
z := &Zfs{KstatPath: testKstatPath}
err = z.Gather(&acc)
require.NoError(t, err)
acc.AssertContainsTaggedFields(t, "zfs", intMetrics, tags)
acc.Metrics = nil
// two pools, all metrics
err = os.MkdirAll(testKstatPath+"/STORAGE", 0750)
require.NoError(t, err)
err = os.WriteFile(testKstatPath+"/STORAGE/io", []byte(""), 0640)
require.NoError(t, err)
tags = map[string]string{
"pools": "HOME::STORAGE",
}
z = &Zfs{KstatPath: testKstatPath}
acc2 := testutil.Accumulator{}
err = z.Gather(&acc2)
require.NoError(t, err)
acc2.AssertContainsTaggedFields(t, "zfs", intMetrics, tags)
acc2.Metrics = nil
intMetrics = getKstatMetricsArcOnly()
// two pools, one metric
z = &Zfs{KstatPath: testKstatPath, KstatMetrics: []string{"arcstats"}}
acc3 := testutil.Accumulator{}
err = z.Gather(&acc3)
require.NoError(t, err)
acc3.AssertContainsTaggedFields(t, "zfs", intMetrics, tags)
}
func TestGetTags(t *testing.T) {
tests := []struct {
name string
pools []poolInfo
expected map[string]string
}{
{
name: "no pools",
expected: map[string]string{"pools": ""},
},
{
name: "single pool",
pools: []poolInfo{
{"data", "/proc/spl/kstat/zfs/data/objset-0x9288", v2},
},
expected: map[string]string{"pools": "data"},
},
{
name: "duplicate pool names",
pools: []poolInfo{
{"pool", "/proc/spl/kstat/zfs/pool/objset-0x23ce1", v2},
{"pool", "/proc/spl/kstat/zfs/pool/objset-0x2e", v2},
{"data", "/proc/spl/kstat/zfs/data/objset-0x9288", v2},
},
expected: map[string]string{"pools": "pool::data"},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
tags := getTags(tc.pools)
require.Equal(t, tc.expected, tags)
})
}
}
func getKstatMetricsArcOnly() map[string]interface{} {
return map[string]interface{}{
"arcstats_hits": int64(5968846374),
"arcstats_misses": int64(1659178751),
"arcstats_demand_data_hits": int64(4860247322),
"arcstats_demand_data_misses": int64(501499535),
"arcstats_demand_metadata_hits": int64(708608325),
"arcstats_demand_metadata_misses": int64(156591375),
"arcstats_prefetch_data_hits": int64(367047144),
"arcstats_prefetch_data_misses": int64(974529898),
"arcstats_prefetch_metadata_hits": int64(32943583),
"arcstats_prefetch_metadata_misses": int64(26557943),
"arcstats_mru_hits": int64(301176811),
"arcstats_mru_ghost_hits": int64(47066067),
"arcstats_mfu_hits": int64(5520612438),
"arcstats_mfu_ghost_hits": int64(45784009),
"arcstats_deleted": int64(1718937704),
"arcstats_recycle_miss": int64(481222994),
"arcstats_mutex_miss": int64(20575623),
"arcstats_evict_skip": int64(14655903906543),
"arcstats_evict_l2_cached": int64(145310202998272),
"arcstats_evict_l2_eligible": int64(16345402777088),
"arcstats_evict_l2_ineligible": int64(7437226893312),
"arcstats_hash_elements": int64(36617980),
"arcstats_hash_elements_max": int64(36618318),
"arcstats_hash_collisions": int64(554145157),
"arcstats_hash_chains": int64(4187651),
"arcstats_hash_chain_max": int64(26),
"arcstats_p": int64(13963222064),
"arcstats_c": int64(16381258376),
"arcstats_c_min": int64(4194304),
"arcstats_c_max": int64(16884125696),
"arcstats_size": int64(16319887096),
"arcstats_hdr_size": int64(42567864),
"arcstats_data_size": int64(60066304),
"arcstats_meta_size": int64(1701534208),
"arcstats_other_size": int64(1661543168),
"arcstats_anon_size": int64(94720),
"arcstats_anon_evict_data": int64(0),
"arcstats_anon_evict_metadata": int64(0),
"arcstats_mru_size": int64(973099008),
"arcstats_mru_evict_data": int64(9175040),
"arcstats_mru_evict_metadata": int64(32768),
"arcstats_mru_ghost_size": int64(32768),
"arcstats_mru_ghost_evict_data": int64(0),
"arcstats_mru_ghost_evict_metadata": int64(32768),
"arcstats_mfu_size": int64(788406784),
"arcstats_mfu_evict_data": int64(50881024),
"arcstats_mfu_evict_metadata": int64(81920),
"arcstats_mfu_ghost_size": int64(0),
"arcstats_mfu_ghost_evict_data": int64(0),
"arcstats_mfu_ghost_evict_metadata": int64(0),
"arcstats_l2_hits": int64(573868618),
"arcstats_l2_misses": int64(1085309718),
"arcstats_l2_feeds": int64(12182087),
"arcstats_l2_rw_clash": int64(9610),
"arcstats_l2_read_bytes": int64(32695938336768),
"arcstats_l2_write_bytes": int64(2826774778880),
"arcstats_l2_writes_sent": int64(4267687),
"arcstats_l2_writes_done": int64(4267687),
"arcstats_l2_writes_error": int64(0),
"arcstats_l2_writes_hdr_miss": int64(164),
"arcstats_l2_evict_lock_retry": int64(5),
"arcstats_l2_evict_reading": int64(0),
"arcstats_l2_free_on_write": int64(1606914),
"arcstats_l2_cdata_free_on_write": int64(1775),
"arcstats_l2_abort_lowmem": int64(83462),
"arcstats_l2_cksum_bad": int64(393860640),
"arcstats_l2_io_error": int64(53881460),
"arcstats_l2_size": int64(2471466648576),
"arcstats_l2_asize": int64(2461690072064),
"arcstats_l2_hdr_size": int64(12854175552),
"arcstats_l2_compress_successes": int64(12184849),
"arcstats_l2_compress_zeros": int64(0),
"arcstats_l2_compress_failures": int64(0),
"arcstats_memory_throttle_count": int64(0),
"arcstats_duplicate_buffers": int64(0),
"arcstats_duplicate_buffers_size": int64(0),
"arcstats_duplicate_reads": int64(0),
"arcstats_memory_direct_count": int64(5159942),
"arcstats_memory_indirect_count": int64(3034640),
"arcstats_arc_no_grow": int64(0),
"arcstats_arc_tempreserve": int64(0),
"arcstats_arc_loaned_bytes": int64(0),
"arcstats_arc_prune": int64(114554259559),
"arcstats_arc_meta_used": int64(16259820792),
"arcstats_arc_meta_limit": int64(12663094272),
"arcstats_arc_meta_max": int64(18327165696),
}
}
func getKstatMetricsAll() map[string]interface{} {
otherMetrics := map[string]interface{}{
"zfetchstats_hits": int64(7812959060),
"zfetchstats_misses": int64(4154484207),
"zfetchstats_colinear_hits": int64(1366368),
"zfetchstats_colinear_misses": int64(4153117839),
"zfetchstats_stride_hits": int64(7309776732),
"zfetchstats_stride_misses": int64(222766182),
"zfetchstats_reclaim_successes": int64(107788388),
"zfetchstats_reclaim_failures": int64(4045329451),
"zfetchstats_streams_resets": int64(20989756),
"zfetchstats_streams_noresets": int64(503182328),
"zfetchstats_bogus_streams": int64(0),
"zil_commit_count": int64(77),
"zil_commit_writer_count": int64(77),
"zil_itx_count": int64(1),
"zil_itx_indirect_count": int64(2),
"zil_itx_indirect_bytes": int64(3),
"zil_itx_copied_count": int64(4),
"zil_itx_copied_bytes": int64(5),
"zil_itx_needcopy_count": int64(6),
"zil_itx_needcopy_bytes": int64(7),
"zil_itx_metaslab_normal_count": int64(8),
"zil_itx_metaslab_normal_bytes": int64(9),
"zil_itx_metaslab_slog_count": int64(10),
"zil_itx_metaslab_slog_bytes": int64(11),
"fm_erpt-dropped": int64(101),
"fm_erpt-set-failed": int64(202),
"fm_fmri-set-failed": int64(303),
"fm_payload-set-failed": int64(404),
"dmu_tx_assigned": int64(39321636),
"dmu_tx_delay": int64(111),
"dmu_tx_error": int64(222),
"dmu_tx_suspended": int64(333),
"dmu_tx_group": int64(444),
"dmu_tx_memory_reserve": int64(555),
"dmu_tx_memory_reclaim": int64(666),
"dmu_tx_dirty_throttle": int64(777),
"dmu_tx_dirty_delay": int64(888),
"dmu_tx_dirty_over_max": int64(999),
"dmu_tx_quota": int64(101010),
"abdstats_struct_size": int64(33840),
"abdstats_linear_cnt": int64(834),
"abdstats_linear_data_size": int64(989696),
"abdstats_scatter_cnt": int64(12),
"abdstats_scatter_data_size": int64(187904),
"abdstats_scatter_chunk_waste": int64(4608),
"abdstats_scatter_order_0": int64(1),
"abdstats_scatter_order_1": int64(21),
"abdstats_scatter_order_2": int64(11),
"abdstats_scatter_order_3": int64(33),
"abdstats_scatter_order_4": int64(44),
"abdstats_scatter_order_5": int64(76),
"abdstats_scatter_order_6": int64(489),
"abdstats_scatter_order_7": int64(237483),
"abdstats_scatter_order_8": int64(233),
"abdstats_scatter_order_9": int64(4411),
"abdstats_scatter_order_10": int64(1023),
"abdstats_scatter_page_multi_chunk": int64(32122),
"abdstats_scatter_page_multi_zone": int64(9930),
"abdstats_scatter_page_alloc_retry": int64(99311),
"abdstats_scatter_sg_table_retry": int64(99221),
}
arcMetrics := getKstatMetricsArcOnly()
for k, v := range otherMetrics {
arcMetrics[k] = v
}
return arcMetrics
}
func getPoolMetrics() map[string]interface{} {
return map[string]interface{}{
"nread": int64(1884160),
"nwritten": int64(6450688),
"reads": int64(22),
"writes": int64(978),
"wtime": int64(272187126),
"wlentime": int64(2850519036),
"wupdate": int64(2263669418655),
"rtime": int64(424226814),
"rlentime": int64(2850519036),
"rupdate": int64(2263669871823),
"wcnt": int64(0),
"rcnt": int64(0),
}
}
func getPoolMetricsNewFormat() map[string]interface{} {
return map[string]interface{}{
"nread": int64(1884160),
"nunlinked": int64(14147),
"nunlinks": int64(14148),
"nwritten": int64(6450688),
"reads": int64(22),
"writes": int64(978),
}
}
func getPoolMetricsNewFormatV22() map[string]interface{} {
return map[string]interface{}{
"nread": int64(1884160),
"nunlinked": int64(14147),
"nunlinks": int64(14148),
"nwritten": int64(6450688),
"reads": int64(22),
"writes": int64(978),
"zil_commit_count": int64(1),
"zil_commit_writer_count": int64(2),
"zil_itx_count": int64(3),
"zil_itx_indirect_count": int64(4),
"zil_itx_indirect_bytes": int64(5),
"zil_itx_copied_count": int64(6),
"zil_itx_copied_bytes": int64(7),
"zil_itx_needcopy_count": int64(8),
"zil_itx_needcopy_bytes": int64(9),
"zil_itx_metaslab_normal_count": int64(10),
"zil_itx_metaslab_normal_bytes": int64(11),
"zil_itx_metaslab_normal_write": int64(12),
"zil_itx_metaslab_normal_alloc": int64(13),
"zil_itx_metaslab_slog_count": int64(14),
"zil_itx_metaslab_slog_bytes": int64(15),
"zil_itx_metaslab_slog_write": int64(16),
"zil_itx_metaslab_slog_alloc": int64(17),
}
}

View file

@ -0,0 +1,25 @@
//go:build !linux && !freebsd
package zfs
import (
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)
type helper struct{} //nolint:unused // not used for "other" OSes, needed for Zfs struct
func (z *Zfs) Init() error {
z.Log.Warn("Current platform is not supported")
return nil
}
func (*Zfs) Gather(telegraf.Accumulator) error {
return nil
}
func init() {
inputs.Add("zfs", func() telegraf.Input {
return &Zfs{}
})
}