Skip to content

Instantly share code, notes, and snippets.

@erik-stephens
Created September 1, 2017 18:29
Show Gist options
  • Save erik-stephens/f12ff1c0f0a2149a191800497a141318 to your computer and use it in GitHub Desktop.
Save erik-stephens/f12ff1c0f0a2149a191800497a141318 to your computer and use it in GitHub Desktop.
SMART collection script for DataDog
#! /usr/bin/env python
# coding: utf8
"""
Publish metrics from `smartctl` output:
* temp.DISK = celsius
*
Also publish these events when they occur:
* SMART 5 - Reallocated_Sector_Count.
* SMART 187 - Reported_Uncorrectable_Errors.
* SMART 188 - Command_Timeout.
* SMART 197 - Current_Pending_Sector_Count.
* SMART 198 - Offline_Uncorrectable
"""
import sys, time, os, re, subprocess
from datadog.statsd import statsd
def output(disk):
"""Return raw output of `smartctl -x DISK`.
Raise Exception when:
* there is any error output
* return status is not successful (ie not 0)
* smartctl executable not found
* DISK does not exist
"""
if os.system('which smartctl > /dev/null') != 0:
raise Exception("Failed to find `smartctl` executable")
if not os.path.exists(disk):
raise Exception("Disk does not exist: {}".format(disk))
p = subprocess.Popen(['smartctl', '-x', disk],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
status = p.wait()
err = p.stderr.read()
if err or status != 0:
raise Exception("Failed to execute `smartctl`: status={}, stderr={}".format(status, err))
return (i.strip() for i in p.stdout.readlines())
def parsed(disk, lines):
"""Yield (name,value,line) for each numeric data point.
"""
for line in lines:
fields = line.split()
if len(fields) < 3:
continue
if fields[1] == 'Temperature_Celsius':
name = "temp.{}".format(disk)
val = float(fields[7])
statsd.gauge(name, val)
yield (name, val, line)
for disk in sys.argv[1:]:
for name, val, line in parsed(disk, output(disk)):
# Print in datadog-friendly log format
print("{} {} {}".format(name, int(time.time()), val))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment