diff --git a/docs/Command_Templates.md b/docs/Command_Templates.md index 5296e52b..7e7d07bc 100644 --- a/docs/Command_Templates.md +++ b/docs/Command_Templates.md @@ -307,6 +307,9 @@ The following are common printer attributes: between micro-controller architectures and with each code revision. - `printer.mcu.last_stats.`: Statistics information on the micro-controller connection. +- `printer.system_stats.sysload`, `printer.system_stats.cputime`, + `printer.system_stats.memavail`: Information on the host operating + system and process load. The above list is subject to change - if using an attribute be sure to review the [Config Changes document](Config_Changes.md) when upgrading diff --git a/klippy/extras/statistics.py b/klippy/extras/statistics.py index 1adcdce4..641396a3 100644 --- a/klippy/extras/statistics.py +++ b/klippy/extras/statistics.py @@ -1,25 +1,53 @@ # Support for logging periodic statistics # -# Copyright (C) 2018-2020 Kevin O'Connor +# Copyright (C) 2018-2021 Kevin O'Connor # # This file may be distributed under the terms of the GNU GPLv3 license. import os, time, logging -def get_os_stats(eventtime): - # Get core usage stats - msg = "sysload=%.2f cputime=%.3f" % (os.getloadavg()[0], time.clock()) - # Get available system memory - try: - f = open("/proc/meminfo", "rb") - data = f.read() - f.close() - for line in data.split('\n'): - if line.startswith("MemAvailable:"): - msg = "%s memavail=%s" % (msg, line.split()[1]) - break - except: - pass - return (False, msg) +class PrinterSysStats: + def __init__(self, config): + printer = config.get_printer() + self.last_process_time = self.total_process_time = 0. + self.last_load_avg = 0. + self.last_mem_avail = 0 + self.mem_file = None + try: + self.mem_file = open("/proc/meminfo", "rb") + except: + pass + printer.register_event_handler("klippy:disconnect", self._disconnect) + def _disconnect(self): + if self.mem_file is not None: + self.mem_file.close() + self.mem_file = None + def stats(self, eventtime): + # Get core usage stats + ptime = time.clock() + pdiff = ptime - self.last_process_time + self.last_process_time = ptime + if pdiff > 0.: + self.total_process_time += pdiff + self.last_load_avg = os.getloadavg()[0] + msg = "sysload=%.2f cputime=%.3f" % (self.last_load_avg, + self.total_process_time) + # Get available system memory + if self.mem_file is not None: + try: + self.mem_file.seek(0) + data = self.mem_file.read() + for line in data.split('\n'): + if line.startswith("MemAvailable:"): + self.last_mem_avail = int(line.split()[1]) + msg = "%s memavail=%d" % (msg, self.last_mem_avail) + break + except: + pass + return (False, msg) + def get_status(self, eventtime): + return {'sysload': self.last_load_avg, + 'cputime': self.total_process_time, + 'memavail': self.last_mem_avail} class PrinterStats: def __init__(self, config): @@ -37,10 +65,10 @@ class PrinterStats: def generate_stats(self, eventtime): stats = [cb(eventtime) for cb in self.stats_cb] if max([s[0] for s in stats]): - stats.append(get_os_stats(eventtime)) logging.info("Stats %.1f: %s", eventtime, ' '.join([s[1] for s in stats])) return eventtime + 1. def load_config(config): + config.get_printer().add_object('system_stats', PrinterSysStats(config)) return PrinterStats(config)