Grafana是一套开源的监控图表显示框架,可以很方便地和监控框架结合来显示精美的监控图,比如常见的基于Zabbix监控来显示图表。但是grafana本身只能通过一定的监控指标触发告警通知,不支持定期发送日报。
见网上大神使用Grafana reporter实现了日报功能,实力有限没有完成搭建。
参考https://www.jianshu.com/p/03cf0fc9c746实现了以下日报发送。
# -*- coding: UTF-8 -*-
import os
import time
import datetime
import threading
import urllib2
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.utils import parseaddr, formataddr
import logging
print "timer is started!!!!!"
#本地路径
#file_path = "/mnt/c/Users/admin/Desktop/"
#log_path = "/mnt/c/Users/admin/Desktop/timer.log"
#容器内文件路径,注意结尾必须为斜线
file_path = "/mnt/deployer/monitor/imgs/"
log_path = file_path + "../timer.log"
print "log_path=" + log_path
##################################################
#汇报时间
alert_time = "09:00:00"
##################################################
##################################################
to_address = ['abc@163.com',
# '1234@163.com'] # 如果想发给多人,可以放入一个数组
cc_reciver = [edg@11.com'] ##['xxxxxxxx@qq.com', 'xxxxxxxx@qq.com'] # 如果想添加抄送人,也可以是单人或者数组的形式
#################################################
#logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',level=logging.DEBUG )
##打印日志到控制台
logging.basicConfig(level=logging.DEBUG ,#控制台打印的日志级别
filename=log_path,
filemode='a',##模式,有w和a,w就是写模式,每次都会重新写日志,覆盖之前的日志
#a是追加模式,默认如果不写的话,就是追加模式
format=
'%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
#日志格式
)
logging.info( '图片存放路径为:' + file_path )
logging.info( '日志存放文件为:' + log_path )
to_addr=''
cc_reciv=''
for to_add in range(len(to_address)):
to_addr = to_addr + to_address[to_add] + ";"
for cc_rec in range(len(cc_reciver)):
cc_reciv = cc_reciv + cc_reciver[cc_rec] + ";"
logging.info( "收件人:" + to_addr)
logging.info( "抄送地址:" + cc_reciv)
logging.info( "汇报时间:" + alert_time)
img_urls = [
["cluster_vcore_persent","http://127.0.0.1:3000/render/d-solo/J0mqLSlWk/neng-li-kai-fang-ji-qun-zong-lan-copybywyg?orgId=1&panelId=92&width=1000&height=500&tz=Asia%2FShanghai",""],
##集群vcore
["queue_mem_persent","http://127.0.0.1:3000/render/d-solo/J0mqLSlWk/neng-li-kai-fang-ji-qun-zong-lan-copybywyg?orgId=1&panelId=56&width=1000&height=500&tz=Asia%2FShanghai",""],
##各个队列内存绝对使用百分比
["cluster_stor_persent","http://127.0.0.1:3000/render/d-solo/J0mqLSlWk/neng-li-kai-fang-ji-qun-zong-lan-copybywyg?orgId=1&panelId=98&width=1000&height=500&tz=Asia%2FShanghai",""],
##集群存储使用情况总览
["tenant_hdfs_persent","http://127.0.0.1:3000/render/d-solo/J0mqLSlWk/neng-li-kai-fang-ji-qun-zong-lan-copybywyg?orgId=1&panelId=50&width=1000&height=500&tz=Asia%2FShanghai",""],
##各租户HDFS文件数
["cluster_rpc_persent","http://127.0.0.1:3000/render/d-solo/J0mqLSlWk/neng-li-kai-fang-ji-qun-zong-lan-copybywyg?orgId=1&panelId=34&width=1000&height=500&tz=Asia%2FShanghai",""],
#集群RPC队列和处理时间#
["cluster_io_persent","http://127.0.0.1:3000/render/d-solo/J0mqLSlWk/neng-li-kai-fang-ji-qun-zong-lan-copybywyg?orgId=1&panelId=18&width=1000&height=500&tz=Asia%2FShanghai",""]
##集群网络IO
]
F_stamp = int(round(time.time()*1000))
F_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()))
S_stamp = F_stamp - 7 * 24 * 3600*1000
S_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()- 7 * 24 * 3600))
def do_job():
print time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
logging.info( '>>>>>>>>>>>>>时间到啦,开始干活!' )
if __name__ == '__main__':
# 下载要的图片
F_stamp = int(round(time.time()*1000))
F_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()))
S_stamp = F_stamp - 7 * 24 * 3600*1000
S_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()- 7 * 24 * 3600))
logging.info( '本次监控的开始时间为:'+ str(S_time)+ ',对应时间戳为:' + str(S_stamp))
logging.info( '本次监控的结束时间为:'+ str(F_time)+ ',对应时间戳为:' + str(F_stamp))
##逐个下载图片
for index in range(len(img_urls)):
img_name = file_path + img_urls[index][0] + str(S_time)+ "-" + str(F_time) + ".png"
img_url = img_urls[index][1] + "&from=" + str(S_stamp) + "&to=" + str(F_stamp)
# print img_url
api_token = "amNfbmxrZjpqY19ubGtmQDEyMw==" #廊坊集群的
# img_name = "img" + time.strftime('%Y%m%d%H%M%S',time.localtime(time.time())) + ".png"
logging.info( '>>>>>>>>>>>>>开始下载图片' + img_name )
download_img(img_url, api_token, img_name)
img_urls[index][2] = img_name
logging.info( '>>>>>>>>>>>>>下载完成-图片' + img_name)
define_email();
logging.info( '>>>>>>>>>>>>>邮件发送成功')
##调用清理函数
del_files(file_path)
global timer
timer = threading.Timer(86400, do_job) # 86400秒就是一天
timer.start()
def del_files(path):
logging.info( '清理上个月的历史文件')
# 1. 获取「今天」
today = datetime.date.today()
# 2. 获取当前月的第一天
first = today.replace(day=1)
# 3. 减一天,得到上个月的最后一天
last_month = first - datetime.timedelta(days=1)
# 4. 格式化成指定形式
last_month_f = last_month.strftime("%Y-%m")
logging.info( '上个月为' + last_month_f)
for root,dirs,files in os.walk(path):#(使用 os.walk ,这个方法返回的是一个三元tupple(dirpath(string), dirnames(list), filenames(list)), 其中第一个为起始路径, 第二个为起始路径下的文件夹, 第三个是起始路径下的文件.)
for name in files:
if last_month_f in name:#判断某一字符串是否具有某一字串,可以使用in语句
logging.info( '删除历史文件' + os.path.join(root,name))
os.remove(os.path.join(root,name))##os.move语句为删除文件语句
# 计算当前时间到指定时间点的描述差
def get_interval_secs(target_time):
today = (datetime.date.today()).strftime('%Y%m%d')
today_time = today + "-" + target_time
today_time_date = datetime.datetime.strptime(today_time, '%Y%m%d-%H:%M:%S')
now = datetime.datetime.now()
interval = today_time_date - now
secs = interval.total_seconds()
if (secs > 0): return secs
else: return secs + 86400
timer = threading.Timer(get_interval_secs(alert_time), do_job) ### 邮件的发送时间
timer.start()
######################## 下载要的图片
def download_img(img_url, api_token, img_name ):
header = {"Authorization": "Basic " + api_token} # 设置http header
request = urllib2.Request(img_url, headers=header)
# print request
try:
response = urllib2.urlopen(request)
filename = img_name
if (response.getcode() == 200):
with open(filename, "wb") as f:
f.write(response.read()) # 将内容写入图片
return filename
except:
return "failed"
#########################发送邮件############
def define_email():
sender = '*@chinaunicom.cn' # 发件箱
# receiver = 'xxxxxxxx@qq.com' # 发给单人时的邮件接收邮箱
reciver = to_address + cc_reciver
smtpserver = "smtp.chinaunicom.cn" # 邮件服务器,如果是qq邮箱那就是这个了,其他的可以自行查找
username = 'aaaaa@chinaunicom.cn' # 发件箱
password = '*****' # 上发件箱密码
msgRoot = MIMEMultipart('related') # 邮件类型,如果要加图片等附件,就得是这个
msgRoot['Subject'] = '廊坊集群资源监控'+ str(S_time) + '~~~~' + str(F_time) # 邮件标题,以下设置项都很明了
msgRoot['From'] = sender
# msgRoot['To'] = receiver # 发给单人
msgRoot['To'] = ",".join( to_address ) # 发给多人
#message['Cc'] = ";".join(cc_reciver) # 抄送人
try:
# 以下为邮件正文内容,含有一个居中的标题和一张图片
content = MIMEText('<html>\
<head>\
<title>Page 1</title>\
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>\
</head>\
<body>\
<div id="string" >您好:</div></p>\
<div id="string" >      廊坊集群资源使用情况如下:</div></p>\
\
<div id="string" >      1.集群Vcore使用百分比:</p>\
      <img src="cid:image1" alt="image1" /></div></p>\
\
<div id="string" >      2.各队列内存绝对使用百分比:</p>\
      <img src="cid:image2" alt="image2" /></div></p>\
\
<div id="string" >      3.集群存储使用情况总览:</p>\
      <img src="cid:image3" alt="image3" /></div></p>\
\
<div id="string" >      4.各租户HDFS文件数:</p>\
      <img src="cid:image4" alt="image4" /></div></p>\
\
<div id="string" >      5.集群RPC队列和处理时间:</p>\
      <img src="cid:image5" alt="image5" /></div></p>\
\
<div id="string" >      6.集群网络IO:</p>\
      <img src="cid:image6" alt="image6" /></div></p>\
\
<div id="string" >      </p>\
<div id="string" >      </p>\
<div id="string" >      </p>\
<div id="string" >      </p>\
<div id="string" >      </p>\
<div id="string" >      </p>\
</body>\
</html>\
\
','html','utf-8')
# 如果有编码格式问题导致乱码,可以进行格式转换:
# content = content.decode('utf-8').encode('gbk')
msgRoot.attach(content)
# 上面加的图片src必须是cid:xxx的形式,xxx就是下面添加图片时设置的图片id
# 添加图片附件
for index in range(len(img_urls)):
img_name = img_urls[index][2]
fp = open(img_name, 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
# imageid = "image" + str(index+1)
msgImage.add_header('Content-ID', str("image" + str(index+1))) # 这个id用于上面html获取图片
msgRoot.attach(msgImage)
except:
content = MIMEText('<html>\
<head>\
<title>Page 1</title>\
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>\
</head>\
<body>\
<div id="string" >您好:</div>\
<div id="string" >      廊坊集群资源日报发送失败,请尽快处理。</div></p>\
</body>\
</html>\
\
','html','utf-8')
# 如果有编码格式问题导致乱码,可以进行格式转换:
# content = content.decode('utf-8').encode('gbk')
msgRoot.attach(content)
# 连接邮件服务器,因为使用SMTP授权码的方式登录
smtp = smtplib.SMTP('smtp.chinaunicom.cn:25')
smtp.login(username, password)
smtp.sendmail(sender, reciver, msgRoot.as_string())
smtp.quit()