From 5b53575768abb60ed089cd572a2118e7a13bc95f Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 1 Apr 2025 20:09:14 +0200 Subject: [PATCH] expanded info and statistics logging with missing data and properties --- cpu_governor_auto_adjust/config.py | 2 +- cpu_governor_auto_adjust/schedule.py | 2 +- cpu_governor_auto_adjust/trigger.py | 26 ++++++++++++++----- cpu_governor_auto_adjust/triggers/cpu_load.py | 6 ++--- cpu_governor_auto_adjust/triggers/log.py | 8 +++--- cpu_governor_auto_adjust/triggers/roon.py | 20 +++++++------- .../triggers/test_trigger1.py | 2 +- cpu_governor_auto_adjust/triggers/time.py | 4 +-- pyproject.toml | 2 +- 9 files changed, 43 insertions(+), 29 deletions(-) diff --git a/cpu_governor_auto_adjust/config.py b/cpu_governor_auto_adjust/config.py index e6bc934..bf35872 100644 --- a/cpu_governor_auto_adjust/config.py +++ b/cpu_governor_auto_adjust/config.py @@ -18,7 +18,7 @@ class TriggerTuple(NamedTuple): custom_config: OrderedDict[str, Any] def __repr__(self) -> str: - return f"{self.name}, loglevel: {self.loglevel}, interval: {self.interval_in_seconds}, governor: {self.governor}, custom_config: {self.custom_config}" + return f"name: {self.name}, loglevel: {self.loglevel}, interval: {self.interval_in_seconds}, governor: {self.governor}, custom_config: {self.custom_config}" class Config: diff --git a/cpu_governor_auto_adjust/schedule.py b/cpu_governor_auto_adjust/schedule.py index cafa111..bc6da82 100644 --- a/cpu_governor_auto_adjust/schedule.py +++ b/cpu_governor_auto_adjust/schedule.py @@ -25,7 +25,7 @@ class TriggerScheduler(AppClass): preferred_governor: Governor = [gov for gov in _governor_list if gov.name == self._config.default_governor].pop() for trigger in self.running_triggers: self.log.debug('trigger %s, state: %s, preferred governor: %s', trigger.name, trigger.trigger_state, trigger.governor.name) - if trigger.active: + if trigger._active: if trigger.governor.priority < preferred_governor.priority: preferred_governor = trigger.governor self.log.debug('preferred governor: %s', preferred_governor.name) diff --git a/cpu_governor_auto_adjust/trigger.py b/cpu_governor_auto_adjust/trigger.py index 2c7c7da..407fdb1 100644 --- a/cpu_governor_auto_adjust/trigger.py +++ b/cpu_governor_auto_adjust/trigger.py @@ -11,7 +11,7 @@ import asyncio class Trigger(AppClass): def __init__(self, _config: Config) -> None: super().__init__(_config) - self.active: bool = False + self._active: bool = False self.log.setLevel(self.config.loglevel.upper()) self._timestamp_last_statistics = monotonic() @@ -19,18 +19,32 @@ class Trigger(AppClass): return super().__hash__(hash(self.name)) def log_statistics(self): - instance_vars = {} + class_vars = {} + + for base in reversed(self.__class__.__mro__[:-1]): + if hasattr(base, '__dict__'): + for key, value in base.__dict__.items(): + # Ignore methods and private attributes + if not key.startswith("__") and not key.startswith("_") and not callable(value): + if isinstance(value, property): + # If it's a property, call the getter method + value = value.fget(self) + if isinstance(value, cached_property): + # If it's a cached_property, call the getter method + value = value.__get__(self) + class_vars[key] = value for key, value in self.__dict__.items(): - if not key.startswith("_") and isinstance(value, (str, int, float, bool, list, dict, datetime, Governor)): + # Ignore private attributes and methods + if not key.startswith("_") and isinstance(value, (str, int, float, bool, list, dict, tuple, datetime, Governor)): if not isinstance(value, (int, float, Governor)): value = str(value) - instance_vars[key] = value - self.log.info("info and statistics: %s", instance_vars) + class_vars[key] = value + self.log.info("info and statistics: %s", class_vars) @property def trigger_state(self) -> str: - return "active" if self.active else "not active" + return "active" if self._active else "not active" @property def name(self) -> str: diff --git a/cpu_governor_auto_adjust/triggers/cpu_load.py b/cpu_governor_auto_adjust/triggers/cpu_load.py index 464264e..5496838 100644 --- a/cpu_governor_auto_adjust/triggers/cpu_load.py +++ b/cpu_governor_auto_adjust/triggers/cpu_load.py @@ -55,7 +55,7 @@ class CpuLoadTrigger(Trigger): return any(load <= threshold for load, threshold in zip(self.current_load, self.low_threshold)) def trigger_code(self) -> None: - current_active = self.active + current_active = self._active new_high_load_active = self.current_load_average_over_high_threshold new_low_load_active = self.current_load_average_over_under_threshold @@ -64,7 +64,7 @@ class CpuLoadTrigger(Trigger): "activating trigger, load: %s, high threshold: %s, governor: %s", self.current_load, self.high_threshold, self.governor.name ) - self.active = True + self._active = True elif current_active and new_high_load_active: self.log.debug( @@ -77,6 +77,6 @@ class CpuLoadTrigger(Trigger): "deactivating trigger, load: %s, low threshold: %s, governor: %s", self.current_load, self.low_threshold, self.governor.name ) - self.active = False + self._active = False else: self.log.debug("trigger is already inactive, load: %s, threshold: %s", self.current_load, self.high_threshold) diff --git a/cpu_governor_auto_adjust/triggers/log.py b/cpu_governor_auto_adjust/triggers/log.py index 5fb2d74..acebeb8 100644 --- a/cpu_governor_auto_adjust/triggers/log.py +++ b/cpu_governor_auto_adjust/triggers/log.py @@ -74,14 +74,14 @@ class LogTrigger(Trigger): def set_active(self) -> None: self.timestamp_last_active_change = datetime.now() - if not self.active: + if not self._active: self.log.info("activating trigger, log file: %s, trigger strings: %s, governor: %s", self.file, self.trigger_strings, self.governor.name) - self.active = True + self._active = True def set_inactive(self) -> None: - if self.active: + if self._active: self.log.info("deactivating trigger, log file: %s, trigger strings: %s, governor: %s", self.file, self.trigger_strings, self.governor.name) - self.active = False + self._active = False def _process_line(self, line: str) -> None: for trigger_string in self.trigger_strings: diff --git a/cpu_governor_auto_adjust/triggers/roon.py b/cpu_governor_auto_adjust/triggers/roon.py index a147ece..dd2c3df 100644 --- a/cpu_governor_auto_adjust/triggers/roon.py +++ b/cpu_governor_auto_adjust/triggers/roon.py @@ -20,14 +20,14 @@ class RoonTrigger(Trigger): def __init__(self, _config: Config) -> None: super().__init__(_config) self.set_status() - self.roonapi.register_state_callback(self.roon_state_callback, "zones_changed") + self._roonapi.register_state_callback(self.roon_state_callback, "zones_changed") def set_status(self) -> None: zones_state = list() - for zone_id in self.roonapi.zones: - self.log.debug(self.roonapi.zones[zone_id]) - zone = self.roonapi.zones[zone_id] + for zone_id in self._roonapi.zones: + self.log.debug(self._roonapi.zones[zone_id]) + zone = self._roonapi.zones[zone_id] self.log.debug("zone_id: %s zone_info: %s" , zone_id, zone) zone_name = zone['display_name'] zone_state = zone['state'] @@ -39,7 +39,7 @@ class RoonTrigger(Trigger): self.log.info("zone_id: %s name: %s, state: %s, now playing: %s" , zone_id, zone_name, zone_state, zone_now_playing) zones_state.append(zone_state) - self.active = "playing" in zones_state or "loading" in zones_state + self._active = "playing" in zones_state or "loading" in zones_state @cached_property def appinfo(self) -> dict[str, Any]: @@ -72,24 +72,24 @@ class RoonTrigger(Trigger): return _token @cached_property - def discover(self) -> RoonDiscovery: + def _discover(self) -> RoonDiscovery: return RoonDiscovery(self.core_id) @cached_property def server(self) -> RoonServer: - _server = self.discover.first() + _server = self._discover.first() assert isinstance(_server, tuple) and len(_server) == 2, "failed to discover roon server" while _server[0] is None: - _server = self.discover.first() + _server = self._discover.first() self.log.warning("roon not ready (yet)") time.sleep(1) - self.discover.stop() + self._discover.stop() roon_server = RoonServer(_server[0], _server[1]) self.log.info("found %s", roon_server) return roon_server @cached_property - def roonapi(self) -> RoonApi: + def _roonapi(self) -> RoonApi: _roonapi = RoonApi(self.appinfo, self.token, self.server.ip, self.server.port, True) return _roonapi diff --git a/cpu_governor_auto_adjust/triggers/test_trigger1.py b/cpu_governor_auto_adjust/triggers/test_trigger1.py index f3f98a1..7acac88 100644 --- a/cpu_governor_auto_adjust/triggers/test_trigger1.py +++ b/cpu_governor_auto_adjust/triggers/test_trigger1.py @@ -9,4 +9,4 @@ class TestTrigger1(Trigger): def trigger_code(self) -> None: choices = [False, True] self.log.debug("run check code of %s", self.__class__.__name__) - self.active = random.choice(choices) + self._active = random.choice(choices) diff --git a/cpu_governor_auto_adjust/triggers/time.py b/cpu_governor_auto_adjust/triggers/time.py index ccd1fd7..487e104 100644 --- a/cpu_governor_auto_adjust/triggers/time.py +++ b/cpu_governor_auto_adjust/triggers/time.py @@ -15,11 +15,11 @@ class TimeTrigger(Trigger): return datetime.strptime(self.config.custom_config['endTime'], '%H:%M').time() def trigger_code(self) -> None: - active_current = self.active + active_current = self._active active_new = self.start_time() <= datetime.now().time() <= self.end_time() if not active_current and active_new: self.log.info("activating trigger, start time: %s, end time: %s, governor: %s", self.start_time(), self.end_time(), self.governor.name) elif active_current and not active_new: self.log.info("deactivating trigger, start time: %s, end time: %s, governor: %s", self.start_time(), self.end_time(), self.governor.name) - self.active = active_new + self._active = active_new \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 8730da0..1dde605 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "cpu_governor_auto_adjust" -version = "0.5.6" +version = "0.5.7" description = "This application has been developed to automatically change cpu governor based on certain triggers." authors = [ { name = "Martin Reurekas", email = "martin@semrks.nl" }