Skip to content

Instantly share code, notes, and snippets.

@jontow
Last active October 30, 2021 18:31
Show Gist options
  • Save jontow/158495b6d768e850acaa61286f6c8343 to your computer and use it in GitHub Desktop.
Save jontow/158495b6d768e850acaa61286f6c8343 to your computer and use it in GitHub Desktop.
openbsd hw_sensors_to_metrics.slow
#!/bin/sh
#
# 2021-10-28 -- [email protected]
#
# Convert OpenBSD "sysctl hw.sensors" output to prometheus scrape-able metrics.
# Example:
#
# These:
# hw.sensors.nsclpcsio0.volt13=1.49 VDC (TS3)
# hw.sensors.owtemp0.temp1=17.12 degC (sn 0000078fa11b)
# Become these:
# hw_sensors_nsclpcsio0_volt13{unit="VDC"} 1.49
# hw_sensors_owtemp0_temp1{unit="degC",serial="0000078fa11b",name="closet"} 17.12
#
# map sensor serial numbers to plaintext names here
SENSOR_0000078fa11b="closet"
sysctl hw.sensors | while read -r sensor; do
# These transforms aren't pleasant, but, using the following example:
# "hw.sensors.owtemp0.temp1=17.06 degC (sn 0000078fa11b)"
# 1). raw output, change periods to underscores and drop equals sign
# "hw.sensors.owtemp0.temp1 =" becomes "hw_sensors_owtemp0_temp1"
mod_output_pass1=$(echo ${sensor} | sed -e 's/\./_/g' -e 's/\=/ /g')
# 2). get name, intentionally strips numerical identifiers
# returns "hw_sensors_owtemp_temp"
sensor_name=$(echo ${mod_output_pass1} | awk '{print $1}' | sed -E 's/[0-9]+//g')
sensor_name_nums=$(echo ${mod_output_pass1} | awk '{print $1}')
# 2a). get "controller id"
# returns "0" from "owtemp0"
sensor_controller_id=$(echo ${sensor_name_nums} | awk -F_ '{print $3}' | grep -E -o '[0-9]+')
# 2b). get "sensor id"
# returns "1" from "temp1"
sensor_sensor_id=$(echo ${sensor_name_nums} | awk -F_ '{print $4}' | grep -E -o '[0-9]+')
# 3). get optional unit, by eliminating other pieces: drop name, serial, value, spaces, what's left is probably unit.. good luck.
# returns "degC"
sensor_unit=$(echo ${mod_output_pass1} | sed -E -e 's/^hw_sensors_[^ ]+//g' -e 's/\ \(.*\)$//g' -e 's/[_0-9]+//g' -e 's/\ +//g')
# 4). get actual reading, by pulling out second field (by whitespace), replace underscore with period
# returns "17.06"
sensor_reading=$(echo ${mod_output_pass1} | awk '{print $2}' | sed 's/_/\./g')
# 5). get optional serial number, by leveraging grep -o (print only match, not whole line), then drop parentheses and "sn" text
# returns "0000078fa11b"
sensor_serial=$(echo ${mod_output_pass1} | grep -E -o '\(sn\ [0-9a-z]+\)' | sed 's/[()]//g' | awk '{print $2}')
sensor_items=""
# first item, so not prepending existing list with comma
if [ ! -z "${sensor_unit}" ]; then
sensor_items="unit=\"${sensor_unit}\""
fi
if [ ! -z "${sensor_controller_id}" ]; then
sensor_items="${sensor_items},controller_id=\"${sensor_controller_id}\""
fi
if [ ! -z "${sensor_sensor_id}" ]; then
sensor_items="${sensor_items},sensor_id=\"${sensor_sensor_id}\""
fi
if [ ! -z "${sensor_serial}" ]; then
# Dirty little lookup using constants defined at top of script
sensor_name_var="SENSOR_${sensor_serial}"
sensor_item_str=$(eval "echo \$$sensor_name_var")
if [ ! -z "${sensor_item_str}" ]; then
sensor_items="${sensor_items},serial=\"${sensor_serial}\",name=\"${sensor_item_str}\""
else
# Didn't find a lookup match, just pass raw serial through
sensor_items="${sensor_items},serial=\"${sensor_serial}\""
fi
fi
if [ ! -z "${sensor_items}" ]; then
# Chop off prepended , because of my lazy join
sensor_items=$(echo ${sensor_items} | sed 's/^,//g')
echo "${sensor_name}{${sensor_items}} ${sensor_reading}"
else
echo "${sensor_name} ${sensor_reading}"
fi
done
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment