起因: 1)板卡上的程序有时需要上报一些消息给上层平台。 2)异常可能来自于程序中许多函数处。如果在调度过程完成,相对因难,例如,超时,就不在主调度流程中。 3)相对简单的办法是在自定义的Exception的子类中(例如JobError)来实现。 4)但这个想法不现实之处在于,无法得到当前的job的ID。如果没有Job ID,自然无法上报。 5)如果改变所有的自定义的Exception,加入job_id这样的变量,有几个困难,一是难以保证都会被赋值,二是会破坏原有的设计,因为原设计认为Exception的扩展,并不属于业务体系,而是公共部分。 5) 仔细分析python的代码后,发现python的logger有handler的功能。该功能可以解决这一系列问题。即种用hook来解决。 示例如下:
import suds
import datetime
import datetime
import logging
from suds.client import Client
wsdl_url = "http://127.0.0.1:9005/?wsdl"
class CcmLoggerHandler(logging.Handler):
def __init__(self, job_id ):
super().__init__()
self.job_id = str(job_id)
self.formatter = logging.Formatter("%(message)s")
def emit(self, record):
msg = str(self.job_id) + (self.formatter.format(record))
if (record.levelno >= 40):
#print("ok")
return
#print(msg)
client = Client(wsdl_url)
result = client.service.add_lava_raise_error2report(self.job_id,msg)
def close(self, linger=-1):
# If the process crashes really early, the handler will be closed
# directly by the logging module. In this case, close is called without
# any arguments.
super().close()
class Job:
"""
Populated by the parser, the Job contains all of the
Actions and their pipelines.
parameters provides the immutable data about this job:
action_timeout
job_name
priority
device_type (mapped to target by scheduler)
logging_level
job_timeout
Job also provides the primary access to the Device.
The NewDevice class only loads the specific configuration of the
device for this job - one job, one device.
"""
def __init__(self, job_id):
self.job_id = job_id
self.logger = logging.getLogger("mydis")
self.logger.addHandler(CcmLoggerHandler(job_id))
def dosomethg(self):
try:
self.logger.info("erery ok.")
b=4/0
except Exception as exc:
self.logger.error("Unable to setup the protocols")
pass
def dos2(self):
try:
b=4/0
except Exception as exc:
self.logger.error("new erroe dos2222")
pass
def main():
job=Job(99)
job.dosomethg()
job.dos2()
return 0
if __name__ == "__main__":
main()
解读:关键有如下几点:
1. 初始化和构造过程。
2.注入hook的过程。
3. 注意log level