Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZFS dataset stats #2

Open
mroach opened this issue Oct 13, 2024 · 1 comment
Open

ZFS dataset stats #2

mroach opened this issue Oct 13, 2024 · 1 comment
Assignees
Labels
enhancement New feature or request

Comments

@mroach
Copy link

mroach commented Oct 13, 2024

Is your feature request related to a problem ?

Hello! This isn't so much a feature request as a submission of an idea with proof of concept code.

The zpool bar doesn't show the actual capacity of pools, but rather the total size of disks in the pool. Not a big deal.

In my setup I'm using multiple datasets, each with their own quotas. I wanted to see these as part of the MOTD.

Also, when a dataset is using significant space on snapshots, I wanted to visualise that in the bar.

Describe the solution you'd like.

  • Displaying each dataset separately
  • Showing the true size of pools and datasets, considering quotas
  • Differentiating data from snapshots in the view

Describe alternatives you've considered.

This script is my first pass at it. I wanted to share it if you think there's value in adding it or a variant of it to the repo as a ZFS option.

Screenshot from 2024-10-13 15-48-53

#!/usr/bin/env bash

set -euo pipefail

size_format=iec
bar_width=60
warn_free_pct=20
red="\e[1;31m"
green="\e[1;32m"
dim="\e[2m"
reset="\e[0m"
ds_char=""
snap_char=""
other_char=""
free_char=""

function format_bytes() {
  numfmt --to="${size_format}" --format="%.01f" "$1"
}

function pct() {
  awk -v n="$1" -v d="$2" 'BEGIN{ print int(n*100.0/d) }'
}

function bar() {
  ds_b="$1"
  snap_b="$2"
  other_b="$3"

  ds_width=$(( (ds_b * bar_width) / 100))
  snap_width=$(( (snap_b * bar_width) / 100))
  other_width=$(( (other_b * bar_width) / 100 ))
  rem=$(( bar_width - ds_width - snap_width - other_width ))

  pct_free=$(( 100 - ds_width - snap_width - other_width ))

  echo -ne "${dim}[${reset}"

  if [ "$pct_free" -lt "$warn_free_pct" ]; then
    echo -ne "$red"
  else
    echo -ne "$green"
  fi

  if [ $ds_width -gt 0 ]; then
    printf "${ds_char}%.0s" $(seq 1 $ds_width)
  fi
  
  if [ $snap_width -gt 0 ]; then
    printf "${snap_char}%.0s" $(seq 1 $snap_width)
  fi

  if [ $other_width -gt 0 ]; then
    printf "${other_char}%.0s" $(seq 1 $other_width)
  fi

  if [ $rem -gt 0 ]; then
    printf "${dim}${free_char}%.0s" $(seq 1 $rem)
    # To pad with spaces, do this instead:
    #printf "${dim}%*s" $rem
  fi

  echo -e "${reset}${dim}]${reset}"
}

echo

while read -r line; do
  IFS=$'\t' read -r -a props <<< "$line"

  name="${props[0]}"
  avail="${props[1]}"
  used="${props[2]}"
  usedsnap="${props[3]}"
  usedds="${props[4]}"

  used_other=$(( used - usedsnap - usedds ))
  capacity=$(( used + avail ))

  ds_used_pct=$(pct "$usedds" "$capacity")
  snap_used_pct=$(pct "$usedsnap" "$capacity")
  other_used_pct=$(pct "$used_other" "$capacity")

  #echo "$name avail=$avail used=$used usnap=$usedsnap uds=$usedds cap=$capacity dp=$ds_used_pct sp=$snap_used_pct"

  # Maybe remove the pool name
  local_name="${name#*/}"
  if [ "$local_name" = "$name" ]; then
    echo "$name"
  else
    echo "  $local_name"
  fi
  echo -n "  "
  bar "$ds_used_pct" "$snap_used_pct" "$other_used_pct"
  echo -n "   "
  printf "Used %s of %s (%s free)\n\n" "$(format_bytes $used)" "$(format_bytes $capacity)" "$(format_bytes $avail)"
done < <(zfs list -Hp -t filesystem -o space -d1)

Or with a few tweaks, a compact layout:

Screenshot from 2024-10-13 16-19-53

Additional context.

No response

@mroach mroach added the enhancement New feature or request label Oct 13, 2024
@reefland
Copy link
Owner

Thank you for sharing! I'll check it out in a bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants