expanded info and statistics logging with missing data and properties
This commit is contained in:
@@ -18,7 +18,7 @@ class TriggerTuple(NamedTuple):
|
|||||||
custom_config: OrderedDict[str, Any]
|
custom_config: OrderedDict[str, Any]
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
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:
|
class Config:
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class TriggerScheduler(AppClass):
|
|||||||
preferred_governor: Governor = [gov for gov in _governor_list if gov.name == self._config.default_governor].pop()
|
preferred_governor: Governor = [gov for gov in _governor_list if gov.name == self._config.default_governor].pop()
|
||||||
for trigger in self.running_triggers:
|
for trigger in self.running_triggers:
|
||||||
self.log.debug('trigger %s, state: %s, preferred governor: %s', trigger.name, trigger.trigger_state, trigger.governor.name)
|
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:
|
if trigger.governor.priority < preferred_governor.priority:
|
||||||
preferred_governor = trigger.governor
|
preferred_governor = trigger.governor
|
||||||
self.log.debug('preferred governor: %s', preferred_governor.name)
|
self.log.debug('preferred governor: %s', preferred_governor.name)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import asyncio
|
|||||||
class Trigger(AppClass):
|
class Trigger(AppClass):
|
||||||
def __init__(self, _config: Config) -> None:
|
def __init__(self, _config: Config) -> None:
|
||||||
super().__init__(_config)
|
super().__init__(_config)
|
||||||
self.active: bool = False
|
self._active: bool = False
|
||||||
self.log.setLevel(self.config.loglevel.upper())
|
self.log.setLevel(self.config.loglevel.upper())
|
||||||
self._timestamp_last_statistics = monotonic()
|
self._timestamp_last_statistics = monotonic()
|
||||||
|
|
||||||
@@ -19,18 +19,32 @@ class Trigger(AppClass):
|
|||||||
return super().__hash__(hash(self.name))
|
return super().__hash__(hash(self.name))
|
||||||
|
|
||||||
def log_statistics(self):
|
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():
|
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)):
|
if not isinstance(value, (int, float, Governor)):
|
||||||
value = str(value)
|
value = str(value)
|
||||||
instance_vars[key] = value
|
class_vars[key] = value
|
||||||
self.log.info("info and statistics: %s", instance_vars)
|
self.log.info("info and statistics: %s", class_vars)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def trigger_state(self) -> str:
|
def trigger_state(self) -> str:
|
||||||
return "active" if self.active else "not active"
|
return "active" if self._active else "not active"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class CpuLoadTrigger(Trigger):
|
|||||||
return any(load <= threshold for load, threshold in zip(self.current_load, self.low_threshold))
|
return any(load <= threshold for load, threshold in zip(self.current_load, self.low_threshold))
|
||||||
|
|
||||||
def trigger_code(self) -> None:
|
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_high_load_active = self.current_load_average_over_high_threshold
|
||||||
new_low_load_active = self.current_load_average_over_under_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",
|
"activating trigger, load: %s, high threshold: %s, governor: %s",
|
||||||
self.current_load, self.high_threshold, self.governor.name
|
self.current_load, self.high_threshold, self.governor.name
|
||||||
)
|
)
|
||||||
self.active = True
|
self._active = True
|
||||||
|
|
||||||
elif current_active and new_high_load_active:
|
elif current_active and new_high_load_active:
|
||||||
self.log.debug(
|
self.log.debug(
|
||||||
@@ -77,6 +77,6 @@ class CpuLoadTrigger(Trigger):
|
|||||||
"deactivating trigger, load: %s, low threshold: %s, governor: %s",
|
"deactivating trigger, load: %s, low threshold: %s, governor: %s",
|
||||||
self.current_load, self.low_threshold, self.governor.name
|
self.current_load, self.low_threshold, self.governor.name
|
||||||
)
|
)
|
||||||
self.active = False
|
self._active = False
|
||||||
else:
|
else:
|
||||||
self.log.debug("trigger is already inactive, load: %s, threshold: %s", self.current_load, self.high_threshold)
|
self.log.debug("trigger is already inactive, load: %s, threshold: %s", self.current_load, self.high_threshold)
|
||||||
|
|||||||
@@ -74,14 +74,14 @@ class LogTrigger(Trigger):
|
|||||||
|
|
||||||
def set_active(self) -> None:
|
def set_active(self) -> None:
|
||||||
self.timestamp_last_active_change = datetime.now()
|
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.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:
|
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.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:
|
def _process_line(self, line: str) -> None:
|
||||||
for trigger_string in self.trigger_strings:
|
for trigger_string in self.trigger_strings:
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ class RoonTrigger(Trigger):
|
|||||||
def __init__(self, _config: Config) -> None:
|
def __init__(self, _config: Config) -> None:
|
||||||
super().__init__(_config)
|
super().__init__(_config)
|
||||||
self.set_status()
|
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:
|
def set_status(self) -> None:
|
||||||
zones_state = list()
|
zones_state = list()
|
||||||
|
|
||||||
for zone_id in self.roonapi.zones:
|
for zone_id in self._roonapi.zones:
|
||||||
self.log.debug(self.roonapi.zones[zone_id])
|
self.log.debug(self._roonapi.zones[zone_id])
|
||||||
zone = self.roonapi.zones[zone_id]
|
zone = self._roonapi.zones[zone_id]
|
||||||
self.log.debug("zone_id: %s zone_info: %s" , zone_id, zone)
|
self.log.debug("zone_id: %s zone_info: %s" , zone_id, zone)
|
||||||
zone_name = zone['display_name']
|
zone_name = zone['display_name']
|
||||||
zone_state = zone['state']
|
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)
|
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)
|
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
|
@cached_property
|
||||||
def appinfo(self) -> dict[str, Any]:
|
def appinfo(self) -> dict[str, Any]:
|
||||||
@@ -72,24 +72,24 @@ class RoonTrigger(Trigger):
|
|||||||
return _token
|
return _token
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def discover(self) -> RoonDiscovery:
|
def _discover(self) -> RoonDiscovery:
|
||||||
return RoonDiscovery(self.core_id)
|
return RoonDiscovery(self.core_id)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def server(self) -> RoonServer:
|
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"
|
assert isinstance(_server, tuple) and len(_server) == 2, "failed to discover roon server"
|
||||||
while _server[0] is None:
|
while _server[0] is None:
|
||||||
_server = self.discover.first()
|
_server = self._discover.first()
|
||||||
self.log.warning("roon not ready (yet)")
|
self.log.warning("roon not ready (yet)")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.discover.stop()
|
self._discover.stop()
|
||||||
roon_server = RoonServer(_server[0], _server[1])
|
roon_server = RoonServer(_server[0], _server[1])
|
||||||
self.log.info("found %s", roon_server)
|
self.log.info("found %s", roon_server)
|
||||||
return roon_server
|
return roon_server
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def roonapi(self) -> RoonApi:
|
def _roonapi(self) -> RoonApi:
|
||||||
_roonapi = RoonApi(self.appinfo, self.token, self.server.ip, self.server.port, True)
|
_roonapi = RoonApi(self.appinfo, self.token, self.server.ip, self.server.port, True)
|
||||||
return _roonapi
|
return _roonapi
|
||||||
|
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ class TestTrigger1(Trigger):
|
|||||||
def trigger_code(self) -> None:
|
def trigger_code(self) -> None:
|
||||||
choices = [False, True]
|
choices = [False, True]
|
||||||
self.log.debug("run check code of %s", self.__class__.__name__)
|
self.log.debug("run check code of %s", self.__class__.__name__)
|
||||||
self.active = random.choice(choices)
|
self._active = random.choice(choices)
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ class TimeTrigger(Trigger):
|
|||||||
return datetime.strptime(self.config.custom_config['endTime'], '%H:%M').time()
|
return datetime.strptime(self.config.custom_config['endTime'], '%H:%M').time()
|
||||||
|
|
||||||
def trigger_code(self) -> None:
|
def trigger_code(self) -> None:
|
||||||
active_current = self.active
|
active_current = self._active
|
||||||
active_new = self.start_time() <= datetime.now().time() <= self.end_time()
|
active_new = self.start_time() <= datetime.now().time() <= self.end_time()
|
||||||
if not active_current and active_new:
|
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)
|
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:
|
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.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
|
||||||
|
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "cpu_governor_auto_adjust"
|
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."
|
description = "This application has been developed to automatically change cpu governor based on certain triggers."
|
||||||
authors = [
|
authors = [
|
||||||
{ name = "Martin Reurekas", email = "martin@semrks.nl" }
|
{ name = "Martin Reurekas", email = "martin@semrks.nl" }
|
||||||
|
|||||||
Reference in New Issue
Block a user