使用场景:
监控脚本或某个方法是否正常运行, 若BUG,则报警, 有多种方式,目前我用到钉钉和邮件报警
使用提示:
不建议直接 copy代码使用, 因为这是从我的框架里抠出来的代码, 脱离我的框架不能保证正常运行.
- 为什么会有
if debug:
这样的语句
我配置的环境有生产环境和产品环境两个, 生产环境下debug=Ture
, 产品环境下debug=False
,所有报警只在产品环境下起作用., 你肯定不想一边调试代码一边在群里被疯狂@
邮件报警:
可以将这个方法做为装饰器使用会非常方便:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# @File : mailsender.py
# @Time : 2019/09/26 14:44:50
# @Author : liuzhanghong
# @Contact : liuzhanghong@bj-cib.com
# @Version : 2.0
# @Desc : 发邮件的组件, 已封装CIBsender, 可以登录后直接使用.
import os, sys
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.header import Header
from email import encoders
import traceback
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class MailSender(object):
"""
发邮件, 支持中文名字的附件目录
"""
def __init__(self, smtpSvr, port, user, pwd, is_ssl=False):
"""
初始化
smtp: string SMTP服务器地址
port: int SMTP端口号
user: string 发件人邮箱地址
pwd: string 发件人邮箱密码
"""
print('SMTP server init...')
if not is_ssl:
self.smtp = smtplib.SMTP()
else:
self.smtp = smtplib.SMTP_SSL()
self.smtp.connect(smtpSvr, port)
self._from = user
print('loging...')
self.smtp.login(user, pwd)
print('logined, get ready data...')
def send(self, subject, content, to_addrs, cc_addrs=None, attachs=None):
"""
发送邮件
subject: string 邮件标题
content: string 邮件正文
to_addrs: [] 收件人列表
cc_addrs: [] 抄送人列表
attachs: [] 附件的绝对路径列表
"""
if cc_addrs is None:
cc_addrs = []
if attachs is None:
attachs = []
to_addrs.extend(cc_addrs)
msg = MIMEMultipart('alternative')
contents = MIMEText(content, "html", _charset='utf-8')
msg.attach(contents)
msg['Subject'] = subject
msg['From'] = self._from
msg['Cc'] = Header(','.join(cc_addrs))
msg['To'] = Header(','.join(to_addrs))
for file in attachs:
basename = os.path.basename(file)
att = MIMEText(open(file, 'rb').read(), 'base64', 'utf-8')
att["Content-Type"] = 'application/octet-stream'
att.add_header('Content-Disposition', 'attachment', filename=('gbk', '', basename))
# encoders.encode_base64(att) # 去掉注释后,中文内容会显示乱码
msg.attach(att)
try:
self.smtp.sendmail(self._from, to_addrs, msg.as_string())
logger.info(f'{subject} send sucess')
except Exception as e:
traceback.print_exc()
logger.info(f'{subject} send fail')
def close(self):
self.smtp.quit()
class Sender(MailSender):
"""可以定制为公司专用发邮件组件,这里已经封装腾讯企业邮配置, 但需要登录自己的邮箱"""
def __init__(self, user='test@test.com', pwd='test', smtpSvr='smtp.exmail.qq.com', port=465, is_ssl=True):
"""
user: string 发件人邮箱地址
pwd: string 发件人邮箱密码
"""
if not is_ssl:
self.smtp = smtplib.SMTP()
else:
self.smtp = smtplib.SMTP_SSL()
self.smtp.connect(smtpSvr, port)
self._from = user
self.smtp.ehlo()
self.smtp.login(user, pwd)
def __str__(self):
return '已封装腾讯企业邮 需要用户名和密码进行登录初始化...'
if __name__ == "__main__":
Sender().send('this is a test subject', 'content for test', ['liuzhanghong@bj-cib.com'])
import mail
mail = mail.Sendmail(from_email='myemail@example.com', from_email_pwd='pwd')
def debug_timeit(code_path):
"""
该装饰器主要功能用捕捉异常后发送报警邮件:
code_path 为代码路径,用于报错时,提示文件的位置
"""
def _deco(func):
def wrapper(*args, **kw):
try:
startTime = int(round(time.time() * 1000))
result = func(*args, **kw)
endTime = int(round(time.time() * 1000))
seconds = (endTime - startTime)/1000
print('start_time:{} end_time: {}, cost: {}'.format(startTime,endTime,seconds))
except Exception as e:
if debug:
print('DEBUG = True,正在调试代码,不需发DEBUG邮件')
else:
print('DEBUG = False, 若报错,将收到报错邮件')
error_text = '<p>' + traceback.format_exc() + '</p>'
mail.sendmail(title='错误! 代码文件为:{}'.format(code_path), content=error_text,
to_emails=['test@163.com'])
return result
return wrapper
return _deco
# 具体的使用方法如下:
@ debug_timeit(code_path=__file__)
def test_debug(test):
return int(test)
钉钉报警
import requests
import traceback
def dingding(at_mobiles, content, group_name='dingding_group'):
"""
目前钉钉通知仅支持将报警消息发到钉钉群里, 不能钉钉到个人,
请将你的钉钉群的token 更新到tokens里.
"""
try:
tokens = {
'dingding_group': 'group_token'
}
access_token = tokens.get(group_name, tokens['dingding_group'])
dd_api = f'https://oapi.dingtalk.com/robot/send?access_token={access_token}'
dd_json = {
"msgtype": "text",
"text": {
"content": content
},
"at": {
"atMobiles": at_mobiles,
"isAtAll": False
}
}
requests.post(dd_api, json=dd_json)
except Exception as e:
traceback.print_exc()
def debug_ding(at_mobiles, content, group_name='dingding_group'):
"""
正式例行化时使用
该装饰器主要功能用捕捉异常后发送到钉钉群里:
"""
def _deco(func):
def wrapper(*args, **kw):
try:
startTime = int(round(time.time() * 1000))
result = func(*args, **kw)
endTime = int(round(time.time() * 1000))
seconds = (endTime - startTime)/1000
print('start_time:{} end_time: {}, cost: {}'.format(startTime, endTime, seconds))
except Exception as e:
if debug:
print('DEBUG = True,正在调试代码,不需发dingding')
else:
print('DEBUG = False,请注意查收dingding通知')
dingding(at_mobiles=at_mobiles, content=content, group_name=group_name )
return result
return wrapper
return _deco
# 具体的使用方法如下:
@ debug_ding(['18111181112', '18711171117'], '这里有BUG了, 快来看看呀', 'dingding_group')
def test_debug(test):
return int(test)
我知道微信也是OK的. 只是我工作中钉钉比较多.😃
欢迎沟通指正
end