Open labbenchstudios opened 4 years ago
Hi, This line of code:
self.scheduler.add_job( 'self.handleTelemetry', 'interval', seconds = pollRate)
output the following error:
Finding files... done.
Importing test modules ... done.
2021-12-06 16:09:01,256:SystemPerformanceManagerTest:INFO:Testing SystemPerformanceManager class...
2021-12-06 16:09:01,256:ConfigUtil:INFO:Loading config: ../../../../../../../config/PiotConfig.props
2021-12-06 16:09:01,256:ConfigUtil:DEBUG:Config: ['Mqtt.GatewayService', 'Coap.GatewayService', 'ConstrainedDevice']
2021-12-06 16:09:01,257:ConfigUtil:INFO:Created instance of ConfigUtil: <programmingtheiot.common.ConfigUtil.ConfigUtil object at 0x7fb64dc6a3a0>
======================================================================
ERROR: setUpClass (src.test.python.programmingtheiot.part01.integration.system.SystemPerformanceManagerTest.SystemPerformanceManagerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/mas/programmingtheiot/python-components/src/test/python/programmingtheiot/part01/integration/system/SystemPerformanceManagerTest.py", line 43, in setUpClass
self.spMgr = SystemPerformanceManager()
File "/home/mas/programmingtheiot/python-components/src/main/python/programmingtheiot/cda/system/SystemPerformanceManager.py", line 46, in __init__
self.scheduler.add_job( 'self.handleTelemetry', 'interval', seconds = pollRate)
NameError: name 'pollRate' is not defined
----------------------------------------------------------------------
Ran 0 tests in 0.007s
FAILED (errors=1)
Trying:
self.scheduler.add_job( 'self.handleTelemetry', 'interval', seconds = self.pollRate)
Output the following error:
Finding files... done.
Importing test modules ... done.
2021-12-06 16:09:48,579:SystemPerformanceManagerTest:INFO:Testing SystemPerformanceManager class...
2021-12-06 16:09:48,580:ConfigUtil:INFO:Loading config: ../../../../../../../config/PiotConfig.props
2021-12-06 16:09:48,580:ConfigUtil:DEBUG:Config: ['Mqtt.GatewayService', 'Coap.GatewayService', 'ConstrainedDevice']
2021-12-06 16:09:48,580:ConfigUtil:INFO:Created instance of ConfigUtil: <programmingtheiot.common.ConfigUtil.ConfigUtil object at 0x7fa719ed53a0>
/usr/local/lib/python3.8/dist-packages/apscheduler/util.py:95: PytzUsageWarning: The zone attribute is specific to pytz's interface; please migrate to a new time zone provider. For more details on how to do so, see https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html
if obj.zone == 'local':
======================================================================
ERROR: setUpClass (src.test.python.programmingtheiot.part01.integration.system.SystemPerformanceManagerTest.SystemPerformanceManagerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/mas/programmingtheiot/python-components/src/test/python/programmingtheiot/part01/integration/system/SystemPerformanceManagerTest.py", line 43, in setUpClass
self.spMgr = SystemPerformanceManager()
File "/home/mas/programmingtheiot/python-components/src/main/python/programmingtheiot/cda/system/SystemPerformanceManager.py", line 46, in __init__
self.scheduler.add_job( 'self.handleTelemetry', 'interval', seconds = self.pollRate)
File "/usr/local/lib/python3.8/dist-packages/apscheduler/schedulers/base.py", line 439, in add_job
job = Job(self, **job_kwargs)
File "/usr/local/lib/python3.8/dist-packages/apscheduler/job.py", line 49, in __init__
self._modify(id=id or uuid4().hex, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/apscheduler/job.py", line 162, in _modify
func = ref_to_obj(func)
File "/usr/local/lib/python3.8/dist-packages/apscheduler/util.py", line 300, in ref_to_obj
raise ValueError('Invalid reference')
ValueError: Invalid reference
----------------------------------------------------------------------
Ran 0 tests in 0.039s
FAILED (errors=1)
Any thought?
Best, Mohammad Abu Shattal
Full code of SystemPerformanceManager:
#####
#
# This class is part of the Programming the Internet of Things project.
#
# It is provided as a simple shell to guide the student and assist with
# implementation for the Programming the Internet of Things exercises,
# and designed to be modified by the student as needed.
#
import logging
from apscheduler.schedulers.background import BackgroundScheduler
import programmingtheiot.common.ConfigConst as ConfigConst
from programmingtheiot.common.ConfigUtil import ConfigUtil
from programmingtheiot.common.IDataMessageListener import IDataMessageListener
from programmingtheiot.cda.system.SystemCpuUtilTask import SystemCpuUtilTask
from programmingtheiot.cda.system.SystemMemUtilTask import SystemMemUtilTask
from programmingtheiot.data.SystemPerformanceData import SystemPerformanceData
class SystemPerformanceManager(object):
"""
Shell representation of class for student implementation.
"""
def __init__(self):
self.configUtil = ConfigUtil()
self.pollRate = self.configUtil.getInteger(
section = ConfigConst.CONSTRAINED_DEVICE,
key = ConfigConst.POLL_CYCLES_KEY,
defaultVal = ConfigConst.DEFAULT_POLL_CYCLES)
self.locationID = self.configUtil.getProperty(
section = ConfigConst.CONSTRAINED_DEVICE,
key = ConfigConst.DEVICE_LOCATION_ID_KEY,
defaultVal = ConfigConst.CONSTRAINED_DEVICE)
if self.pollRate <= 0:
self.pollRate = ConfigConst.DEFAULT_POLL_CYCLES
self.scheduler = BackgroundScheduler()
self.scheduler.add_job( 'self.handleTelemetry', 'interval', seconds = self.pollRate)
self.dataMsgListener = None
def handleTelemetry(self):
self.cpuUtilTask = SystemCpuUtilTask()
self.memUtilTask = SystemMemUtilTask()
logging.debug('CPU utilization is %s percent, and memory utilization is %s percent.', str(self.cpuUtilPct), str(self.memUtilPct))
def setDataMessageListener(self, listener: IDataMessageListener) -> bool:
pass
def startManager(self):
logging.info("Started SystemPerformanceManager")
if not self.scheduler.running:
self.scheduler.start()
else:
logging.warning( "SystemPerformanceManager scheduler already started. Ignoring.")
def stopManager(self):
logging.info("Stopped SystemPerformanceManager")
try:
self.scheduler.shutdown()
except:
logging.warning( "SystemPerformanceManager scheduler already stopped. Ignoring.")
Hi - thanks for pointing this out and for your question. Two things:
Hope this helps!
Thank you for your quick help! That helped but I needed to update the code to include definitions for cpuUtilPct and memUtilPct to be members of the SystemPerformanceManager Class. Below is the full code of SystemPerformance that worked correctly:
#####
#
# This class is part of the Programming the Internet of Things project.
#
# It is provided as a simple shell to guide the student and assist with
# implementation for the Programming the Internet of Things exercises,
# and designed to be modified by the student as needed.
#
import logging
from apscheduler.schedulers.background import BackgroundScheduler
import programmingtheiot.common.ConfigConst as ConfigConst
from programmingtheiot.common.ConfigUtil import ConfigUtil
from programmingtheiot.common.IDataMessageListener import IDataMessageListener
from programmingtheiot.cda.system.SystemCpuUtilTask import SystemCpuUtilTask
from programmingtheiot.cda.system.SystemMemUtilTask import SystemMemUtilTask
from programmingtheiot.data.SystemPerformanceData import SystemPerformanceData
class SystemPerformanceManager(object):
"""
Shell representation of class for student implementation.
"""
def __init__(self):
self.configUtil = ConfigUtil()
self.pollRate = self.configUtil.getInteger(
section = ConfigConst.CONSTRAINED_DEVICE,
key = ConfigConst.POLL_CYCLES_KEY,
defaultVal = ConfigConst.DEFAULT_POLL_CYCLES)
self.locationID = self.configUtil.getProperty(
section = ConfigConst.CONSTRAINED_DEVICE,
key = ConfigConst.DEVICE_LOCATION_ID_KEY,
defaultVal = ConfigConst.CONSTRAINED_DEVICE)
if self.pollRate <= 0:
self.pollRate = ConfigConst.DEFAULT_POLL_CYCLES
self.scheduler = BackgroundScheduler()
self.scheduler.add_job( self.handleTelemetry, 'interval', seconds = self.pollRate)
self.cpuUtilTask = SystemCpuUtilTask()
self.memUtilTask = SystemMemUtilTask()
self.cpuUtilPct = self.cpuUtilTask.getTelemetryValue()
self.memUtilPct = self.memUtilTask.getTelemetryValue()
self.dataMsgListener = None
def handleTelemetry(self):
cpuUtilPct = self.cpuUtilTask.getTelemetryValue()
memUtilPct = self.memUtilTask.getTelemetryValue()
logging.debug('CPU utilization is %s percent, and memory utilization is %s percent.', str(self.cpuUtilPct), str(self.memUtilPct))
def setDataMessageListener(self, listener: IDataMessageListener) -> bool:
pass
def startManager(self):
logging.info("Started SystemPerformanceManager")
if not self.scheduler.running:
self.scheduler.start()
else:
logging.warning( "SystemPerformanceManager scheduler already started. Ignoring.")
def stopManager(self):
logging.info("Stopped SystemPerformanceManager")
try:
self.scheduler.shutdown()
except:
logging.warning( "SystemPerformanceManager scheduler already stopped. Ignoring.")
Below are the results that I have for this code. I see the results are the same during one run (multiple iterations over time. e.g.: 85.7 in this run). When I run the code it gives a new value (e.g. 98.2 )but it is repeated during the same run.
Finding files... done.
Importing test modules ... done.
2021-12-07 12:23:10,371:SystemPerformanceManagerTest:INFO:Testing SystemPerformanceManager class...
2021-12-07 12:23:10,371:ConfigUtil:INFO:Loading config: ../../../../../../../config/PiotConfig.props
2021-12-07 12:23:10,372:ConfigUtil:DEBUG:Config: ['Mqtt.GatewayService', 'Coap.GatewayService', 'ConstrainedDevice']
2021-12-07 12:23:10,372:ConfigUtil:INFO:Created instance of ConfigUtil: <programmingtheiot.common.ConfigUtil.ConfigUtil object at 0x7fa2c5dce3a0>
/usr/local/lib/python3.8/dist-packages/apscheduler/util.py:95: PytzUsageWarning: The zone attribute is specific to pytz's interface; please migrate to a new time zone provider. For more details on how to do so, see https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html
if obj.zone == 'local':
2021-12-07 12:23:10,414:base:INFO:Adding job tentatively -- it will be properly scheduled when the scheduler starts
2021-12-07 12:23:10,414:SystemPerformanceManager:INFO:Started SystemPerformanceManager
/usr/local/lib/python3.8/dist-packages/apscheduler/triggers/interval.py:66: PytzUsageWarning: The normalize method is no longer necessary, as this time zone supports the fold attribute (PEP 495). For more details on migrating to a PEP 495-compliant implementation, see https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html
return self.timezone.normalize(next_fire_time)
2021-12-07 12:23:10,419:base:INFO:Added job "SystemPerformanceManager.handleTelemetry" to job store "default"
2021-12-07 12:23:10,419:base:INFO:Scheduler started
2021-12-07 12:23:10,419:base:DEBUG:Looking for jobs to run
2021-12-07 12:23:10,419:base:DEBUG:Next wakeup is due at 2021-12-07 12:23:15.413896-05:00 (in 4.993956 seconds)
2021-12-07 12:23:15,414:base:DEBUG:Looking for jobs to run
2021-12-07 12:23:15,414:base:INFO:Running job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], next run at: 2021-12-07 12:23:15 EST)" (scheduled at 2021-12-07 12:23:15.413896-05:00)
2021-12-07 12:23:15,415:base:DEBUG:Next wakeup is due at 2021-12-07 12:23:20.413896-05:00 (in 4.999609 seconds)
2021-12-07 12:23:15,415:SystemPerformanceManager:DEBUG:CPU utilization is 85.7 percent, and memory utilization is None percent.
2021-12-07 12:23:15,415:base:INFO:Job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], next run at: 2021-12-07 12:23:20 EST)" executed successfully
2021-12-07 12:23:20,414:base:DEBUG:Looking for jobs to run
2021-12-07 12:23:20,415:base:DEBUG:Next wakeup is due at 2021-12-07 12:23:25.413896-05:00 (in 4.998919 seconds)
2021-12-07 12:23:20,415:base:INFO:Running job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], next run at: 2021-12-07 12:23:25 EST)" (scheduled at 2021-12-07 12:23:20.413896-05:00)
2021-12-07 12:23:20,415:SystemPerformanceManager:DEBUG:CPU utilization is 85.7 percent, and memory utilization is None percent.
2021-12-07 12:23:20,415:base:INFO:Job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], next run at: 2021-12-07 12:23:25 EST)" executed successfully
2021-12-07 12:23:25,414:base:DEBUG:Looking for jobs to run
2021-12-07 12:23:25,414:base:DEBUG:Next wakeup is due at 2021-12-07 12:23:30.413896-05:00 (in 4.999570 seconds)
2021-12-07 12:23:25,414:base:INFO:Running job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], next run at: 2021-12-07 12:23:30 EST)" (scheduled at 2021-12-07 12:23:25.413896-05:00)
2021-12-07 12:23:25,414:SystemPerformanceManager:DEBUG:CPU utilization is 85.7 percent, and memory utilization is None percent.
2021-12-07 12:23:25,414:base:INFO:Job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], next run at: 2021-12-07 12:23:30 EST)" executed successfully
2021-12-07 12:23:30,414:base:DEBUG:Looking for jobs to run
2021-12-07 12:23:30,414:base:DEBUG:Next wakeup is due at 2021-12-07 12:23:35.413896-05:00 (in 4.999605 seconds)
2021-12-07 12:23:30,414:base:INFO:Running job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], next run at: 2021-12-07 12:23:35 EST)" (scheduled at 2021-12-07 12:23:30.413896-05:00)
2021-12-07 12:23:30,414:SystemPerformanceManager:DEBUG:CPU utilization is 85.7 percent, and memory utilization is None percent.
2021-12-07 12:23:30,414:base:INFO:Job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], next run at: 2021-12-07 12:23:35 EST)" executed successfully
Glad to hear the fixes mentioned resolved the initial issue. Here are some thoughts on your follow-up question:
generateTelemetry()
function should be the only place you need to invoke the getTelemetryValue()
function on each task instance, as it will be invoked during each poll cycle from the scheduler.cpuUtilPct
to store the value from the task in handleTelemetry()
, be sure to use the same reference in any logging you may want to include. The example shows a class-scoped self.cpuUtilPct
- if you go with that approach, use self.cpuUtilPct
to retrieve the value.Hope this helps!
Description
SystemCpuUtilTask
andSystemMemUtilTask
withinSystemPerformanceManager
and use theapscheduler
library to run each task at a regular interval.Review the README
Estimated effort may vary greatly
Actions
NOTE: The implementation examples depicted here are only one way to implement the requirements listed. Your own implementation may vary of course.
Update the constructor as follows:
add_job()
method requires a function pointer to thehandleTelemetry()
method, which is already stubbed out.add_job()
- you may want to consider using additional parameters, such ascoalesce
andmisfire_grace_time
if you run into thread call delays or failures. See apscheduler v3.x - add_job() docs for further info. Here's one notional example for review purposes:Create a public method named
handleTelemetry()
and add the following lines of code:cpuUtilPct
andmemUtilPct
as class-scoped. Since these variables are only needed within thehandleTelemetry()
method, they can be locally scoped to the method.logging.debug('CPU utilization is %s percent, and memory utilization is %s percent.', str(cpuUtilPct), str(memUtilPct))
Implement the
startManager()
andstopManager()
methods:if not self.scheduler.running: self.scheduler.start() logging.info("Started SystemPerformanceManager.") else: logging.warning("SystemPerformanceManager scheduler already started. Ignoring.")
def stopManager(self): logging.info("Stopping SystemPerformanceManager...")
Finding files... done. Importing test modules ... done.
2020-09-05 22:47:52,609:SystemPerformanceManagerTest:INFO:Testing SystemPerformanceManager class... 2020-09-05 22:47:52,761:base:INFO:Adding job tentatively -- it will be properly scheduled when the scheduler starts 2020-09-05 22:47:52,762:SystemPerformanceManager:INFO:Started SystemPerformanceManager. 2020-09-05 22:47:52,763:base:INFO:Added job "SystemPerformanceManager.handleTelemetry" to job store "default" 2020-09-05 22:47:52,763:base:INFO:Scheduler started 2020-09-05 22:47:52,764:base:DEBUG:Looking for jobs to run 2020-09-05 22:47:52,764:base:DEBUG:Next wakeup is due at 2020-09-05 22:47:57.761111-04:00 (in 4.997008 seconds) 2020-09-05 22:47:57,762:base:DEBUG:Looking for jobs to run 2020-09-05 22:47:57,763:base:INFO:Running job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], nex t run at: 2020-09-05 22:47:57 EDT)" (scheduled at 2020-09-05 22:47:57.761111-04:00) 2020-09-05 22:47:57,763:SystemPerformanceManager:DEBUG:CPU utilization is 10.0 percent, and memory utilization is 64.1 pe rcent. . . . 2020-09-05 22:48:52,762:base:INFO:Job "SystemPerformanceManager.handleTelemetry (trigger: interval[0:00:05], next run at : 2020-09-05 22:48:57 EDT)" executed successfully 2020-09-05 22:48:52,764:SystemPerformanceManager:INFO:Stopped SystemPerformanceManager. 2020-09-05 22:48:52,764:base:INFO:Scheduler has been shut down 2020-09-05 22:48:52,764:base:DEBUG:Looking for jobs to run 2020-09-05 22:48:52,765:base:DEBUG:No jobs; waiting until a job is added
Ran 1 test in 60.156s
OK