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,458 @@
# sysstat Input Plugin
Collect [sysstat](https://github.com/sysstat/sysstat) metrics - requires the
sysstat package installed.
This plugin collects system metrics with the sysstat collector utility `sadc`
and parses the created binary data file with the `sadf` utility.
## 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
# Sysstat metrics collector
# This plugin ONLY supports Linux
[[inputs.sysstat]]
## Path to the sadc command.
#
## Common Defaults:
## Debian/Ubuntu: /usr/lib/sysstat/sadc
## Arch: /usr/lib/sa/sadc
## RHEL/CentOS: /usr/lib64/sa/sadc
sadc_path = "/usr/lib/sa/sadc" # required
## Path to the sadf command, if it is not in PATH
# sadf_path = "/usr/bin/sadf"
## Activities is a list of activities, that are passed as argument to the
## sadc collector utility (e.g: DISK, SNMP etc...)
## The more activities that are added, the more data is collected.
# activities = ["DISK"]
## Group metrics to measurements.
##
## If group is false each metric will be prefixed with a description
## and represents itself a measurement.
##
## If Group is true, corresponding metrics are grouped to a single measurement.
# group = true
## Options for the sadf command. The values on the left represent the sadf options and
## the values on the right their description (which are used for grouping and prefixing metrics).
##
## Run 'sar -h' or 'man sar' to find out the supported options for your sysstat version.
[inputs.sysstat.options]
-C = "cpu"
-B = "paging"
-b = "io"
-d = "disk" # requires DISK activity
"-n ALL" = "network"
"-P ALL" = "per_cpu"
-q = "queue"
-R = "mem"
-r = "mem_util"
-S = "swap_util"
-u = "cpu_util"
-v = "inode"
-W = "swap"
-w = "task"
# -H = "hugepages" # only available for newer linux distributions
# "-I ALL" = "interrupts" # requires INT activity
## Device tags can be used to add additional tags for devices. For example the configuration below
## adds a tag vg with value rootvg for all metrics with sda devices.
# [[inputs.sysstat.device_tags.sda]]
# vg = "rootvg"
```
## Metrics
### If group=true
- cpu
- pct_idle (float)
- pct_iowait (float)
- pct_nice (float)
- pct_steal (float)
- pct_system (float)
- pct_user (float)
- disk
- avgqu-sz (float)
- avgrq-sz (float)
- await (float)
- pct_util (float)
- rd_sec_pers (float)
- svctm (float)
- tps (float)
And much more, depending on the options you configure.
### If group=false
- cpu_pct_idle
- value (float)
- cpu_pct_iowait
- value (float)
- cpu_pct_nice
- value (float)
- cpu_pct_steal
- value (float)
- cpu_pct_system
- value (float)
- cpu_pct_user
- value (float)
- disk_avgqu-sz
- value (float)
- disk_avgrq-sz
- value (float)
- disk_await
- value (float)
- disk_pct_util
- value (float)
- disk_rd_sec_per_s
- value (float)
- disk_svctm
- value (float)
- disk_tps
- value (float)
And much more, depending on the options you configure.
### Tags
- All measurements have the following tags:
- device
And more if you define some `device_tags`.
## Example Output
With the configuration below:
```toml
[[inputs.sysstat]]
sadc_path = "/usr/lib/sa/sadc" # required
activities = ["DISK", "SNMP", "INT"]
group = true
[inputs.sysstat.options]
-C = "cpu"
-B = "paging"
-b = "io"
-d = "disk" # requires DISK activity
-H = "hugepages"
"-I ALL" = "interrupts" # requires INT activity
"-n ALL" = "network"
"-P ALL" = "per_cpu"
-q = "queue"
-R = "mem"
"-r ALL" = "mem_util"
-S = "swap_util"
-u = "cpu_util"
-v = "inode"
-W = "swap"
-w = "task"
[[inputs.sysstat.device_tags.sda]]
vg = "rootvg"
```
you get the following output:
```text
cpu_util,device=all pct_idle=98.85,pct_iowait=0,pct_nice=0.38,pct_steal=0,pct_system=0.64,pct_user=0.13 1459255626657883725
swap pswpin_per_s=0,pswpout_per_s=0 1459255626658387650
per_cpu,device=cpu1 pct_idle=98.98,pct_iowait=0,pct_nice=0.26,pct_steal=0,pct_system=0.51,pct_user=0.26 1459255626659630437
per_cpu,device=all pct_idle=98.85,pct_iowait=0,pct_nice=0.38,pct_steal=0,pct_system=0.64,pct_user=0.13 1459255626659670744
per_cpu,device=cpu0 pct_idle=98.73,pct_iowait=0,pct_nice=0.76,pct_steal=0,pct_system=0.51,pct_user=0 1459255626659697515
hugepages kbhugfree=0,kbhugused=0,pct_hugused=0 1459255626660057517
network,device=lo coll_per_s=0,pct_ifutil=0,rxcmp_per_s=0,rxdrop_per_s=0,rxerr_per_s=0,rxfifo_per_s=0,rxfram_per_s=0,rxkB_per_s=0.81,rxmcst_per_s=0,rxpck_per_s=16,txcarr_per_s=0,txcmp_per_s=0,txdrop_per_s=0,txerr_per_s=0,txfifo_per_s=0,txkB_per_s=0.81,txpck_per_s=16 1459255626661197666
network access_per_s=0,active_per_s=0,asmf_per_s=0,asmok_per_s=0,asmrq_per_s=0,atmptf_per_s=0,badcall_per_s=0,call_per_s=0,estres_per_s=0,fragcrt_per_s=0,fragf_per_s=0,fragok_per_s=0,fwddgm_per_s=0,getatt_per_s=0,hit_per_s=0,iadrerr_per_s=0,iadrmk_per_s=0,iadrmkr_per_s=0,idel_per_s=16,idgm_per_s=0,idgmerr_per_s=0,idisc_per_s=0,idstunr_per_s=0,iech_per_s=0,iechr_per_s=0,ierr_per_s=0,ihdrerr_per_s=0,imsg_per_s=0,ip-frag=0,iparmpb_per_s=0,irec_per_s=16,iredir_per_s=0,iseg_per_s=16,isegerr_per_s=0,isrcq_per_s=0,itm_per_s=0,itmex_per_s=0,itmr_per_s=0,iukwnpr_per_s=0,miss_per_s=0,noport_per_s=0,oadrmk_per_s=0,oadrmkr_per_s=0,odgm_per_s=0,odisc_per_s=0,odstunr_per_s=0,oech_per_s=0,oechr_per_s=0,oerr_per_s=0,omsg_per_s=0,onort_per_s=0,oparmpb_per_s=0,oredir_per_s=0,orq_per_s=16,orsts_per_s=0,oseg_per_s=16,osrcq_per_s=0,otm_per_s=0,otmex_per_s=0,otmr_per_s=0,packet_per_s=0,passive_per_s=0,rawsck=0,read_per_s=0,retrans_per_s=0,saccess_per_s=0,scall_per_s=0,sgetatt_per_s=0,sread_per_s=0,swrite_per_s=0,tcp-tw=7,tcp_per_s=0,tcpsck=1543,totsck=4052,udp_per_s=0,udpsck=2,write_per_s=0 1459255626661381788
network,device=ens33 coll_per_s=0,pct_ifutil=0,rxcmp_per_s=0,rxdrop_per_s=0,rxerr_per_s=0,rxfifo_per_s=0,rxfram_per_s=0,rxkB_per_s=0,rxmcst_per_s=0,rxpck_per_s=0,txcarr_per_s=0,txcmp_per_s=0,txdrop_per_s=0,txerr_per_s=0,txfifo_per_s=0,txkB_per_s=0,txpck_per_s=0 1459255626661533072
disk,device=sda,vg=rootvg avgqu-sz=0.01,avgrq-sz=8.5,await=3.31,pct_util=0.1,rd_sec_per_s=0,svctm=0.25,tps=4,wr_sec_per_s=34 1459255626663974389
queue blocked=0,ldavg-1=1.61,ldavg-15=1.34,ldavg-5=1.67,plist-sz=1415,runq-sz=0 1459255626664159054
paging fault_per_s=0.25,majflt_per_s=0,pct_vmeff=0,pgfree_per_s=19,pgpgin_per_s=0,pgpgout_per_s=17,pgscand_per_s=0,pgscank_per_s=0,pgsteal_per_s=0 1459255626664304249
mem_util kbactive=2206568,kbanonpg=1472208,kbbuffers=118020,kbcached=1035252,kbcommit=8717200,kbdirty=156,kbinact=418912,kbkstack=24672,kbmemfree=1744868,kbmemused=3610272,kbpgtbl=87116,kbslab=233804,kbvmused=0,pct_commit=136.13,pct_memused=67.42 1459255626664554981
io bread_per_s=0,bwrtn_per_s=34,rtps=0,tps=4,wtps=4 1459255626664596198
inode dentunusd=235039,file-nr=17120,inode-nr=94505,pty-nr=14 1459255626664663693
interrupts,device=i000 intr_per_s=0 1459255626664800109
interrupts,device=i003 intr_per_s=0 1459255626665255145
interrupts,device=i004 intr_per_s=0 1459255626665281776
interrupts,device=i006 intr_per_s=0 1459255626665297416
interrupts,device=i007 intr_per_s=0 1459255626665321008
interrupts,device=i010 intr_per_s=0 1459255626665339413
interrupts,device=i012 intr_per_s=0 1459255626665361510
interrupts,device=i013 intr_per_s=0 1459255626665381327
interrupts,device=i015 intr_per_s=1 1459255626665397313
interrupts,device=i001 intr_per_s=0.25 1459255626665412985
interrupts,device=i002 intr_per_s=0 1459255626665430475
interrupts,device=i005 intr_per_s=0 1459255626665453944
interrupts,device=i008 intr_per_s=0 1459255626665470650
interrupts,device=i011 intr_per_s=0 1459255626665486069
interrupts,device=i009 intr_per_s=0 1459255626665502913
interrupts,device=i014 intr_per_s=0 1459255626665518152
task cswch_per_s=722.25,proc_per_s=0 1459255626665849646
cpu,device=all pct_idle=98.85,pct_iowait=0,pct_nice=0.38,pct_steal=0,pct_system=0.64,pct_user=0.13 1459255626666639715
mem bufpg_per_s=0,campg_per_s=1.75,frmpg_per_s=-8.25 1459255626666770205
swap_util kbswpcad=0,kbswpfree=1048572,kbswpused=0,pct_swpcad=0,pct_swpused=0 1459255626667313276
```
If you change the group value to false like below:
```toml
[[inputs.sysstat]]
sadc_path = "/usr/lib/sa/sadc" # required
activities = ["DISK", "SNMP", "INT"]
group = false
[inputs.sysstat.options]
-C = "cpu"
-B = "paging"
-b = "io"
-d = "disk" # requires DISK activity
-H = "hugepages"
"-I ALL" = "interrupts" # requires INT activity
"-n ALL" = "network"
"-P ALL" = "per_cpu"
-q = "queue"
-R = "mem"
"-r ALL" = "mem_util"
-S = "swap_util"
-u = "cpu_util"
-v = "inode"
-W = "swap"
-w = "task"
[[inputs.sysstat.device_tags.sda]]
vg = "rootvg"
```
you get the following output:
```text
io_tps value=0.5 1459255780126025822
io_rtps value=0 1459255780126025822
io_wtps value=0.5 1459255780126025822
io_bread_per_s value=0 1459255780126025822
io_bwrtn_per_s value=38 1459255780126025822
cpu_util_pct_user,device=all value=39.07 1459255780126025822
cpu_util_pct_nice,device=all value=0 1459255780126025822
cpu_util_pct_system,device=all value=47.94 1459255780126025822
cpu_util_pct_iowait,device=all value=0 1459255780126025822
cpu_util_pct_steal,device=all value=0 1459255780126025822
cpu_util_pct_idle,device=all value=12.98 1459255780126025822
swap_pswpin_per_s value=0 1459255780126025822
cpu_pct_user,device=all value=39.07 1459255780126025822
cpu_pct_nice,device=all value=0 1459255780126025822
cpu_pct_system,device=all value=47.94 1459255780126025822
cpu_pct_iowait,device=all value=0 1459255780126025822
cpu_pct_steal,device=all value=0 1459255780126025822
cpu_pct_idle,device=all value=12.98 1459255780126025822
per_cpu_pct_user,device=all value=39.07 1459255780126025822
per_cpu_pct_nice,device=all value=0 1459255780126025822
per_cpu_pct_system,device=all value=47.94 1459255780126025822
per_cpu_pct_iowait,device=all value=0 1459255780126025822
per_cpu_pct_steal,device=all value=0 1459255780126025822
per_cpu_pct_idle,device=all value=12.98 1459255780126025822
per_cpu_pct_user,device=cpu0 value=33.5 1459255780126025822
per_cpu_pct_nice,device=cpu0 value=0 1459255780126025822
per_cpu_pct_system,device=cpu0 value=65.25 1459255780126025822
per_cpu_pct_iowait,device=cpu0 value=0 1459255780126025822
per_cpu_pct_steal,device=cpu0 value=0 1459255780126025822
per_cpu_pct_idle,device=cpu0 value=1.25 1459255780126025822
per_cpu_pct_user,device=cpu1 value=44.85 1459255780126025822
per_cpu_pct_nice,device=cpu1 value=0 1459255780126025822
per_cpu_pct_system,device=cpu1 value=29.55 1459255780126025822
per_cpu_pct_iowait,device=cpu1 value=0 1459255780126025822
per_cpu_pct_steal,device=cpu1 value=0 1459255780126025822
per_cpu_pct_idle,device=cpu1 value=25.59 1459255780126025822
hugepages_kbhugfree value=0 1459255780126025822
hugepages_kbhugused value=0 1459255780126025822
hugepages_pct_hugused value=0 1459255780126025822
interrupts_intr_per_s,device=i000 value=0 1459255780126025822
inode_dentunusd value=252876 1459255780126025822
mem_util_kbmemfree value=1613612 1459255780126025822
disk_tps,device=sda,vg=rootvg value=0.5 1459255780126025822
swap_pswpout_per_s value=0 1459255780126025822
network_rxpck_per_s,device=ens33 value=0 1459255780126025822
queue_runq-sz value=4 1459255780126025822
task_proc_per_s value=0 1459255780126025822
task_cswch_per_s value=2019 1459255780126025822
mem_frmpg_per_s value=0 1459255780126025822
mem_bufpg_per_s value=0.5 1459255780126025822
mem_campg_per_s value=1.25 1459255780126025822
interrupts_intr_per_s,device=i001 value=0 1459255780126025822
inode_file-nr value=19104 1459255780126025822
mem_util_kbmemused value=3741528 1459255780126025822
disk_rd_sec_per_s,device=sda,vg=rootvg value=0 1459255780126025822
network_txpck_per_s,device=ens33 value=0 1459255780126025822
queue_plist-sz value=1512 1459255780126025822
paging_pgpgin_per_s value=0 1459255780126025822
paging_pgpgout_per_s value=19 1459255780126025822
paging_fault_per_s value=0.25 1459255780126025822
paging_majflt_per_s value=0 1459255780126025822
paging_pgfree_per_s value=34.25 1459255780126025822
paging_pgscank_per_s value=0 1459255780126025822
paging_pgscand_per_s value=0 1459255780126025822
paging_pgsteal_per_s value=0 1459255780126025822
paging_pct_vmeff value=0 1459255780126025822
interrupts_intr_per_s,device=i002 value=0 1459255780126025822
interrupts_intr_per_s,device=i003 value=0 1459255780126025822
interrupts_intr_per_s,device=i004 value=0 1459255780126025822
interrupts_intr_per_s,device=i005 value=0 1459255780126025822
interrupts_intr_per_s,device=i006 value=0 1459255780126025822
interrupts_intr_per_s,device=i007 value=0 1459255780126025822
interrupts_intr_per_s,device=i008 value=0 1459255780126025822
interrupts_intr_per_s,device=i009 value=0 1459255780126025822
interrupts_intr_per_s,device=i010 value=0 1459255780126025822
interrupts_intr_per_s,device=i011 value=0 1459255780126025822
interrupts_intr_per_s,device=i012 value=0 1459255780126025822
interrupts_intr_per_s,device=i013 value=0 1459255780126025822
interrupts_intr_per_s,device=i014 value=0 1459255780126025822
interrupts_intr_per_s,device=i015 value=1 1459255780126025822
inode_inode-nr value=94709 1459255780126025822
inode_pty-nr value=14 1459255780126025822
mem_util_pct_memused value=69.87 1459255780126025822
mem_util_kbbuffers value=118252 1459255780126025822
mem_util_kbcached value=1045240 1459255780126025822
mem_util_kbcommit value=9628152 1459255780126025822
mem_util_pct_commit value=150.35 1459255780126025822
mem_util_kbactive value=2303752 1459255780126025822
mem_util_kbinact value=428340 1459255780126025822
mem_util_kbdirty value=104 1459255780126025822
mem_util_kbanonpg value=1568676 1459255780126025822
mem_util_kbslab value=240032 1459255780126025822
mem_util_kbkstack value=26224 1459255780126025822
mem_util_kbpgtbl value=98056 1459255780126025822
mem_util_kbvmused value=0 1459255780126025822
disk_wr_sec_per_s,device=sda,vg=rootvg value=38 1459255780126025822
disk_avgrq-sz,device=sda,vg=rootvg value=76 1459255780126025822
disk_avgqu-sz,device=sda,vg=rootvg value=0 1459255780126025822
disk_await,device=sda,vg=rootvg value=2 1459255780126025822
disk_svctm,device=sda,vg=rootvg value=2 1459255780126025822
disk_pct_util,device=sda,vg=rootvg value=0.1 1459255780126025822
network_rxkB_per_s,device=ens33 value=0 1459255780126025822
network_txkB_per_s,device=ens33 value=0 1459255780126025822
network_rxcmp_per_s,device=ens33 value=0 1459255780126025822
network_txcmp_per_s,device=ens33 value=0 1459255780126025822
network_rxmcst_per_s,device=ens33 value=0 1459255780126025822
network_pct_ifutil,device=ens33 value=0 1459255780126025822
network_rxpck_per_s,device=lo value=10.75 1459255780126025822
network_txpck_per_s,device=lo value=10.75 1459255780126025822
network_rxkB_per_s,device=lo value=0.77 1459255780126025822
network_txkB_per_s,device=lo value=0.77 1459255780126025822
network_rxcmp_per_s,device=lo value=0 1459255780126025822
network_txcmp_per_s,device=lo value=0 1459255780126025822
network_rxmcst_per_s,device=lo value=0 1459255780126025822
network_pct_ifutil,device=lo value=0 1459255780126025822
network_rxerr_per_s,device=ens33 value=0 1459255780126025822
network_txerr_per_s,device=ens33 value=0 1459255780126025822
network_coll_per_s,device=ens33 value=0 1459255780126025822
network_rxdrop_per_s,device=ens33 value=0 1459255780126025822
network_txdrop_per_s,device=ens33 value=0 1459255780126025822
network_txcarr_per_s,device=ens33 value=0 1459255780126025822
network_rxfram_per_s,device=ens33 value=0 1459255780126025822
network_rxfifo_per_s,device=ens33 value=0 1459255780126025822
network_txfifo_per_s,device=ens33 value=0 1459255780126025822
network_rxerr_per_s,device=lo value=0 1459255780126025822
network_txerr_per_s,device=lo value=0 1459255780126025822
network_coll_per_s,device=lo value=0 1459255780126025822
network_rxdrop_per_s,device=lo value=0 1459255780126025822
network_txdrop_per_s,device=lo value=0 1459255780126025822
network_txcarr_per_s,device=lo value=0 1459255780126025822
network_rxfram_per_s,device=lo value=0 1459255780126025822
network_rxfifo_per_s,device=lo value=0 1459255780126025822
network_txfifo_per_s,device=lo value=0 1459255780126025822
network_call_per_s value=0 1459255780126025822
network_retrans_per_s value=0 1459255780126025822
network_read_per_s value=0 1459255780126025822
network_write_per_s value=0 1459255780126025822
network_access_per_s value=0 1459255780126025822
network_getatt_per_s value=0 1459255780126025822
network_scall_per_s value=0 1459255780126025822
network_badcall_per_s value=0 1459255780126025822
network_packet_per_s value=0 1459255780126025822
network_udp_per_s value=0 1459255780126025822
network_tcp_per_s value=0 1459255780126025822
network_hit_per_s value=0 1459255780126025822
network_miss_per_s value=0 1459255780126025822
network_sread_per_s value=0 1459255780126025822
network_swrite_per_s value=0 1459255780126025822
network_saccess_per_s value=0 1459255780126025822
network_sgetatt_per_s value=0 1459255780126025822
network_totsck value=4234 1459255780126025822
network_tcpsck value=1637 1459255780126025822
network_udpsck value=2 1459255780126025822
network_rawsck value=0 1459255780126025822
network_ip-frag value=0 1459255780126025822
network_tcp-tw value=4 1459255780126025822
network_irec_per_s value=10.75 1459255780126025822
network_fwddgm_per_s value=0 1459255780126025822
network_idel_per_s value=10.75 1459255780126025822
network_orq_per_s value=10.75 1459255780126025822
network_asmrq_per_s value=0 1459255780126025822
network_asmok_per_s value=0 1459255780126025822
network_fragok_per_s value=0 1459255780126025822
network_fragcrt_per_s value=0 1459255780126025822
network_ihdrerr_per_s value=0 1459255780126025822
network_iadrerr_per_s value=0 1459255780126025822
network_iukwnpr_per_s value=0 1459255780126025822
network_idisc_per_s value=0 1459255780126025822
network_odisc_per_s value=0 1459255780126025822
network_onort_per_s value=0 1459255780126025822
network_asmf_per_s value=0 1459255780126025822
network_fragf_per_s value=0 1459255780126025822
network_imsg_per_s value=0 1459255780126025822
network_omsg_per_s value=0 1459255780126025822
network_iech_per_s value=0 1459255780126025822
network_iechr_per_s value=0 1459255780126025822
network_oech_per_s value=0 1459255780126025822
network_oechr_per_s value=0 1459255780126025822
network_itm_per_s value=0 1459255780126025822
network_itmr_per_s value=0 1459255780126025822
network_otm_per_s value=0 1459255780126025822
network_otmr_per_s value=0 1459255780126025822
network_iadrmk_per_s value=0 1459255780126025822
network_iadrmkr_per_s value=0 1459255780126025822
network_oadrmk_per_s value=0 1459255780126025822
network_oadrmkr_per_s value=0 1459255780126025822
network_ierr_per_s value=0 1459255780126025822
network_oerr_per_s value=0 1459255780126025822
network_idstunr_per_s value=0 1459255780126025822
network_odstunr_per_s value=0 1459255780126025822
network_itmex_per_s value=0 1459255780126025822
network_otmex_per_s value=0 1459255780126025822
network_iparmpb_per_s value=0 1459255780126025822
network_oparmpb_per_s value=0 1459255780126025822
network_isrcq_per_s value=0 1459255780126025822
network_osrcq_per_s value=0 1459255780126025822
network_iredir_per_s value=0 1459255780126025822
network_oredir_per_s value=0 1459255780126025822
network_active_per_s value=0 1459255780126025822
network_passive_per_s value=0 1459255780126025822
network_iseg_per_s value=10.75 1459255780126025822
network_oseg_per_s value=9.5 1459255780126025822
network_atmptf_per_s value=0 1459255780126025822
network_estres_per_s value=0 1459255780126025822
network_retrans_per_s value=1.5 1459255780126025822
network_isegerr_per_s value=0.25 1459255780126025822
network_orsts_per_s value=0 1459255780126025822
network_idgm_per_s value=0 1459255780126025822
network_odgm_per_s value=0 1459255780126025822
network_noport_per_s value=0 1459255780126025822
network_idgmerr_per_s value=0 1459255780126025822
queue_ldavg-1 value=2.1 1459255780126025822
queue_ldavg-5 value=1.82 1459255780126025822
queue_ldavg-15 value=1.44 1459255780126025822
queue_blocked value=0 1459255780126025822
swap_util_kbswpfree value=1048572 1459255780126025822
swap_util_kbswpused value=0 1459255780126025822
swap_util_pct_swpused value=0 1459255780126025822
swap_util_kbswpcad value=0 1459255780126025822
swap_util_pct_swpcad value=0 1459255780126025822
```

View file

@ -0,0 +1,53 @@
# Sysstat metrics collector
# This plugin ONLY supports Linux
[[inputs.sysstat]]
## Path to the sadc command.
#
## Common Defaults:
## Debian/Ubuntu: /usr/lib/sysstat/sadc
## Arch: /usr/lib/sa/sadc
## RHEL/CentOS: /usr/lib64/sa/sadc
sadc_path = "/usr/lib/sa/sadc" # required
## Path to the sadf command, if it is not in PATH
# sadf_path = "/usr/bin/sadf"
## Activities is a list of activities, that are passed as argument to the
## sadc collector utility (e.g: DISK, SNMP etc...)
## The more activities that are added, the more data is collected.
# activities = ["DISK"]
## Group metrics to measurements.
##
## If group is false each metric will be prefixed with a description
## and represents itself a measurement.
##
## If Group is true, corresponding metrics are grouped to a single measurement.
# group = true
## Options for the sadf command. The values on the left represent the sadf options and
## the values on the right their description (which are used for grouping and prefixing metrics).
##
## Run 'sar -h' or 'man sar' to find out the supported options for your sysstat version.
[inputs.sysstat.options]
-C = "cpu"
-B = "paging"
-b = "io"
-d = "disk" # requires DISK activity
"-n ALL" = "network"
"-P ALL" = "per_cpu"
-q = "queue"
-R = "mem"
-r = "mem_util"
-S = "swap_util"
-u = "cpu_util"
-v = "inode"
-W = "swap"
-w = "task"
# -H = "hugepages" # only available for newer linux distributions
# "-I ALL" = "interrupts" # requires INT activity
## Device tags can be used to add additional tags for devices. For example the configuration below
## adds a tag vg with value rootvg for all metrics with sda devices.
# [[inputs.sysstat.device_tags.sda]]
# vg = "rootvg"

View file

@ -0,0 +1,317 @@
//go:generate ../../../tools/readme_config_includer/generator
//go:build linux
package sysstat
import (
"bufio"
_ "embed"
"encoding/csv"
"errors"
"fmt"
"io"
"os"
"os/exec"
"strconv"
"strings"
"sync"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/internal"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
var (
execCommand = exec.Command // execCommand is used to mock commands in tests.
dfltActivities = []string{"DISK"}
)
const (
parseInterval = 1 // parseInterval is the interval (in seconds) where the parsing of the binary file takes place.
cmd = "sadf"
)
type Sysstat struct {
// Sadc represents the path to the sadc collector utility.
Sadc string `toml:"sadc_path"`
// Force the execution time of sadc
SadcInterval config.Duration `toml:"sadc_interval"`
// Sadf represents the path to the sadf cmd.
Sadf string `toml:"sadf_path"`
// Activities is a list of activities that are passed as argument to the
// collector utility (e.g: DISK, SNMP etc...)
// The more activities that are added, the more data is collected.
Activities []string `toml:"activities"`
// Options is a map of options.
//
// The key represents the actual option that the Sadf command is called with and
// the value represents the description for that option.
//
// For example, if you have the following options map:
// map[string]string{"-C": "cpu", "-d": "disk"}
// The Sadf command is run with the options -C and -d to extract cpu and
// disk metrics from the collected binary file.
//
// If Group is false (see below), each metric will be prefixed with the corresponding description
// and represents itself a measurement.
//
// If Group is true, metrics are grouped to a single measurement with the corresponding description as name.
Options map[string]string `toml:"options"`
// Group determines if metrics are grouped or not.
Group bool `toml:"group"`
// DeviceTags adds the possibility to add additional tags for devices.
DeviceTags map[string][]map[string]string `toml:"device_tags"`
Log telegraf.Logger `toml:"-"`
// Used to autodetect how long the sadc command should run for
interval int
firstTimestamp time.Time
}
func (*Sysstat) SampleConfig() string {
return sampleConfig
}
func (s *Sysstat) Init() error {
// Set defaults
if s.Sadf == "" {
sadf, err := exec.LookPath(cmd)
if err != nil {
return fmt.Errorf("looking up %q failed: %w", cmd, err)
}
s.Sadf = sadf
}
if s.Sadf == "" {
return fmt.Errorf("no path specified for %q", cmd)
}
return nil
}
func (s *Sysstat) Gather(acc telegraf.Accumulator) error {
if time.Duration(s.SadcInterval) != 0 {
// Collect interval is calculated as interval - parseInterval
s.interval = int(time.Duration(s.SadcInterval).Seconds()) + parseInterval
}
if s.interval == 0 {
if s.firstTimestamp.IsZero() {
s.firstTimestamp = time.Now()
} else {
s.interval = int(time.Since(s.firstTimestamp).Seconds() + 0.5)
}
}
tmpfile, err := os.CreateTemp("", "sysstat-*")
if err != nil {
return fmt.Errorf("failed to create tmp file: %w", err)
}
defer os.Remove(tmpfile.Name())
defer tmpfile.Close()
ts := time.Now().Add(time.Duration(s.interval) * time.Second)
if err := s.collect(tmpfile.Name()); err != nil {
return err
}
var wg sync.WaitGroup
for option := range s.Options {
wg.Add(1)
go func(acc telegraf.Accumulator, option string) {
defer wg.Done()
acc.AddError(s.parse(acc, option, tmpfile.Name(), ts))
}(acc, option)
}
wg.Wait()
return nil
}
// collect collects sysstat data with the collector utility sadc.
// It runs the following command:
//
// Sadc -S <Activity1> -S <Activity2> ... <collectInterval> 2 tmpFile
//
// The above command collects system metrics during <collectInterval> and
// saves it in binary form to tmpFile.
func (s *Sysstat) collect(tempfile string) error {
options := make([]string, 0, len(s.Activities))
for _, act := range s.Activities {
options = append(options, "-S", act)
}
// collectInterval has to be smaller than the telegraf data collection interval
collectInterval := s.interval - parseInterval
// If true, interval is not defined yet and Gather is run for the first time.
if collectInterval <= 0 {
collectInterval = 1 // In that case we only collect for 1 second.
}
options = append(options, strconv.Itoa(collectInterval), "2", tempfile)
cmd := execCommand(s.Sadc, options...)
out, err := internal.CombinedOutputTimeout(cmd, time.Second*time.Duration(collectInterval+parseInterval))
if err != nil {
return fmt.Errorf("failed to run command %q: %w - %q", strings.Join(cmd.Args, " "), err, string(out))
}
return nil
}
func filterEnviron(env []string, prefix string) []string {
newenv := env[:0]
for _, envvar := range env {
if !strings.HasPrefix(envvar, prefix) {
newenv = append(newenv, envvar)
}
}
return newenv
}
// Return the Cmd with its environment configured to use the C locale
func withCLocale(cmd *exec.Cmd) *exec.Cmd {
var env []string
if cmd.Env != nil {
env = cmd.Env
} else {
env = os.Environ()
}
env = filterEnviron(env, "LANG")
env = filterEnviron(env, "LC_")
env = append(env, "LANG=C")
cmd.Env = env
return cmd
}
// parse runs Sadf on the previously saved tmpFile:
//
// Sadf -p -- -p <option> tmpFile
//
// and parses the output to add it to the telegraf.Accumulator acc.
func (s *Sysstat) parse(acc telegraf.Accumulator, option, tmpfile string, ts time.Time) error {
cmd := execCommand(s.Sadf, sadfOptions(option, tmpfile)...)
cmd = withCLocale(cmd)
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}
if err := cmd.Start(); err != nil {
return fmt.Errorf("running command %q failed: %w", strings.Join(cmd.Args, " "), err)
}
r := bufio.NewReader(stdout)
csvReader := csv.NewReader(r)
csvReader.Comma = '\t'
csvReader.FieldsPerRecord = 6
var measurement string
// groupData to accumulate data when Group=true
type groupData struct {
tags map[string]string
fields map[string]interface{}
}
m := make(map[string]groupData)
for {
record, err := csvReader.Read()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return err
}
device := record[3]
value, err := strconv.ParseFloat(record[5], 64)
if err != nil {
return err
}
tags := make(map[string]string)
if device != "-" {
tags["device"] = device
if addTags, ok := s.DeviceTags[device]; ok {
for _, tag := range addTags {
for k, v := range tag {
tags[k] = v
}
}
}
}
if s.Group {
measurement = s.Options[option]
if _, ok := m[device]; !ok {
m[device] = groupData{
fields: make(map[string]interface{}),
tags: make(map[string]string),
}
}
g := m[device]
if len(g.tags) == 0 {
for k, v := range tags {
g.tags[k] = v
}
}
g.fields[escape(record[4])] = value
} else {
measurement = s.Options[option] + "_" + escape(record[4])
fields := map[string]interface{}{
"value": value,
}
acc.AddFields(measurement, fields, tags, ts)
}
}
if s.Group {
for _, v := range m {
acc.AddFields(measurement, v.fields, v.tags, ts)
}
}
if err := internal.WaitTimeout(cmd, time.Second*5); err != nil {
return fmt.Errorf("command %q failed with: %w", strings.Join(cmd.Args, " "), err)
}
return nil
}
// sadfOptions creates the correct options for the sadf utility.
func sadfOptions(activityOption, tmpfile string) []string {
options := []string{
"-p",
"--",
"-p",
}
opts := strings.Split(activityOption, " ")
options = append(options, opts...)
options = append(options, tmpfile)
return options
}
// escape removes % and / chars in field names
func escape(dirty string) string {
var fieldEscaper = strings.NewReplacer(
`%%`, "pct_",
`%`, "pct_",
`/`, "_per_",
)
return fieldEscaper.Replace(dirty)
}
func init() {
inputs.Add("sysstat", func() telegraf.Input {
return &Sysstat{
Group: true,
Activities: dfltActivities,
}
})
}

View file

@ -0,0 +1,54 @@
//go:build !race && linux
package sysstat
import (
"os/exec"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/testutil"
)
// TestInterval verifies that the correct interval is created. It is not
// run with -race option, because in that scenario interval between the two
// Gather calls is greater than wantedInterval.
func TestInterval(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test with sleep in short mode.")
}
// overwriting exec commands with mock commands
execCommand = fakeExecCommand
defer func() { execCommand = exec.Command }()
var acc testutil.Accumulator
s := &Sysstat{
Log: testutil.Logger{},
interval: 0,
Sadc: "/usr/lib/sa/sadc",
Sadf: "/usr/bin/sadf",
Group: false,
Activities: []string{"DISK", "SNMP"},
Options: map[string]string{
"C": "cpu",
"d": "disk",
},
DeviceTags: map[string][]map[string]string{
"sda": {
{
"vg": "rootvg",
},
},
},
}
require.NoError(t, s.Init())
require.NoError(t, acc.GatherError(s.Gather))
wantedInterval := 3
time.Sleep(time.Duration(wantedInterval) * time.Second)
require.NoError(t, acc.GatherError(s.Gather))
require.Equalf(t, wantedInterval, s.interval, "wrong interval: got %d, want %d", s.interval, wantedInterval)
}

View file

@ -0,0 +1,33 @@
//go:generate ../../../tools/readme_config_includer/generator
//go:build !linux
package sysstat
import (
_ "embed"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
type Sysstat struct {
Log telegraf.Logger `toml:"-"`
}
func (*Sysstat) SampleConfig() string { return sampleConfig }
func (s *Sysstat) Init() error {
s.Log.Warn("Current platform is not supported")
return nil
}
func (*Sysstat) Gather(telegraf.Accumulator) error { return nil }
func init() {
inputs.Add("sysstat", func() telegraf.Input {
return &Sysstat{}
})
}

View file

@ -0,0 +1,328 @@
//go:build linux
package sysstat
import (
"fmt"
"os"
"os/exec"
"path"
"testing"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/testutil"
)
func TestGather(t *testing.T) {
// overwriting exec commands with mock commands
execCommand = fakeExecCommand
defer func() { execCommand = exec.Command }()
var acc testutil.Accumulator
s := &Sysstat{
Log: testutil.Logger{},
interval: 10,
Sadc: "/usr/lib/sa/sadc",
Sadf: "/usr/bin/sadf",
Group: false,
Activities: []string{"DISK", "SNMP"},
Options: map[string]string{
"C": "cpu",
"d": "disk",
},
DeviceTags: map[string][]map[string]string{
"sda": {
{
"vg": "rootvg",
},
},
},
}
require.NoError(t, s.Init())
require.NoError(t, acc.GatherError(s.Gather))
cpuTags := map[string]string{"device": "all"}
diskTags := map[string]string{"device": "sda", "vg": "rootvg"}
tests := []struct {
measurement string
fields map[string]interface{}
tags map[string]string
}{
{
"cpu_pct_user",
map[string]interface{}{
"value": 0.65,
},
cpuTags,
},
{
"cpu_pct_nice",
map[string]interface{}{
"value": 0.0,
},
cpuTags,
},
{
"cpu_pct_system",
map[string]interface{}{
"value": 0.10,
},
cpuTags,
},
{
"cpu_pct_iowait",
map[string]interface{}{
"value": 0.15,
},
cpuTags,
},
{
"cpu_pct_steal",
map[string]interface{}{
"value": 0.0,
},
cpuTags,
},
{
"cpu_pct_idle",
map[string]interface{}{
"value": 99.1,
},
cpuTags,
},
{
"disk_tps",
map[string]interface{}{
"value": 0.00,
},
diskTags,
},
{
"disk_rd_sec_per_s",
map[string]interface{}{
"value": 0.00,
},
diskTags,
},
{
"disk_wr_sec_per_s",
map[string]interface{}{
"value": 0.00,
},
diskTags,
},
{
"disk_avgrq-sz",
map[string]interface{}{
"value": 0.00,
},
diskTags,
},
{
"disk_avgqu-sz",
map[string]interface{}{
"value": 0.00,
},
diskTags,
},
{
"disk_await",
map[string]interface{}{
"value": 0.00,
},
diskTags,
},
{
"disk_svctm",
map[string]interface{}{
"value": 0.00,
},
diskTags,
},
{
"disk_pct_util",
map[string]interface{}{
"value": 0.00,
},
diskTags,
},
}
for _, test := range tests {
acc.AssertContainsTaggedFields(t, test.measurement, test.fields, test.tags)
}
}
func TestGatherGrouped(t *testing.T) {
// overwriting exec commands with mock commands
execCommand = fakeExecCommand
defer func() { execCommand = exec.Command }()
var acc testutil.Accumulator
s := &Sysstat{
Log: testutil.Logger{},
interval: 10,
Sadc: "/usr/lib/sa/sadc",
Sadf: "/usr/bin/sadf",
Group: true,
Activities: []string{"DISK", "SNMP"},
Options: map[string]string{
"C": "cpu",
"d": "disk",
},
DeviceTags: map[string][]map[string]string{
"sda": {
{
"vg": "rootvg",
},
},
},
}
require.NoError(t, s.Init())
require.NoError(t, acc.GatherError(s.Gather))
var tests = []struct {
measurement string
fields map[string]interface{}
tags map[string]string
}{
{
"cpu",
map[string]interface{}{
"pct_user": 0.65,
"pct_nice": 0.0,
"pct_system": 0.10,
"pct_iowait": 0.15,
"pct_steal": 0.0,
"pct_idle": 99.1,
},
map[string]string{"device": "all"},
},
{
"disk",
map[string]interface{}{
"tps": 0.00,
"rd_sec_per_s": 0.00,
"wr_sec_per_s": 0.00,
"avgrq-sz": 0.00,
"avgqu-sz": 0.00,
"await": 0.00,
"svctm": 0.00,
"pct_util": 0.00,
},
map[string]string{"device": "sda", "vg": "rootvg"},
},
{
"disk",
map[string]interface{}{
"tps": 2.01,
"rd_sec_per_s": 1.0,
"wr_sec_per_s": 0.00,
"avgrq-sz": 0.30,
"avgqu-sz": 0.60,
"await": 0.70,
"svctm": 0.20,
"pct_util": 0.30,
},
map[string]string{"device": "sdb"},
},
}
for _, test := range tests {
acc.AssertContainsTaggedFields(t, test.measurement, test.fields, test.tags)
}
}
func TestEscape(t *testing.T) {
var tests = []struct {
input string
escaped string
}{
{
"%util",
"pct_util",
},
{
"%%util",
"pct_util",
},
{
"bread/s",
"bread_per_s",
},
{
"%nice",
"pct_nice",
},
}
for _, test := range tests {
if test.escaped != escape(test.input) {
t.Errorf("wrong escape, got %s, wanted %s", escape(test.input), test.escaped)
}
}
}
// Helper function that mock the exec.Command call (and call the test binary)
func fakeExecCommand(command string, args ...string) *exec.Cmd {
cs := []string{"-test.run=TestHelperProcess", "--", command}
cs = append(cs, args...)
cmd := exec.Command(os.Args[0], cs...)
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
return cmd
}
// TestHelperProcess isn't a real test. It's used to mock exec.Command
// For example, if you run:
// GO_WANT_HELPER_PROCESS=1 go test -test.run=TestHelperProcess -- sadf -p -- -p -C tmpFile
// it returns mockData["C"] output.
func TestHelperProcess(t *testing.T) {
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
return
}
mockData := map[string]string{
"C": `dell-xps 5 2016-03-25 16:18:10 UTC all %user 0.65
dell-xps 5 2016-03-25 16:18:10 UTC all %nice 0.00
dell-xps 5 2016-03-25 16:18:10 UTC all %system 0.10
dell-xps 5 2016-03-25 16:18:10 UTC all %iowait 0.15
dell-xps 5 2016-03-25 16:18:10 UTC all %steal 0.00
dell-xps 5 2016-03-25 16:18:10 UTC all %idle 99.10
`,
"d": `dell-xps 5 2016-03-25 16:18:10 UTC sda tps 0.00
dell-xps 5 2016-03-25 16:18:10 UTC sda rd_sec/s 0.00
dell-xps 5 2016-03-25 16:18:10 UTC sda wr_sec/s 0.00
dell-xps 5 2016-03-25 16:18:10 UTC sda avgrq-sz 0.00
dell-xps 5 2016-03-25 16:18:10 UTC sda avgqu-sz 0.00
dell-xps 5 2016-03-25 16:18:10 UTC sda await 0.00
dell-xps 5 2016-03-25 16:18:10 UTC sda svctm 0.00
dell-xps 5 2016-03-25 16:18:10 UTC sda %util 0.00
dell-xps 5 2016-03-25 16:18:10 UTC sdb tps 2.01
dell-xps 5 2016-03-25 16:18:10 UTC sdb rd_sec/s 1.00
dell-xps 5 2016-03-25 16:18:10 UTC sdb wr_sec/s 0.00
dell-xps 5 2016-03-25 16:18:10 UTC sdb avgrq-sz 0.30
dell-xps 5 2016-03-25 16:18:10 UTC sdb avgqu-sz 0.60
dell-xps 5 2016-03-25 16:18:10 UTC sdb await 0.70
dell-xps 5 2016-03-25 16:18:10 UTC sdb svctm 0.20
dell-xps 5 2016-03-25 16:18:10 UTC sdb %util 0.30
`,
}
args := os.Args
// Previous arguments are tests stuff, that looks like :
// /tmp/go-build970079519/…/_test/integration.test -test.run=TestHelperProcess --
cmd, args := args[3], args[4:]
// Handle the case where args[0] is dir:...
switch path.Base(cmd) {
case "sadf":
_, err := fmt.Fprint(os.Stdout, mockData[args[3]])
require.NoError(t, err)
default:
}
// some code here to check arguments perhaps?
//nolint:revive // error code is important for this "test"
os.Exit(0)
}