Skip to content

Instantly share code, notes, and snippets.

@krisraich
Last active April 4, 2024 08:55
Show Gist options
  • Save krisraich/5cdff4df9442f0186a5904c8ca0359bc to your computer and use it in GitHub Desktop.
Save krisraich/5cdff4df9442f0186a5904c8ca0359bc to your computer and use it in GitHub Desktop.
ZFS to InfluxDB Monitoring Script for TrueNas
# A python script that can be run on TrueNas without installing any further libs.
# This script send zpool iostat to an InfluxDB 2.
# Use this script if you want to avoid creating jails.
#
# Run on start with crontab (and avid sending emails on output):
# MAILTO=""
# @reboot /usr/local/bin/python /root/reportZFS.py &
import subprocess
import requests
# InfluxDB configuration
influx_url = "http://influx:8068"
influx_token = ""
influx_org = ""
influx_bucket = ""
influx_measurement = "zfs_stats"
# name of the zfs pool
pool_name = ""
# ZFS command to get statistics, poll rate 1sec
zfs_command = ["zpool", "iostat", "-y", "-p", "-H", pool_name, "1"]
def monitor_zfs_iostat(command):
try:
with subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as proc:
for output in proc.stdout:
if output == '' and proc.poll() is not None:
break
lines = output.strip().split('\n')
headers = ["pool", "alloc", "free", "reads", "writes", "read", "write"]
data = lines[0].split()
#only send stats when some IO is happening
if data[3] != '0' or data[4] != '0' :
# Create a dictionary with headers as keys and data as values
zfs_stats = dict(zip(headers, data))
# print(zfs_stats)
write_to_influxdb(zfs_stats)
proc.wait()
return proc.returncode
except Exception as e:
print(f"An error occurred: {e}")
return 1
def write_to_influxdb(stats):
# Format the data into InfluxDB line protocol
tags = f"pool={stats.get('pool')}"
fields = {
"alloc": int(stats.get("alloc")),
"free": int(stats.get("free")),
"read_ops": int(stats.get("reads")),
"write_ops": int(stats.get("writes")),
"read_bytes": int(stats.get("read")),
"write_bytes": int(stats.get("write")),
}
data = f"{influx_measurement},{tags} " + ",".join([f"{k}={v}" for k, v in fields.items()])
# Send the data to InfluxDB
url = f"{influx_url}/api/v2/write?org={influx_org}&bucket={influx_bucket}&precision=s"
headers = {
"Authorization": f"Token {influx_token}",
"Content-Type": "application/octet-stream",
}
response = requests.post(url, headers=headers, data=data)
if response.status_code != 204:
print(f"Error writing to InfluxDB. Status Code: {response.status_code}, Response: {response.text}")
if __name__ == "__main__":
return_code = monitor_zfs_iostat(zfs_command)
print(f"Subprocess finished with return code: {return_code}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment