Package park :: Package core :: Module monitor

Source Code for Module park.core.monitor

  1  # This program is public domain 
  2  """ 
  3  Asychronous execution monitoring service. 
  4   
  5  Long running computations need to convey status information to the user. 
  6  This status can take multiple forms, such as output to the console or 
  7  activity on a GUI, or even mail to your inbox. 
  8   
  9  `park.core.message` defines several standard messages:: 
 10   
 11      `Started` for job start 
 12      `Joined` first message when joining an already running job 
 13      `Progress` for job activity 
 14      `Improved` for partial results 
 15      `Completed` for final result 
 16      `Aborted` when job is killed 
 17      `Error` when job has an error 
 18      `Log` for various debugging messages 
 19   
 20  The `Monitor` class handles the stream of messages, dispatching each 
 21  to a user defined handler.  For each message, Monitor.put(message) 
 22  will look for the method named onMonitorName where Name is the name 
 23  of the message class.  For example,  onMonitorStarted(self, message) 
 24  will be called in response to the Started message.  If onMonitorName 
 25  is not defined, then onMonitorMessage will be called.  The default 
 26  behaviour of onMonitorMessage is to print the message on the console. 
 27   
 28  Individual services may have specialized message types.  Such services 
 29  may also provide a specialized Monitor subclass to handle these 
 30  messages. 
 31   
 32  Log messages are sent to the standard system logger using onMonitorLog. 
 33  See logging in the python standard library for details on controlling 
 34  the logger. 
 35   
 36  `park.core.wxmonitor.Monitor` is a predefined monitor which 
 37  dispatches events to a wx GUI. 
 38  """ 
 39  __all__ = ['Monitor'] 
 40   
 41  import sys 
 42  import logging 
43 44 -class Monitor(object):
45 """ 46 Messages that are received during the processing of the job. 47 48 Standard message types:: 49 50 `Started`, `Progress`, `Improved`, `Completed`, 51 `Error`, `Aborted`, `Log` 52 53 Specific job types may have their own monitor messages. 54 55 The messages themselves should all produce nicely formatted results 56 in response to str(message). 57 58 The message dispatch calls on<Class>(message) if the on<Class> 59 method exists for the message type. If not, then dispatch 60 calls otherwise(message). By default onLog(message) submits the 61 log record to the logger. 62 63 Subclass Monitor to define your own behaviours. 64 """
65 - def put(self, message):
66 """ 67 Called from thread when new message has arrived. 68 """ 69 method = "onMonitor"+message.__class__.__name__ 70 fn = getattr(self, method, self.onMonitorMessage) 71 fn(message)
72
73 - def onMonitorMessage(self, message):
74 """ 75 What to do if the message handler is not found. 76 77 Default is to ignore the message. 78 """ 79 print ">",str(message)
80
81 - def onMonitorLog(self, message):
82 """ 83 Called when the job sends a logging record. 84 85 The logging record contains a normal python logging record. 86 87 The default behaviour is to tie into the application logging 88 system using:: 89 90 logger = logging.getLogger(message.record.name) 91 logger.handle(message.record) 92 93 Logging levels are set in the job controller. 94 """ 95 logging.basicConfig() 96 logger = logging.getLogger(message.record.name) 97 logger.handle(message.record)
98 99 # === Demonstration and test code === 100 101 from park.util.threads import threaded
102 @threaded 103 -def _demo_stream(rate=0, monitor=None):
104 import sys, time 105 import park.core.message as msg 106 107 def messagestream(monitor,rate,stream): 108 for m in stream: 109 time.sleep(rate) 110 monitor.put(m) 111 time.sleep(rate)
112 R = logging.LogRecord('hi',60,'hello.py',3,'log message',(),None,'here') 113 try: raise Exception('Test exception') 114 except: trace = sys.exc_info() 115 stream=[msg.Started(), 116 msg.Improved(status='Good'), 117 msg.Progress(1,10), 118 msg.Progress(2,10), 119 msg.Progress(3,10), 120 msg.Joined(progress=(3,10),improved='Good'), 121 msg.Improved(status='Better!'), 122 msg.Aborted(), 123 msg.Started(), 124 msg.Progress(1,10,'seconds'), 125 msg.Improved(status='Better!'), 126 msg.Progress(8,10), 127 msg.Completed(status='Best!'), 128 msg.Started(), 129 msg.Log(R), 130 msg.Progress(6,10), 131 msg.Error(trace), 132 msg.Completed(status='Bye!')] 133 messagestream(monitor,rate,stream) 134
135 -def demo(rate=0):
136 import park.core.monitor 137 _demo_stream(rate=rate, monitor=park.core.monitor.Monitor())
138
139 -def test():
140 class TestMonitor(Monitor): 141 def __init__(self): self.id = 0 142 def onMonitorStarted(self, msg): 143 assert self.id in [0,8,13] 144 self.id+=1
145 def onMonitorImproved(self, msg): 146 assert self.id in [1,6,10] 147 self.id+=1 148 def onMonitorProgress(self, msg): 149 assert self.id in [2,3,4,9,11,15] 150 self.id+=1 151 #def onMonitorJoined(self, msg): 152 # assert self.id in [5] 153 # self.id += 1 154 def onMonitorAborted(self, msg): 155 assert self.id in [7] 156 self.id += 1 157 def onMonitorCompleted(self, msg): 158 assert self.id in [12] 159 self.id += 1 160 def onMonitorLog(self, msg): 161 assert self.id in [14] 162 self.id += 1 163 def onMonitorError(self, msg): 164 assert self.id in [16] 165 self.id += 1 166 def onMonitorMessage(self, msg): 167 # Uncaught messages should be 'Joined'; everything else in stream 168 # is caught. 169 assert msg.__class__.__name__ == 'Joined' 170 assert self.id in [5] 171 self.id += 1 172 _demo_stream(rate=0, monitor=TestMonitor()) 173 174 if __name__ == "__main__": 175 #demo(rate=0.1) 176 test() 177