您的位置:首页 > 编程语言 > Python开发

[Python--] Python logging模块实现邮件报警

2015-04-24 10:20 459 查看
需求定义:

job运行中如果有失败,发送邮件到指定邮箱用于报警

 

由于没有相关方面的经验,在思考如何发送报警经过了如下几个过程:

【思路一】首先想到的是根据spark job的运行状态来确定是否发送报警邮件,那么只要我们能获取到spark运行出错时候的返回值,就可以通过smtplib模块进行邮件发送。所以思路一的关键点在于运行状态的获取。再查找资料后发现,spark-1.1.0版本未提供像1.3.0版本那样可以返回TaskId和TaskState的接口(或许存在可以获取的方法,但我没有找到,如果哪位大侠知道,烦请告知一下),而暂时我们还没有需要要升级spark版本,考量之后,放弃;

【思路二】因为job执行的时候会打log,于是想到日志的关键字扫描。如果发现日志里面存在‘error’,则发送报警邮件,告知job运行失败;这个存在问题就是,每天的日志文件有很多, 这种方法势必要花费大量的时间来读取文件。如果能够在写日志的同时发送报警就好了,于是有了思路三;

【思路三】最开始想到的是改写logger.error()或者是获取record的level等级。在查找资料的过程中发现了logging.handlers.SMTPHandler(再次感叹一下Python模块的强大性)可以直接实现远程输入日志到邮件地址,通过简单的配置就可以使用,不必自己再烦心重写。

handler = logging.handlers.SMTPHandler(mail_host,mail_from,mail_to,'%s__JOB FAILED Attention__' % date.today())

handler.setLevel(logging.ERROR)

handler.setFormatter(logging.Formatter(format))

logger.addHandler(handler)


【思路四】思路三又有什么问题呢?每一条错误日志都会对应一封邮件的发送,如果多条错误,邮箱且不是要爆掉。这当然不是我们所希望的结果。恩,不要忘掉强大的Python模块。logging.handlers.MemoryHandler是将日志输出的内存中定制的buffer,一旦buffer存满或是超过设定的级别就会将日志记录发送给指定的target handler处理。/usr/lib/python2.6/logging/handlers.py中可以查看MemoryHandler的源代码(通过help(logging))。

def flush(self):
"""
For a MemoryHandler, flushing means just sending the buffered
records to the target, if there is one. Override if you want
different behaviour.
"""
if self.target:
for record in self.buffer:
self.target.handle(record)
self.buffer = []


从代码中可以看出,虽然我们暂时缓存了多条日志数据,但是当缓存溢出时,对应buffer中的每一条记录,都对应一个动作,即,如果我们设置target为SMTPHandler,还是会发送多个邮件。So, override if you want different behaviour。

class OptmizedMemoryHandler(logging.handlers.MemoryHandler):
def __init__(self, capacity, mail_subject, mail_host, mail_from, mail_to):
""" capacity: flush memory
mail_subject: warning mail subject
mail_host: the email host used
mail_from: address send from; str
mail_to: address send to; multi-addresses splitted by ';'

"""
logging.handlers.MemoryHandler.__init__(self, capacity, flushLevel = logging.ERROR,\
target = None)
self.mail_subject = mail_subject
self.mail_host = mail_host
self.mail_from = mail_from
self.mail_to = mail_to

def flush(self):
"""if flushed send mail
"""
if self.buffer != [] and len(self.buffer) >= self.capacity:
content = ''
for record in self.buffer:
message = record.getMessage()
content += record.levelname + " occurred at " + time.strftime('%Y-%m-%d %H:%M:%S',time.localti    me(record.created)) + "  : " + message + '\n'
self.send_warning_mail(self.mail_subject, content,self.mail_host, self.mail_from, self.mail_to)
self.buffer = []

def send_warning_mail(self, subject, content, host, from_addr, to_addr):
"""send mail
"""
msg = MIMEText(content)
msg['Subject'] = subject
try:
smtp = smtplib.SMTP()
smtp.connect(host)
smtp.sendmail(from_addr, to_addr, msg.as_string())
smtp.close()
except:
print traceback.format_exc()

http://www.red-dove.com/python_logging.html   有很多logging的介绍和示例,可供参考
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python logging smtp