1. 程式人生 > 實用技巧 >Zabbix使用python匯出效能資料execl表-從零到無

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: [email protected]
# -*- 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表