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


- - 時間:2020年12月5日

- - 作者:飛翔的小胖豬

前言

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

環境

 

 

腳本說明

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

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

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

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

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

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

6.整合之前的所有數據,以主機名為key生成字典。

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,conn

# 指定模板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,db_conn = 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)
    db_conn.close()
    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表

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM