configure collectd

This commit is contained in:
2025-01-03 09:42:20 +01:00
parent b8471944b0
commit d967b73db4
18 changed files with 314 additions and 1162 deletions

43
collectd/Dockerfile Normal file
View File

@@ -0,0 +1,43 @@
FROM debian:bookworm
ENV DEBIAN_FRONTEND=noninteractive
ENV TIMEZONE=Europe/Amsterdam
RUN apt update --fix-missing
RUN apt dist-upgrade -y --no-install-recommends
RUN echo $TIMEZONE > /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata
RUN apt install -y libsensors5 liblzo2-2 collectd btrfs-progs libatasmart4 speedtest-cli
RUN apt install -y smartmontools
RUN apt install -y wget git
ENV HDDTEMP_VERSION=0.3.1
RUN wget https://github.com/slowpeek/hddtemp/archive/refs/tags/${HDDTEMP_VERSION}.tar.gz \
&& tar xvf ${HDDTEMP_VERSION}.tar.gz && mv hddtemp-${HDDTEMP_VERSION}/hddtemp-lt /usr/sbin/hddtemp
RUN apt -y install make g++ python3 python3-dev python3-pybind11 cmake
COPY PMT /pmt
#RUN git clone https://git.astron.nl:/RD/pmt
RUN cmake -Spmt -Bpmt/build -DPMT_BUILD_RAPL=1 -DPMT_BUILD_BINARY=1 -DPMT_BUILD_PYTHON=1 -DCMAKE_INSTALL_PREFIX=/opt/pmt
RUN make -Cpmt/build -j install
ENV LD_LIBRARY_PATH="/opt/pmt/lib"
ENV PYTHONPATH="/opt/pmt/lib/python3.11/site-packages"
ENV PATH="$PATH:/opt/pmt/bin"
RUN apt -y remove make g++ python3-dev python3-pybind11 cmake
RUN apt autoremove -y
RUN apt -y install sudo
RUN adduser collectd
RUN usermod -aG sudo collectd
RUN echo 'collectd ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/collectd
RUN apt install -y --no-install-recommends python3-pip
RUN pip install --break-system-packages requests
CMD ["/usr/sbin/collectd", "-f"]

View File

@@ -1,35 +0,0 @@
FROM debian:bookworm
ENV LC_ALL=C
ENV DEBIAN_FRONTEND=noninteractive
ENV TIMEZONE=Europe/Amsterdam
RUN apt update
RUN apt dist-upgrade -y --no-install-recommends
RUN echo $TIMEZONE > /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata
RUN apt install -y libsensors5 liblzo2-2 collectd sudo btrfs-progs libatasmart4 speedtest-cli
RUN apt install -y smartmontools
RUN apt install -y wget git
ENV HDDTEMP_VERSION=0.2.4
RUN wget https://github.com/slowpeek/hddtemp/archive/refs/tags/${HDDTEMP_VERSION}.tar.gz \
&& tar xvf ${HDDTEMP_VERSION}.tar.gz && mv hddtemp-${HDDTEMP_VERSION}/hddtemp-lt /usr/sbin/hddtemp
RUN apt install -y gcc python3-dev make
RUN git clone https://github.com/RRZE-HPC/likwid.git
RUN cd likwid && make -j && make install
RUN git clone https://github.com/RRZE-HPC/pylikwid.git
RUN cd pylikwid && python3 setup.py build_ext && python3 setup.py install
RUN apt remove -y gcc python-dev make
RUN apt autoremove -y
RUN useradd collectd
RUN usermod -aG sudo collectd
RUN echo 'collectd ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/collectd
CMD /usr/sbin/collectd -f

View File

@@ -1,31 +0,0 @@
FROM debian:buster
ENV LC_ALL=C
ENV DEBIAN_FRONTEND=noninteractive
ENV TIMEZONE=Europe/Amsterdam
RUN apt update
RUN apt dist-upgrade -y --no-install-recommends
RUN echo $TIMEZONE > /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata
RUN apt install -y software-properties-common gpgv dirmngr psmisc wget curl python3-pip git gawk zip gperf unzip lbzip2 inetutils-ping inetutils-telnet rsync
RUN pip3 install argparse
RUN apt install -y libsensors5 liblzo2-2 hddtemp collectd sudo btrfs-progs libatasmart4 speedtest-cli
RUN useradd collectd
RUN usermod -aG sudo collectd
RUN echo 'collectd ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/collectd
RUN apt install -y gcc python-dev make
RUN git clone https://github.com/RRZE-HPC/likwid.git
RUN cd likwid && make -j && make install
RUN git clone https://github.com/RRZE-HPC/pylikwid.git
RUN cd pylikwid && python setup.py build_ext && python setup.py install
ENV LD_LIBRARY_PATH /usr/local/lib
CMD /usr/sbin/collectd -f

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
LoadPlugin exec LoadPlugin exec
<Plugin "exec"> <Plugin "exec">
Exec collectd "/host/usr/local/bin/btrfs-data" Exec collectd "/host/usr/local/bin/btrfs-data"
</Plugin> </Plugin>

View File

@@ -0,0 +1,5 @@
LoadPlugin exec
<Plugin "exec">
Exec collectd "/host/usr/local/bin/cpufreq-data"
</Plugin>

View File

@@ -1,6 +1,5 @@
<Plugin "df"> <Plugin df>
MountPoint "/mnt/due" MountPoint "/media/docker"
MountPoint "/mnt/quattro" FSType "ext4"
MountPoint "/mnt/mezzo/var/lib/docker" IgnoreSelected false
</Plugin> </Plugin>

View File

@@ -1,6 +1,5 @@
LoadPlugin exec LoadPlugin exec
<Plugin "exec"> <Plugin "exec">
Exec collectd "/host/usr/local/bin/du-data" Exec collectd "/host/usr/local/bin/du-data"
</Plugin> </Plugin>

View File

@@ -1,6 +1,5 @@
LoadPlugin exec LoadPlugin exec
<Plugin "exec"> <Plugin "exec">
Exec nobody "/host/usr/local/bin/speedtest-data" Exec nobody "/host/usr/local/bin/speedtest-data"
</Plugin> </Plugin>

View File

@@ -1,18 +1,20 @@
#!/usr/bin/python -u #!/usr/bin/python3
# #
# Imports # Imports
# #
import sys import sys
import time import time
import commands import subprocess
import argparse import argparse
#sys.exit(1)
# #
# Misc # Misc
# #
#sys.tracebacklimit = 0 # sys.tracebacklimit = 0
# #
@@ -28,26 +30,27 @@ size_snapshot_exclusive = 0
# Methods # Methods
# #
def get_subvol_list(path): def get_subvol_list(path):
command = 'sudo btrfs subvolume list -t %s' % (path) command = "sudo btrfs subvolume list -t %s" % (path)
status, output = commands.getstatusoutput(command) status, output = subprocess.getstatusoutput(command)
if status is not 0: if status != 0:
raise Exception(command) raise Exception(command)
# Every line contains the following values: subvol_id, gen, toplevel, path # Every line contains the following values: subvol_id, gen, toplevel, path
return output.splitlines()[2:] return output.splitlines()[2:]
def get_filesystem_size(path):
command = 'sudo btrfs filesystem show --raw %s' % (path)
status, output = commands.getstatusoutput(command)
if status is not 0 or True: def get_filesystem_size(path):
command = "sudo btrfs filesystem show --raw %s" % (path)
status, output = subprocess.getstatusoutput(command)
if status != 0:
# This command fails when running inside Docker container # This command fails when running inside Docker container
# return maximum size of any filesystem instead # return maximum size of any filesystem instead
command = 'sudo btrfs filesystem show --raw' command = "sudo btrfs filesystem show --raw"
status, output = commands.getstatusoutput(command) status, output = subprocess.getstatusoutput(command)
lines = output.splitlines() lines = output.splitlines()
lines = filter(lambda x: 'devid' in x, lines) lines = [x for x in lines if "devid" in x]
sizes = [int(line.split()[3]) for line in lines] sizes = [int(line.split()[3]) for line in lines]
return max(sizes) return max(sizes)
@@ -57,11 +60,12 @@ def get_filesystem_size(path):
# Element 3 and 5 respectively contain total and used sizes # Element 3 and 5 respectively contain total and used sizes
return int(line.split()[3]) return int(line.split()[3])
def get_id_root(name, path): def get_id_root(name, path):
lines = get_subvol_list(path) lines = get_subvol_list(path)
# Filter lines where toplevel == 5 # Filter lines where toplevel == 5
subvol_ids = filter(lambda x: int(x.split()[2]) == 5, lines) subvol_ids = [x for x in lines if int(x.split()[2]) == 5]
# Try to retrieve the subvol_id for the root subvolume (if any) # Try to retrieve the subvol_id for the root subvolume (if any)
if len(subvol_ids) == 1: if len(subvol_ids) == 1:
@@ -70,18 +74,18 @@ def get_id_root(name, path):
else: else:
# The path contains a btrfs filesystem with multiple subvolumes for data # The path contains a btrfs filesystem with multiple subvolumes for data
try: try:
return int(filter(lambda x: x.split()[3] == name, subvol_ids)[0].split()[0]) return int(list(filter(lambda x: x.split()[3] == name, subvol_ids))[0].split()[0])
except IndexError: except IndexError:
pass pass
# Volume not found, root is probably the btrfs default (5) # Volume not found, root is probably the btrfs default (5)
return 5 return 5
def get_id_subvolumes(path, subvol_id): def get_id_subvolumes(path, subvol_id):
lines = get_subvol_list(path) lines = get_subvol_list(path)
lines = filter(lambda x: int(x.split()[2]) == subvol_id, lines) lines = [x for x in lines if int(x.split()[2]) == subvol_id]
return list(map(lambda x: int(x.split()[0]), lines)) return list([int(x.split()[0]) for x in lines])
def get_disk_usage(name, path): def get_disk_usage(name, path):
@@ -90,10 +94,10 @@ def get_disk_usage(name, path):
size_filesystem = get_filesystem_size(path) size_filesystem = get_filesystem_size(path)
# Get disk usage from quota # Get disk usage from quota
command = 'sudo btrfs qgroup show --raw %s' % (path) command = "sudo btrfs qgroup show --raw %s" % (path)
status, output = commands.getstatusoutput(command) status, output = subprocess.getstatusoutput(command)
if status is not 0: if status != 0:
raise Exception(command) raise Exception(command)
lines = output.splitlines()[2:] lines = output.splitlines()[2:]
@@ -125,11 +129,11 @@ def get_disk_usage(name, path):
size_total = 0 size_total = 0
size_exclusive = 0 size_exclusive = 0
try: try:
subvol_id = int(split[0].split('/')[1]) subvol_id = int(split[0].split("/")[1])
size_total = float(split[1]) size_total = float(split[1])
size_exclusive = float(split[2]) size_exclusive = float(split[2])
except IndexError: except IndexError:
# ignore 'WARNING: Quota disabled' # ignore "WARNING: Quota disabled"
pass pass
# size_exclusive is incorrect when snapshot is # size_exclusive is incorrect when snapshot is
@@ -145,51 +149,83 @@ def get_disk_usage(name, path):
size_snapshot_total += size_total size_snapshot_total += size_total
size_snapshot_exclusive += size_exclusive size_snapshot_exclusive += size_exclusive
def rescan_quota(path): def rescan_quota(path):
command = 'sudo btrfs quota rescan %s' % (path) command = "sudo btrfs quota rescan %s" % (path)
status, output = commands.getstatusoutput(command) status, output = subprocess.getstatusoutput(command)
if status is not 0: if status != 0:
Exception(command) Exception(command)
def print_human_readable(name): def print_human_readable(name):
global size_data_total global size_data_total
global size_data_exclusive global size_data_exclusive
global size_snapshot_exclusive global size_snapshot_exclusive
size_data_total = size_data_total / (1024*1e6) size_data_total = size_data_total / (1024 * 1e6)
size_data_exclusive = size_data_exclusive / (1024*1e6) size_data_exclusive = size_data_exclusive / (1024 * 1e6)
size_snapshot_exclusive = size_snapshot_exclusive / (1024*1e6) size_snapshot_exclusive = size_snapshot_exclusive / (1024 * 1e6)
print '%10s: %6.1f Gb, %6.1f Gb, %6.1f Gb' % (name, size_data_total, size_data_exclusive, size_snapshot_exclusive) print(
"%10s: %6.1f Gb, %6.1f Gb, %6.1f Gb"
% (name, size_data_total, size_data_exclusive, size_snapshot_exclusive)
)
def print_rrd(name): def print_rrd(name):
timestamp = int(time.time()) timestamp = int(time.time())
print('PUTVAL {}/exec-btrfs_{}/gauge-data_total {}:{:.1f}'.format(hostname, name, timestamp, size_data_total)) print(
print('PUTVAL {}/exec-btrfs_{}/gauge-data_exclusive {}:{:.1f}'.format(hostname, name, timestamp, size_data_exclusive)) (
print('PUTVAL {}/exec-btrfs_{}/gauge-snapshot_total {}:{:.1f}'.format(hostname, name, timestamp, size_snapshot_total)) "PUTVAL {}/exec-btrfs_{}/gauge-data_total {}:{:.1f}".format(
print('PUTVAL {}/exec-btrfs_{}/gauge-snapshot_exclusive {}:{:.1f}'.format(hostname, name, timestamp, size_snapshot_exclusive)) hostname, name, timestamp, size_data_total
)
)
)
print(
(
"PUTVAL {}/exec-btrfs_{}/gauge-data_exclusive {}:{:.1f}".format(
hostname, name, timestamp, size_data_exclusive
)
)
)
print(
(
"PUTVAL {}/exec-btrfs_{}/gauge-snapshot_total {}:{:.1f}".format(
hostname, name, timestamp, size_snapshot_total
)
)
)
print(
(
"PUTVAL {}/exec-btrfs_{}/gauge-snapshot_exclusive {}:{:.1f}".format(
hostname, name, timestamp, size_snapshot_exclusive
)
)
)
# #
# Volumes to scan # Volumes to scan
# #
hostname = 'server' hostname = "shuttle"
interval = 10 interval = 10
volumes = [ volumes = list()
['mezzo-scratch', '/mnt/mezzo/scratch'],
['mezzo-sync', '/mnt/mezzo/sync'],
['helium-personal', '/mnt/yotta/helium/personal'],
['helium-shared', '/mnt/yotta/helium/shared'],
['neon', '/mnt/yotta/neon'],
['krypton', '/mnt/yotta/krypton'],
['xenon-borg', '/mnt/yotta/xenon/borg'],
['xenon-rsnapshot', '/mnt/yotta/xenon/rsnapshot']
]
# SSD
volumes.append(["scratch", "/host/root/mnt/mezzo/scratch"])
volumes.append(["sync", "/host/root/mnt/mezzo/sync"])
# HDD
volumes.append(["personal", "/host/root/mnt/yotta/helium/personal"])
volumes.append(["shared", "/host/root/mnt/yotta/helium/shared"])
volumes.append(["neon", "/host/root/mnt/yotta/neon"])
volumes.append(["krypton", "/host/root/mnt/yotta/krypton"])
volumes.append(["borg", "/host/root/mnt/yotta/xenon/borg"])
volumes.append(["rsnapshot", "/host/root/mnt/yotta/xenon/rsnapshot"])
# #
# Command line arguments # Command line arguments
# #
parser = argparse.ArgumentParser(description='Get BTRFS disk usage') parser = argparse.ArgumentParser(description="Get BTRFS disk usage")
parser.add_argument('-s', action='store_true', help='print in human readable format') parser.add_argument("-s", action="store_true", help="print in human readable format")
args = parser.parse_args() args = parser.parse_args()
human_readable = args.s human_readable = args.s
@@ -198,15 +234,17 @@ human_readable = args.s
# Main # Main
# #
if human_readable: if human_readable:
for name, path in volumes: for (name, path) in volumes:
get_disk_usage(name, path) get_disk_usage(name, path)
print_human_readable(name) print_human_readable(name)
else: else:
# RRD mode # RRD mode
while True: while True:
for name, path in volumes: for (name, path) in volumes:
get_disk_usage(name, path) get_disk_usage(name, path)
print_rrd(name) print_rrd(name)
sys.stdout.flush()
time.sleep(interval) time.sleep(interval)
rescan_quota(path) # rescan_quota(path)

View File

@@ -0,0 +1,58 @@
#!/usr/bin/python3
import argparse
import time
import sys
import os
hostname = "shuttle"
measurement_interval = 5
def get_cpu_frequencies():
frequencies = []
try:
cpu_dirs = [
d
for d in os.listdir("/sys/devices/system/cpu/")
if d.startswith("cpu") and d[3:].isdigit()
]
for cpu_dir in cpu_dirs:
with open(
f"/sys/devices/system/cpu/{cpu_dir}/cpufreq/scaling_cur_freq", "r"
) as f:
frequency = int(f.read().strip()) / 1000 # Convert Hz to MHz
frequencies.append((int(cpu_dir[3:]), frequency))
except Exception as e:
print("Error:", e)
return frequencies
def main():
parser = argparse.ArgumentParser(description="Query CPU frequencies.")
parser.add_argument(
"-s",
"--human-readable",
action="store_true",
help="Print frequencies in human-readable format",
)
args = parser.parse_args()
if args.human_readable:
frequencies = get_cpu_frequencies()
for cpu, frequency in frequencies:
print(f"CPU{cpu} Frequency: {frequency:.2f} MHz")
else:
while True:
frequencies = get_cpu_frequencies()
timestamp = int(time.time())
for cpu, frequency in frequencies:
print(
f"PUTVAL {hostname}/cpu-frequency/gauge-cpu{cpu} {timestamp}:{frequency:.0f}"
)
sys.stdout.flush()
time.sleep(measurement_interval)
if __name__ == "__main__":
main()

View File

@@ -1,12 +1,11 @@
#!/usr/bin/python #!/usr/bin/python3
# #
# Imports # Imports
# #
import os
import sys import sys
import time import time
import commands import subprocess
import argparse import argparse
@@ -14,13 +13,12 @@ import argparse
# Methods # Methods
# #
def get_disk_usage(path, human_readable): def get_disk_usage(path, human_readable):
'''disk usage in human readable format (e.g. '2,1GB')''' """disk usage in human readable format (e.g. '2,1GB')"""
arguments = '-sh' if human_readable else '-s' arguments = "-sh" if human_readable else "-s"
path = os.path.realpath(path) command = "du %s %s" % (arguments, path)
command = 'sudo du %s %s' % (arguments, path) status, output = subprocess.getstatusoutput(command)
status, output = commands.getstatusoutput(command)
if status is not 0: if status != 0:
raise Exception(command) raise Exception(command)
disk_usage = output.split()[0] disk_usage = output.split()[0]
@@ -29,13 +27,13 @@ def get_disk_usage(path, human_readable):
disk_usage = int(disk_usage) * 1024 disk_usage = int(disk_usage) * 1024
return disk_usage return disk_usage
# #
# Directories to scan # Directories to scan
# #
hostname = 'server' hostname = 'shuttle'
interval = 10 interval = 10
directories = [ directories = [
#['bram', '/media/data/Personal/Bram'],
['rik', '/media/data/Personal/Rik'], ['rik', '/media/data/Personal/Rik'],
['books', '/media/data/Shared/Books'], ['books', '/media/data/Shared/Books'],
['games', '/media/data/Shared/Games'], ['games', '/media/data/Shared/Games'],
@@ -45,15 +43,14 @@ directories = [
['music', '/media/data/Shared/Music'], ['music', '/media/data/Shared/Music'],
['photographs', '/media/data/Shared/Photographs'], ['photographs', '/media/data/Shared/Photographs'],
['pictures', '/media/data/Shared/Pictures'], ['pictures', '/media/data/Shared/Pictures'],
['raw', '/media/data/Shared/Raw'],
['software', '/media/data/Shared/Software'] ['software', '/media/data/Shared/Software']
] ]
# #
# Command line arguments # Command line arguments
# #
parser = argparse.ArgumentParser(description='Get BTRFS disk usage') parser = argparse.ArgumentParser(description="Get DU disk usage")
parser.add_argument('-s', action='store_true', help='print in human readable format') parser.add_argument("-s", action="store_true", help="print in human readable format")
args = parser.parse_args() args = parser.parse_args()
human_readable = args.s human_readable = args.s
@@ -61,10 +58,10 @@ human_readable = args.s
# #
# Main # Main
# #
if (human_readable): if human_readable:
for (name, path) in directories: for (name, path) in directories:
disk_usage = get_disk_usage(path, human_readable) disk_usage = get_disk_usage(path, human_readable)
print('%s: %s' % (name, disk_usage)) print(("%s: %s" % (name, disk_usage)))
else: else:
# RRD mode # RRD mode
while True: while True:
@@ -72,6 +69,12 @@ else:
disk_usage = get_disk_usage(path, human_readable) disk_usage = get_disk_usage(path, human_readable)
timestamp = int(time.time()) timestamp = int(time.time())
size = float(disk_usage) size = float(disk_usage)
print('PUTVAL {}/exec-du_{}/gauge-size {}:{:.1f}'.format(hostname, name, timestamp, size)) print(
(
"PUTVAL {}/exec-du_{}/gauge-size {}:{:.1f}".format(
hostname, name, timestamp, size
)
)
)
sys.stdout.flush() sys.stdout.flush()
time.sleep(interval) time.sleep(interval)

View File

@@ -1,10 +1,11 @@
#!/usr/bin/env python #!/usr/bin/python3
import sys
import os import os
import requests import requests
import re import re
import time import time
import datetime import datetime
import sys
import random import random
collection = 'funds' collection = 'funds'
@@ -55,7 +56,7 @@ def morningstar_ticker(funds):
def put_value(fund, value, timestamp = 'N'): def put_value(fund, value, timestamp = 'N'):
print('PUTVAL {}/exec-fund-{}/gauge-ticker interval={} {}:{}'.format(collection, fund, interval, timestamp, value)) print('PUTVAL {}/exec-fund-{}/gauge-ticker interval={} {}:{}'.format(collection, fund, interval, timestamp, value))
sys.stdout.flush() sys.stdout.flush()
if timestamp is 'N': if timestamp == 'N':
timestamp = int(time.time()) timestamp = int(time.time())
# log.write('{},{},{}\n'.format(fund, timestamp, int(value))) # log.write('{},{},{}\n'.format(fund, timestamp, int(value)))

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/python3
# #
# Imports # Imports
@@ -6,61 +6,58 @@
import sys import sys
import time import time
import argparse import argparse
import pylikwid import pmt
# #
# Configuration # Configuration
# #
hostname = 'server' hostname = "shuttle"
cpuid = 0 measurement_duration = 5
pinfo = pylikwid.getpowerinfo() measurement_interval = 15
domainid = pinfo.get('domains').get('PKG').get('ID') pm = pmt.create("rapl")
measurement_duration = 10
measurement_interval = 60
dinfo = pinfo.get('domains')
domain_names = dinfo.keys()
domain_ids = [domain['ID'] for domain in dinfo.values()]
# #
# Command line arguments # Command line arguments
# #
parser = argparse.ArgumentParser(description='Get CPU power consumption') parser = argparse.ArgumentParser(description="Get CPU power consumption")
parser.add_argument('-s', action='store_true', help='print in human readable format') parser.add_argument("-s", action="store_true", help="print in human readable format")
args = parser.parse_args() args = parser.parse_args()
human_readable = args.s human_readable = args.s
# #
# Methods # Methods
# #
def get_power(): def get_power():
#print dict(zip(domain_names, domain_ids))
start = list()
end = list()
power = list()
for domain_id in domain_ids:
e_start = pylikwid.startpower(cpuid, domain_id)
start.append(e_start)
time.sleep(measurement_duration) time.sleep(measurement_duration)
for domain_id in domain_ids: measurements = dict()
e_stop = pylikwid.stoppower(cpuid, domain_id) state = pm.read()
end.append(e_stop) for i in range(state.nr_measurements()):
for events in zip(start, end, domain_ids): name = state.name(i)
power.append(pylikwid.getpower(events[0], events[1], events[2])) watts = state.watts(i)
measurements[name] = watts
return measurements
return dict(zip(domain_names, power))
def print_rrd(measurements): def print_rrd(measurements):
timestamp = int(time.time()) timestamp = int(time.time())
for measurement in measurements.items(): for measurement in list(measurements.items()):
name = measurement[0].lower() name = measurement[0].lower()
power = measurement[1] power = measurement[1]
print('PUTVAL {}/exec-power/gauge-{} {}:{:.1f}'.format(hostname, name, timestamp, power)) print(
(
"PUTVAL {}/exec-power/gauge-{} {}:{:.1f}".format(
hostname, name, timestamp, power
)
)
)
# #
# Main # Main
# #
if (human_readable): if human_readable:
print get_power() print(get_power())
else: else:
while True: while True:
power = get_power() power = get_power()

View File

@@ -1,12 +1,16 @@
#!/bin/bash #!/bin/bash
SPEEDTEST=/sbin/speedtest-cli
COLLECTION=server SPEEDTEST=/usr/bin/speedtest-cli
INTERVAL=1800 COLLECTION=shuttle
INTERVAL=900
while :; do while :; do
SECONDS=0 SECONDS=0
RESULT=($($SPEEDTEST | grep Mbit | cut -d' ' -f 2)) RESULT=($($SPEEDTEST | grep Mbit | cut -d' ' -f 2))
echo "PUTVAL $COLLECTION/exec-speedtest/gauge-download interval=$INTERVAL N:${RESULT[0]}" TIMESTAMP=$(date +%s)
echo "PUTVAL $COLLECTION/exec-speedtest/gauge-upload interval=$INTERVAL N:${RESULT[1]}" #echo "PUTVAL $COLLECTION/exec-speedtest/gauge-download interval=$INTERVAL N:${RESULT[0]}"
#echo "PUTVAL $COLLECTION/exec-speedtest/gauge-upload interval=$INTERVAL N:${RESULT[1]}"
echo "PUTVAL $COLLECTION/exec-speedtest/gauge-download ${TIMESTAMP}:${RESULT[0]}"
echo "PUTVAL $COLLECTION/exec-speedtest/gauge-upload ${TIMESTAMP}:${RESULT[1]}"
sleep $((INTERVAL-$SECONDS)) sleep $((INTERVAL-$SECONDS))
done done

View File

@@ -1,23 +1,22 @@
#!/usr/bin/python -u #!/usr/bin/python3
# #
# Imports # Imports
# #
import sys import sys
import time import time
import commands
import argparse import argparse
import subprocess
# #
# Methods # Methods
# #
def get_temperature(disks): def get_temperature(disks):
command = "sudo smartctl -a /dev/%s | grep Temperature_Celsius | awk '{print $10}'" % disk command = "sudo smartctl -a /dev/%s | grep Temperature_Celsius | awk '{print $10}'" % disk
status, output = commands.getstatusoutput(command) result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
try: try:
return int(output) return int(result.stdout)
except Exception as e: except Exception as e:
return None return None
@@ -25,9 +24,9 @@ def get_temperature(disks):
# #
# Settings # Settings
# #
hostname = 'server' hostname = 'shuttle'
interval = 10 interval = 10
disks = ['sdd', 'sde', 'sdf'] disks = ['sda', 'sdb', 'sdc', 'sdd']
# #
@@ -40,4 +39,3 @@ while True:
if temperature: if temperature:
print('PUTVAL {}/exec-temperature/gauge-{}_total {}:{}'.format(hostname, disk, timestamp, temperature)) print('PUTVAL {}/exec-temperature/gauge-{}_total {}:{}'.format(hostname, disk, timestamp, temperature))
time.sleep(interval) time.sleep(interval)

View File

@@ -0,0 +1,17 @@
services:
collectd:
build:
context: /home/user/src
dockerfile: /opt/collectd/Dockerfile
container_name: collectd
image: collectd:bookworm
privileged: true
restart: unless-stopped
volumes:
- /opt/collectd/etc:/etc/collectd
- /opt/collectd/var:/var/lib/collectd
- /opt/collectd/usr:/host/usr
- /:/host/root:ro
- /media/data:/media/data:ro
- /var/lib/docker:/media/docker:ro
- /dev/mapper:/dev/mapper

View File

@@ -6,6 +6,7 @@ include:
- docker-compose.authentik.yaml - docker-compose.authentik.yaml
# Other # Other
- docker-compose.collectd.yaml
- docker-compose.homarr.yaml - docker-compose.homarr.yaml
- docker-compose.homeassistant.yaml - docker-compose.homeassistant.yaml
- docker-compose.grafana.yaml - docker-compose.grafana.yaml