使用Python发送grafana快照拼合成的监控日报

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" >&nbsp &nbsp &nbsp 廊坊集群资源使用情况如下:</div></p>\
        \
            <div id="string"  >&nbsp &nbsp &nbsp 1.集群Vcore使用百分比:</p>\
            &nbsp &nbsp &nbsp <img src="cid:image1" alt="image1"  /></div></p>\
        \
            <div id="string" >&nbsp &nbsp &nbsp 2.各队列内存绝对使用百分比:</p>\
            &nbsp &nbsp &nbsp <img src="cid:image2" alt="image2"  /></div></p>\
        \
            <div id="string"  >&nbsp &nbsp &nbsp 3.集群存储使用情况总览:</p>\
            &nbsp &nbsp &nbsp <img src="cid:image3" alt="image3"  /></div></p>\
        \
            <div id="string"  >&nbsp &nbsp &nbsp 4.各租户HDFS文件数:</p>\
            &nbsp &nbsp &nbsp <img src="cid:image4" alt="image4"  /></div></p>\
        \
            <div id="string"  >&nbsp &nbsp &nbsp 5.集群RPC队列和处理时间:</p>\
            &nbsp &nbsp &nbsp <img src="cid:image5" alt="image5"  /></div></p>\
        \
            <div id="string"  >&nbsp &nbsp &nbsp 6.集群网络IO:</p>\
            &nbsp &nbsp &nbsp <img src="cid:image6" alt="image6"  /></div></p>\
        \
            <div id="string"  >&nbsp &nbsp &nbsp </p>\
            <div id="string"  >&nbsp &nbsp &nbsp </p>\
            <div id="string"  >&nbsp &nbsp &nbsp </p>\
            <div id="string"  >&nbsp &nbsp &nbsp </p>\
            <div id="string"  >&nbsp &nbsp &nbsp </p>\
            <div id="string"  >&nbsp &nbsp &nbsp </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" >&nbsp &nbsp &nbsp 廊坊集群资源日报发送失败,请尽快处理。</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()
    

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,451评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,172评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,782评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,709评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,733评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,578评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,320评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,241评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,686评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,878评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,992评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,715评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,336评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,912评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,040评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,173评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,947评论 2 355