85a770ac7b
godverdomme gezeik elke keer omdat een impliciete conversie ergens niet helemaal goed is verdomme ik snap toch ook wel dat een functie die een str accepteert ook gewoon een int kan accepteren omdat python dan gewoon een impliciete conversie naar str doet wat is dat nou weer voor mierenneukerij houd eens effe op met me
139 lines
4.4 KiB
Python
Executable File
139 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Simple stat daemon
|
|
# Listens on a port for requests, responds with some basic information about the current state of the system.
|
|
|
|
import configparser
|
|
import os
|
|
import subprocess
|
|
import time
|
|
import argparse
|
|
import json
|
|
import http.server
|
|
import socketserver
|
|
|
|
def get_default_config():
|
|
config = configparser.ConfigParser(interpolation=None)
|
|
config['stat.system.uptime'] = {
|
|
'command': 'uptime -p | cut -d" " -f2-',
|
|
'format': '{}'
|
|
}
|
|
config['stat.cpu.temp'] = {
|
|
'command': 'sensors -j | jq \'.["k10temp-pci-00c3"]["Tctl"]["temp1_input"]\'',
|
|
'transform': 'lambda x: float(x)',
|
|
'format': '{:.1f}',
|
|
'unit': '°C',
|
|
'historical': '1'
|
|
}
|
|
config['stat.cpu.act'] = {
|
|
'command': 'top -bn1 | grep "Cpu(s)" | sed "s/.*, *\\([0-9.]*\\)%%* id.*/\\1/" | awk \'{print 100-$1}\'',
|
|
'transform': 'lambda x: float(x)',
|
|
'format': '{:.1f}',
|
|
'unit': '%',
|
|
'historical': '1'
|
|
}
|
|
config['stat.memory.pct'] = {
|
|
'command': 'free | awk \'NR==2 {printf "%.1f", $3*100/$2}\'',
|
|
'transform': 'lambda x: float(x)',
|
|
'format': '{:.1f}',
|
|
'unit': '%',
|
|
'historical': '1'
|
|
}
|
|
config['stat.memory.total'] = {
|
|
'command': 'free -m | awk \'NR==2 {print $2}\'',
|
|
'transform': 'lambda x: int(x)',
|
|
'format': '{}',
|
|
'unit': 'MB'
|
|
}
|
|
config['stat.disk.root'] = {
|
|
'command': 'df -h / | awk \'NR==2 {printf "%s/%s [%d%%]", $3, $2, $5}\'',
|
|
'format': '{}'
|
|
}
|
|
return config
|
|
|
|
def get_config():
|
|
config_home = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
|
|
config_dir = os.path.join(config_home, "stats")
|
|
if not os.path.exists(config_dir):
|
|
os.makedirs(config_dir)
|
|
config_file = os.path.join(config_dir, "config.ini")
|
|
|
|
config = configparser.ConfigParser(interpolation=None)
|
|
|
|
if os.path.exists(config_file):
|
|
config.read(config_file)
|
|
else:
|
|
config = get_default_config()
|
|
with open(config_file, 'w') as f:
|
|
config.write(f)
|
|
return config
|
|
|
|
def get_stats(config):
|
|
stats = {}
|
|
stat_sections = [s for s in config.sections() if s.startswith('stat.')]
|
|
for section in stat_sections:
|
|
# Split into category and name
|
|
_, category, name = section.split('.')
|
|
stat_config = config[section]
|
|
if category not in stats:
|
|
stats[category] = {}
|
|
|
|
try:
|
|
value = subprocess.getoutput(stat_config['command']).strip()
|
|
|
|
transform = stat_config.get('transform', None)
|
|
format = stat_config.get('format', None)
|
|
unit = stat_config.get('unit', None)
|
|
historical = stat_config.get('historical', False)
|
|
if transform:
|
|
transform_func = eval(transform)
|
|
value = transform_func(value)
|
|
if format:
|
|
value = format.format(value)
|
|
data = {
|
|
'value': value
|
|
}
|
|
if unit:
|
|
data['unit'] = unit
|
|
if historical:
|
|
data['track'] = bool(historical)
|
|
stats[category][name] = data
|
|
|
|
except Exception as e:
|
|
print(e)
|
|
#stats[category][name] = f"Error: {str(e)}"
|
|
return stats
|
|
|
|
class StatsHandler(http.server.SimpleHTTPRequestHandler):
|
|
def do_GET(self):
|
|
data = {
|
|
'timestamp': time.time(),
|
|
'stats': get_stats(get_config())
|
|
}
|
|
response = json.dumps(data).encode('utf-8')
|
|
|
|
self.send_response(200)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.send_header('Content-Length', str(len(response)))
|
|
self.end_headers()
|
|
self.wfile.write(response)
|
|
|
|
class StatsServer(socketserver.TCPServer):
|
|
allow_reuse_address = True
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='Stats HTTP Server')
|
|
parser.add_argument('--port', type=int, default=5747, help='Port to listen on')
|
|
parser.add_argument('--host', default='0.0.0.0', help='Host to bind to')
|
|
args = parser.parse_args()
|
|
|
|
with StatsServer((args.host, args.port), StatsHandler) as httpd:
|
|
print(f"Serving stats on http://{args.host}:{args.port}")
|
|
try:
|
|
httpd.serve_forever()
|
|
except KeyboardInterrupt:
|
|
print("\nShutting down server...")
|
|
httpd.server_close()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|