diff --git a/README.md b/README.md index e1d68dc..b0bf56b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ Add the following config section to your telegraf.yml: [[inputs.exec]] commands = ["/etc/telegraf/bcachefs_perf.sh"] data_format = "influx" +[[inputs.exec]] + commands = ["/etc/telegraf/bcachefs_time_stats.sh"] + data_format = "influx" ``` ![example disks table](disks-table.png) diff --git a/bcachefs_time_stats.sh b/bcachefs_time_stats.sh new file mode 100644 index 0000000..2dd41f6 --- /dev/null +++ b/bcachefs_time_stats.sh @@ -0,0 +1,108 @@ +#!/bin/bash +set -euo pipefail + +function to_ns() +{ + local val unit + read -r val unit <<< "$1" + + case "$unit" in + ns) echo "$val" ;; + us) echo $(( val * 1000 )) ;; + ms) echo $(( val * 1000000 )) ;; + s) echo $(( val * 1000000000 )) ;; + m) echo $(( val * 60 * 1000000000 )) ;; + h) echo $(( val * 3600 * 1000000000 )) ;; + d) echo $(( val * 86400 * 1000000000 )) ;; + w) echo $(( val * 604800 * 1000000000 )) ;; + eon) echo 0 ;; # bcachefs uses this as "infinite" + *) echo 0 ;; + esac +} + +cd /sys/fs/bcachefs + +for uuid in *; do + cd "$uuid/time_stats" + + for stat in * ; do + count="" + dur_min="" + dur_max="" + dur_total="" + + mean_since="" + mean_recent="" + stddev_since="" + stddev_recent="" + + in_duration=0 + + while IFS= read -r line; do + # trim leading whitespace + line="${line#"${line%%[![:space:]]*}"}" + + case "$line" in + count:*) + count="${line#count:}" + count="${count//[[:space:]]/}" + ;; + "duration of events") + in_duration=1 + ;; + "time between events") + in_duration=0 + ;; + min:*) + (( in_duration )) && dur_min="${line#min:}" + ;; + max:*) + (( in_duration )) && dur_max="${line#max:}" + ;; + total:*) + (( in_duration )) && dur_total="${line#total:}" + ;; + mean:*) + if (( in_duration )); then + rest="${line#mean:}" + read -r ms_val ms_unit mr_val mr_unit <<< "$rest" + mean_since="$ms_val $ms_unit" + mean_recent="$mr_val $mr_unit" + fi + ;; + stddev:*) + if (( in_duration )); then + rest="${line#stddev:}" + read -r ss_val ss_unit sr_val sr_unit <<< "$rest" + stddev_since="$ss_val $ss_unit" + stddev_recent="$sr_val $sr_unit" + fi + ;; + esac + done < "$stat" + + # trim leading whitespace + for v in dur_min dur_max dur_total mean_since mean_recent stddev_since stddev_recent; do + eval "$v=\"\${$v#\"\${$v%%[![:space:]]*}\"}\"" + done + + dur_min_ns=$(to_ns "$dur_min") + dur_max_ns=$(to_ns "$dur_max") + dur_total_ns=$(to_ns "$dur_total") + mean_since_ns=$(to_ns "$mean_since") + mean_recent_ns=$(to_ns "$mean_recent") + stddev_since_ns=$(to_ns "$stddev_since") + stddev_recent_ns=$(to_ns "$stddev_recent") + + printf "bcachefs_time_stats,uuid=%s,stat=%s " "$uuid" "$stat" + printf "count=%si," "$count" + printf "dur_min_ns=%si,dur_max_ns=%si,dur_total_ns=%si," \ + "$dur_min_ns" "$dur_max_ns" "$dur_total_ns" + printf "mean_since_ns=%si,mean_recent_ns=%si," \ + "$mean_since_ns" "$mean_recent_ns" + printf "stddev_since_ns=%si,stddev_recent_ns=%si\n" \ + "$stddev_since_ns" "$stddev_recent_ns" + done + + cd .. +done