From 2c325e9cdb16414696880922f5c355d78c7ac80b Mon Sep 17 00:00:00 2001 From: Iris De Santis Date: Mon, 5 Aug 2024 14:18:15 +0200 Subject: [PATCH] init --- .vscode/settings.json | 11 +++++++++++ src/checks/__init__.py | 0 src/checks/check_battery.py | 11 +++++++++++ src/checks/check_boot_errors.py | 10 ++++++++++ src/checks/check_cpu_usage.py | 26 ++++++++++++++++++++++++++ src/checks/check_gpu_usage.py | 22 ++++++++++++++++++++++ src/checks/log_package_updates.py | 10 ++++++++++ src/checks/log_suspension.py | 20 ++++++++++++++++++++ src/logger.py | 13 +++++++++++++ src/main.py | 31 +++++++++++++++++++++++++++++++ src/messages/__init__.py | 0 src/messages/quirky_messages.py | 12 ++++++++++++ src/system_checks.py | 0 13 files changed, 166 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 src/checks/__init__.py create mode 100644 src/checks/check_battery.py create mode 100644 src/checks/check_boot_errors.py create mode 100644 src/checks/check_cpu_usage.py create mode 100644 src/checks/check_gpu_usage.py create mode 100644 src/checks/log_package_updates.py create mode 100644 src/checks/log_suspension.py create mode 100644 src/logger.py create mode 100644 src/main.py create mode 100644 src/messages/__init__.py create mode 100644 src/messages/quirky_messages.py create mode 100644 src/system_checks.py diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e6e7934 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true + }, + "hide-files.files": [] +} \ No newline at end of file diff --git a/src/checks/__init__.py b/src/checks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/checks/check_battery.py b/src/checks/check_battery.py new file mode 100644 index 0000000..bbc7e3e --- /dev/null +++ b/src/checks/check_battery.py @@ -0,0 +1,11 @@ +import psutil +from logger import log_message + +def check_battery(): + """Check the battery status.""" + battery = psutil.sensors_battery() + if battery: + if battery.percent < 20 and not battery.power_plugged: + log_message("running out of battery,,, (less than 20%) ") + elif battery.percent == 100 and battery.power_plugged: + log_message("Battery is fully charged!!") diff --git a/src/checks/check_boot_errors.py b/src/checks/check_boot_errors.py new file mode 100644 index 0000000..f13b04e --- /dev/null +++ b/src/checks/check_boot_errors.py @@ -0,0 +1,10 @@ +from os import environ +import subprocess +from logger import log_message + +def check_boot_errors(): + """Check for boot errors using dmesg.""" + result = subprocess.run(["dmesg"], capture_output=True, text=True) + errors = result.stdout.lower().count("error") + if errors > 30: + log_message("Last boot has had more than 30 errors,, :( (according to dmesg)" + environ.get("BOT_OWNER") + " please check the logs!") diff --git a/src/checks/check_cpu_usage.py b/src/checks/check_cpu_usage.py new file mode 100644 index 0000000..4cc67a8 --- /dev/null +++ b/src/checks/check_cpu_usage.py @@ -0,0 +1,26 @@ +from os import environ +import psutil +from datetime import datetime +from logger import log_message + +cpu_overload_start = None + +def check_cpu_usage(): + """Check CPU usage and log if overloaded for more than 2 minutes.""" + global cpu_overload_start + cpu_usage = psutil.cpu_percent(interval=1) + if cpu_usage > 90: + if cpu_overload_start is None: + cpu_overload_start = datetime.now() + elif (datetime.now() - cpu_overload_start).total_seconds() > 120: + process_info = get_top_cpu_process() + log_message(f"CPU overloaded by {process_info} for more than 2 minutes,," + environ.get("BOT_OWNER") + " please do something!") + cpu_overload_start = None # Reset + else: + cpu_overload_start = None # Reset if not overloaded + +def get_top_cpu_process(): + """Get the process using the most CPU.""" + processes = [(p.info['name'], p.info['cpu_percent']) for p in psutil.process_iter(['name', 'cpu_percent'])] + top_process = max(processes, key=lambda x: x[1], default=("Unknown", 0)) + return f"{top_process[0]} ({top_process[1]}%)" diff --git a/src/checks/check_gpu_usage.py b/src/checks/check_gpu_usage.py new file mode 100644 index 0000000..4bd0896 --- /dev/null +++ b/src/checks/check_gpu_usage.py @@ -0,0 +1,22 @@ +import subprocess +from logger import log_message + +def check_gpu_usage(): + """Check AMD GPU usage using rocm-smi or radeontop if available.""" + try: + result = subprocess.run(["rocm-smi", "--showuse"], capture_output=True, text=True) + for line in result.stdout.split('\n'): + if "GPU use" in line: + usage = int(line.split()[-1].strip('%')) + if usage > 90: + log_message("GPU overloaded") + except FileNotFoundError: + try: + result = subprocess.run(["radeontop", "-d", "-", "-l", "1"], capture_output=True, text=True) + for line in result.stdout.split('\n'): + if "gpu" in line: + usage = int(line.split()[1].strip('%')) + if usage > 90: + log_message("GPU overloaded") + except FileNotFoundError: + log_message("AMD GPU monitoring tool not found") diff --git a/src/checks/log_package_updates.py b/src/checks/log_package_updates.py new file mode 100644 index 0000000..a7fdb2d --- /dev/null +++ b/src/checks/log_package_updates.py @@ -0,0 +1,10 @@ +import subprocess +from logger import log_message + +def log_package_updates(): + """Log the number of package updates.""" + result = subprocess.run(["dnf", "history", "list", "updates", "--reverse"], capture_output=True, text=True) + updates = result.stdout.split('\n')[1:-1] + if updates: + num_updates = len(updates) + log_message(f"Updated {num_updates} packages") diff --git a/src/checks/log_suspension.py b/src/checks/log_suspension.py new file mode 100644 index 0000000..3319750 --- /dev/null +++ b/src/checks/log_suspension.py @@ -0,0 +1,20 @@ +import os +from datetime import datetime +from logger import log_message + +suspend_start = None +last_suspend_time = None + +def log_suspension(): + """Log time spent in suspension.""" + global suspend_start, last_suspend_time + if os.path.exists('/var/log/pm-suspend.log'): + suspend_log_time = os.path.getmtime('/var/log/pm-suspend.log') + if last_suspend_time is None or suspend_log_time > last_suspend_time: + if suspend_start is None: + suspend_start = datetime.fromtimestamp(suspend_log_time) + else: + suspend_duration = (datetime.fromtimestamp(suspend_log_time) - suspend_start).total_seconds() / 60 + log_message(f"Spent {suspend_duration:.2f} minutes in suspension") + suspend_start = None + last_suspend_time = suspend_log_time diff --git a/src/logger.py b/src/logger.py new file mode 100644 index 0000000..49f70c4 --- /dev/null +++ b/src/logger.py @@ -0,0 +1,13 @@ +from datetime import datetime + +def log_message(message): + """Logs a message with a timestamp.""" + with open("system_health_log.txt", "a") as log_file: + log_file.write(f"{datetime.now()}: {message}\n") + print(message) + post_to_misskey(message) + +def post_to_misskey(message): + """Posts a message to Misskey.""" + # Placeholder for Misskey posting functionality + pass diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..83455ae --- /dev/null +++ b/src/main.py @@ -0,0 +1,31 @@ +from os import environ +import time +from logger import log_message, post_to_misskey +from src.messages.quirky_messages import add_quirky_messages +from checks.check_battery import check_battery +from checks.check_boot_errors import check_boot_errors +from checks.check_cpu_usage import check_cpu_usage +from checks.check_gpu_usage import check_gpu_usage +from checks.log_package_updates import log_package_updates +from checks.log_suspension import log_suspension + +def main(): + log_message("Starting system health monitoring,, ") + try: + while True: + check_boot_errors() + check_battery() + check_cpu_usage() + check_gpu_usage() + log_suspension() + log_package_updates() + add_quirky_messages() + log_message("System health check complete,, ") + # Optionally, post to Misskey + post_to_misskey("Performed system health check.") + time.sleep(300) # Wait for 5 minutes before next check + except KeyboardInterrupt: + log_message("Monitoring stopped by " + environ.get("BOT_OWNER") + " ,,") + +if __name__ == "__main__": + main() diff --git a/src/messages/__init__.py b/src/messages/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/messages/quirky_messages.py b/src/messages/quirky_messages.py new file mode 100644 index 0000000..18b8a0f --- /dev/null +++ b/src/messages/quirky_messages.py @@ -0,0 +1,12 @@ +from datetime import datetime +from logger import log_message + +def add_quirky_messages(): + """Add some quirky messages.""" + quirky_messages = [ + "Feeling a bit slow today,, need some coffee?", + "Why do programmers prefer dark mode? Because light attracts bugs!", + "If you see me lagging, just blame it on a solar flare!", + ] + message = quirky_messages[datetime.now().second % len(quirky_messages)] + log_message(message) diff --git a/src/system_checks.py b/src/system_checks.py new file mode 100644 index 0000000..e69de29