Zabbix使用python導出性能數據execl表-從零到無

- - 時間:2020年12月5日html

- - 做者:飛翔的小胖豬python

前言

使用zabbix做爲基礎環境的監控系統時,除了經過web頁面和自定義告警通知手段獲取當前主機服務器運行狀態,趨勢數據也是很重要的,透過趨勢數據能夠了解服務器在某個時間範圍內關鍵指標狀況,是否長期高負載運行或長期空閒狀態。在虛擬化或雲平臺環境下趨勢數據可做爲服務器資源壓縮回收擴容參考數據,文章經過使用python腳本鏈接zabbix後端的mysql數據庫,查詢整理服務器運行性能數據生成execl文件。mysql

環境

 

 

腳本說明

該腳本只試用於linux操做系統中。具體工做思路及流程以下:linux

1.獲取到主機所在監控模板的id號(步驟能夠參考我https://www.cnblogs.com/Pigs-Will-Fly/p/13954583.html這篇文章中)文章中不涉及id號查詢方法。web

2.獲取指定監控模板下所包含的全部主機id號。sql

3.使用主機id號和主機名造成字典,以便後期整合數據用。數據庫

4.使用主機id號結合item指標查詢出每一個機器每一個指標惟一的item號並生成字典。後端

5.使用item號查詢出具體的數據。服務器

6.整合以前的全部數據,以主機名爲key生成字典。app

7.寫入數據到execl表中。

PS:腳本再查詢主機ID時使用的是監控模板ID,而不是使用分組ID號。

 

腳本文件

#!/usr/bin/python3
# @Date: 2020/10/29 21:16
# @Author: lvan
# @email: yinwanit@qq.com
# -*- coding: utf-8 -*-

import pymysql
import time,datetime
import math
from decimal import *
import xlsxwriter
import xlrd
#打開數據庫鏈接函數
def open_mysql_db(zdbhost,zdbuser,zdbpass,zdbport,zdbname):
    print(".開始鏈接數據庫...")
    conn = pymysql.connect(host=zdbhost, user=zdbuser, passwd=zdbpass, port=zdbport, db=zdbname, charset="utf8")
    cursor = conn.cursor()
    print("--完成:鏈接數據庫,狀態OK!")
    return cursor

# 指定模板ID,獲取模板中包含的主機id號
def get_temp_id(db_cursor,groupid):
    print("開始獲取模板中包含主機ID號...")
    sql = '''select hostid from hosts_templates where templateid = "{0}"'''.format(groupid)
    db_cursor.execute(sql)
    hostlist = [i for i in list("%s" %j for j in db_cursor.fetchall())]
    print("--完成:主機ID號獲取,狀態OK!")
    return hostlist
    #結果爲['10357', '10362', '10363', '10365']


#經過hostid獲取到主機的host名,定義一個保存主機IP地址和ID號的字典
def get_host_for_hostid(hostlist,db_cursor):
    print('.開始生成主機id號和主機名對應關係...')
    Ipinfo_dict = dict()
    for hostid in hostlist:  #每次從hostlist中取一個hostid出來,而後獲取到指定的host經過字典的方式加入到IpinfoList中去。
        #print("hostid:",hostid)
        sql = '''select host from hosts where status = 0 and hostid = {0}'''.format(hostid)
        ret = db_cursor.execute(sql)
        if ret:
            for i in db_cursor.fetchone():
                Ipinfo_dict[hostid] = i
    print('--完成:主機id與主機名關係生成,狀態OK!')
    return Ipinfo_dict
    #結果{'10357': '192.168.111.131', '10362': '192.168.111.11', '10363': '192.168.111.12', '10365': '192.168.111.124'}



#獲取指定id號的主機的item資源號,在trends表和trends_uint中
def get_itemid(keys,hostlist,db_cursor):
    print('.開始獲取ITEM號...')
    Item_key_dict = dict()
    Hostid_Item_dict = dict()
    Item_name_list = list()
    item_name_dir = dict()
    for bb in ['trends','trends_uint']:
        Iteminfo_list = list()
        for j in keys[bb]:
            for k in hostlist:
                #print("this is %s,this er %s",j,k)
                sql = '''select itemid from items where hostid = {0} and key_ = "{1}" '''.format(k,j)
                if db_cursor.execute(sql):
                    itemid = "".join("%s" %i for i in list(db_cursor.fetchone()))
                    Hostid_Item_dict[itemid] = k
                    Iteminfo_list.append(itemid)
                    item_name_dir[itemid] = j
                else:
                    itemid = None
            Item_key_dict[bb] =Iteminfo_list
    print('--完成:ITEM號獲取,狀態OK!')
    return Item_key_dict,Hostid_Item_dict,item_name_dir
    #結果:輸出的item_dict: {'trends': ['33875', '34302', '34367', '34497', '33882', '34309', '34374', '34504', '33878', '34305', '34370', '34500'], 'trends_uint': ['33903', '34330', '34395', '34525', '33905', '34332', '34397', '34527']}
    #輸出的item_host_dict: {'33875': '10357', '34302': '10362', '34367': '10363', '34497': '10365', '33882': '10357', '34309': '10362', '34374': '10363', '34504': '10365', '33878': '10357', '34305': '10362', '34370': '10363', '34500': '10365', '33903': '10357', '34330': '10362', '34395': '10363', '34525': '10365', '33905': '10357', '34332': '10362', '34397': '10363', '34527': '10365'}



#整合數據,以前得主機id,ip地址,item值名,item名整合在一塊兒。
def format_all_data(host_id_list,id_ip_dir,Item_key_dict,Hostid_Item_dict,Item_name_dir,item_values_dir_list):
    print('.開始整合數據...')
    resut_info = dict()
    for i in list(id_ip_dir.values()):
        temp_values_dir = dict()
        #print(i) #經過ip來肯定,若是i和item_name_dir裏面數據查出來的一致則記錄數據到字典,當數據記錄完畢後添加到最終字典中,並開啓下一次循環,清空temp_values_dir字典
        for j in list(Item_name_dir.keys()):
            #print(j)
            temp_ip = id_ip_dir[Hostid_Item_dict[j]]
            temp_item_name = Item_name_dir[j]
            temp_value = item_values_dir_list[j]
            if temp_ip == i:
                temp_values_dir[temp_item_name] = temp_value
        resut_info[i] = temp_values_dir
    print('--完成:整合數據完成,狀態OK!')
    return resut_info
    #最終想獲得的數據格式爲:{ip:{{cpu:[最小,中間,最大]}},{內存:[最小,中間,最大]}}


#查詢指定表中的指定指標的數據,反饋itemid和及值名字類型大小。
def get_items_valuesb(item_dict_r,db_cursor,start_time,end_time):
    print('.開始查詢數據...')
    resultlist = {}
    for table_name in ['trends','trends_uint']:
        for itemid in item_dict_r[table_name]:
            sql = '''select min(value_min),avg(value_avg),max(value_max) from {2} where itemid = {3} and clock >= {4} and clock <= {5}'''.format(type, type, table_name, itemid, start_time, end_time)
            db_cursor.execute(sql)
            result = db_cursor.fetchall()
            for aa,bb,cc in result:
                value_list = list()
                value_list.append(aa)
                value_list.append(bb)
                value_list.append(cc)
                resultlist[itemid] = value_list
    print('完成:數據查詢完成,狀態OK!')
    return  resultlist
    #生成格式爲{itemid:[min,avg,max]}


#寫入數據到execl中
def writeexecl(format_data_r_dict,file_dir):
    # 建立文件
    print('開始生成execl文件...')
    workbook = xlsxwriter.Workbook(file_dir)
    # 建立工做薄
    worksheet = workbook.add_worksheet()
    print(" 建立工做薄");
    # 寫入標題(第一行)
    i = 0
    for value in ["ip地址", "CPU負載谷值", "CPU負載均值", "CPU負載峯值","根目錄使用GB",'根目錄使用百分比GB','更目錄總量GB','內存可用谷值GB','內存可用均值GB','內存可用峯值GB','內存總大小GB','CPU空閒谷','CPU空閒均','CPU空閒峯','CPU個數']:
        worksheet.write(0, i, value)
        i = i + 1
        # 寫入內容:
    j = 1
    for ip_host in list(format_data_r_dict.keys()):
        #這爲一行
        value= format_data_r_dict[ip_host]
        worksheet.write(j, 0, ip_host)
        worksheet.write(j, 1, value['system.cpu.load[all,avg15]'][0])
        worksheet.write(j, 2, value['system.cpu.load[all,avg15]'][1])
        worksheet.write(j, 3, value['system.cpu.load[all,avg15]'][2])
        worksheet.write(j, 4, '{}GB'.format(math.ceil(value['vfs.fs.size[/,used]'][0] / 1024 / 1024 / 1024)))
        worksheet.write(j, 5, '{:.2f}%'.format(value['vfs.fs.size[/,pused]'][0]))
        worksheet.write(j, 6, '{}GB'.format(math.ceil(value['vfs.fs.size[/,total]'][0] / 1024 / 1024 / 1024)))
        worksheet.write(j, 7, '{}GB'.format(math.ceil(value['vm.memory.size[available]'][0] / 1024 / 1024 / 1024)))
        worksheet.write(j, 8, '{}GB'.format(math.ceil(value['vm.memory.size[available]'][1] / 1024 / 1024 / 1024)))
        worksheet.write(j, 9, '{}GB'.format(math.ceil(value['vm.memory.size[available]'][2] / 1024 / 1024 / 1024)))
        worksheet.write(j, 10, '{}GB'.format(math.ceil(value['vm.memory.size[total]'][0] / 1024 / 1024 / 1024)))
        worksheet.write(j, 11, '{:.2f}%'.format(value['system.cpu.util[,idle]'][0]))
        worksheet.write(j, 12, '{:.2f}%'.format(value['system.cpu.util[,idle]'][1]))
        worksheet.write(j, 13, '{:.2f}%'.format(value['system.cpu.util[,idle]'][2]))
        worksheet.write(j, 14, value['system.cpu.num'][0])
        j = j + 1
    workbook.close()
    print(" 完成:execl文件生成,狀態OK!路徑爲: ",file_dir)

if __name__ == "__main__":
    # zabbix數據庫信息:
    zdbhost1 = "192.168.111.124"
    zdbuser1 = "zabbix"
    zdbpass1 = "password"
    zdbport1 = 3306
    zdbname1 = "zabbix"
    #監控模板id號
    groupid = 10001
    #定義時間範圍,此處填寫的時時間戳。可以使用https://tool.lu/timestamp/網頁工具自行轉換,因此失效了自行百度。
    start_time = 0
    end_time = 999999999999
    #設置execl保存文件名
    save_file_dir = 'test2222.xls'
    # 須要查詢的key列表,trends_unit字典裏面的是trends_uint裏的值;trends字典裏面的是trends的值
    keys = {
        'trends_uint': [
            'vfs.fs.size[/,used]',
            'vm.memory.size[available]',
            'vm.memory.size[total]',
            'system.cpu.num',
            'vfs.fs.size[/,total]',
        ],
        'trends': [
            'system.cpu.load[all,avg15]',
            'system.cpu.util[,idle]',
            'system.swap.size[,pfree]',
            'vfs.fs.size[/,pused]',
        ],
    }
    db_r = open_mysql_db(zdbhost1,zdbuser1,zdbpass1,zdbport1,zdbname1)
    hostid_r = get_temp_id(db_r,groupid)
    ee = get_host_for_hostid(hostid_r,db_r)
    a,b,c=get_itemid(keys,hostid_r,db_r)
    ff = get_items_valuesb(a, db_r,start_time,end_time)
    ll = format_all_data(hostid_r,ee,a,b,c,ff)
    writeexecl(ll,save_file_dir)
View Code

 

如何使用腳本

讀者在copy腳本到本身本地後還須要對腳本中部分位置進行修改(下列沒有提到的地方儘可能不要修改)。須要修改的清單以下。

.基本參數類:

    》數據庫地址

    》數據庫用戶名

    》數據庫用戶密碼

    》數據庫端口

    》數據庫庫名

    》監控模板id號

    》時間範圍開始時間

    》時間範圍結束時間

    》execl文件保存位置

.指標類:

    》keys字典值須要根據需求在其後添加對應指標

.execl類:

    》根據需求修改writeexecl函數中列名及列數據

 

基本參數修改:

基本參數類在main()函數中一目瞭然按照實際狀況修改就好了。

 

修改指標及execl修改:

腳本中的指標和execl輸出的內容基本包含了服務器主要關注的點,讀者能夠直接使用腳本中的指標及execl輸出格式。若是須要對指標和execl輸出結果進行修改,須要作到execl輸出內容必定要在keys字典中。

指標:

在main()函數的keys字典中根具實際需求添加(execl中用到的數據必須包含在keys,keys中的數據能夠不被execl使用)。

  

 

execl輸出:

writeexecl()函數中定義了execl輸出的列及實際數據,修改該函數時須要作到列名數量和實際數據列數據一致。

    列名:在for value in 列中紅色圈的列表中添加或者修改字符。

 

    具體數據:writeexecl()函數中修改具體數據來源時須要注意數據填入的具體列數。

 列名:0表示第一列,根據實際狀況寫入數據到具體列。

 指標:keys字典中的值,須要寫入到execl中才寫入進來。

 下標:每個指標在收集數據時都是一致的,下標0表示該指標的最小值,1表示該指標的均值,2表示該指標的峯值。

 

執行結果

 

結果execl表

相關文章
相關標籤/搜索