我公司在某項(xiàng)目組維護(hù)的OGG(Oracle Goldengate,一款數(shù)據(jù)同步軟件),由于局方?jīng)]有成熟的監(jiān)控平臺,一直沒有短信告警,導(dǎo)致我方維護(hù)人員每天都需要頻繁登錄每個配置過OGG的主機(jī)進(jìn)行巡檢(目前已達(dá)20多臺),工作重復(fù)量較大,但一直沒有很好的解決辦法。雖然可通過寫shell腳本,并配置crontab定時任務(wù)的方式生成巡檢結(jié)果,但還是需要人為地查看。前不久,局方給了一個HTTP接口,說是通過調(diào)用這個接口便可實(shí)現(xiàn)短信監(jiān)控,但是沒給調(diào)用該接口的具體實(shí)現(xiàn)代碼。 正好那段時間我所在的項(xiàng)目組離那邊比較近,接到同事的反饋后,就想如何去實(shí)現(xiàn)這個監(jiān)控的需求。
雖然用shell腳本也可以實(shí)現(xiàn)http接口的調(diào)用(使用curl命令、GET/POST的方式),但是比較復(fù)雜,而且后期不好維護(hù)。既然已經(jīng)放棄了使用shell腳本實(shí)現(xiàn)(主要還是自己懶。。。),那么就得用一種編程語言來做了。既要比shell編寫起來簡單直觀,還要便于后期維護(hù),最好還能有時間、相關(guān)運(yùn)行日志的記錄,那么好像非Python莫屬了,哈哈!話不多說,下面就大概說一下實(shí)現(xiàn)的具體過程。
HTTP接口的調(diào)用方式
HTTP接口的調(diào)用格式如下:
http://xxx.xxx.0.2/sms/sendsms.php?Action=MSG_ALERT&DestTermID=手機(jī)號碼&MsgContent=告警內(nèi)容
HTTP接口的好處就是,測試的時候可以在瀏覽器內(nèi)直接調(diào)用。我們先拼湊一條告警信息,并直接在瀏覽器中輸入:
http://xxx.xxx.0.2/sms/sendsms.php?Action=MSG_ALERT&DestTermID=180xxxx3808&MsgContent=OGG_ALERT!
很快就能收到返回的告警信息,說明請求的格式?jīng)]問題。
初步監(jiān)控目標(biāo)
OGG進(jìn)程狀態(tài)共有RUNNING, STOPPED, ABENDED三種,其中RUNNING為正常運(yùn)行狀態(tài),STOPPED一般是人為停止的狀態(tài),ABENDED是由于數(shù)據(jù)同步等原因?qū)е碌漠惓V袛酄顟B(tài)。我們初步的監(jiān)控目標(biāo)就是能夠發(fā)現(xiàn)異常ABENDED的進(jìn)程,并定時發(fā)送告警短信給相關(guān)維護(hù)人員(即監(jiān)控圖中的Status列)。
對于監(jiān)控頻率的設(shè)置,通過詢問局方人員得知,目前需要監(jiān)控的系統(tǒng)有本地和異地容災(zāi)兩部分系統(tǒng)。異地容災(zāi)系統(tǒng)由于有集團(tuán)考核,及時性要求較高,出現(xiàn)問題必須馬上處理,所以需要配置成每5分鐘檢查一次;而本地系統(tǒng)配置成每小時檢查一次即可。
收集告警信息
根據(jù)上面的接口調(diào)用方式,那么我們現(xiàn)在要做的可以分以下幾步:
1) 收集OGG的運(yùn)行狀態(tài),并匯總到一起;
2) 過濾出包含ABENDED的進(jìn)程及對應(yīng)的業(yè)務(wù)系統(tǒng)名稱;
3) 發(fā)送包含該業(yè)務(wù)系統(tǒng)名稱的告警短信給相關(guān)人員(注:短信接收人員可能有多個)。
其中的第一條,我們的同事已經(jīng)通過shell腳本實(shí)現(xiàn)好了(還加入了對目錄使用率的告警),并統(tǒng)一ftp到了一臺Windows監(jiān)控主機(jī)的目錄下,幫了我的一個大忙。腳本內(nèi)容如下:
oggcheck.sh (主要收集OGG進(jìn)程狀態(tài)、目錄使用率情況及超過閾值后的關(guān)鍵字over_load)
#!/usr/bin/sh
# 設(shè)置OGG目錄使用率閾值
OGG_DIR_THRESHOLD=60
# 獲取并輸出操作系統(tǒng)類型
OS_TYPE=`uname -a| awk '{print $1}'`
echo "OS TYPE: $OS_TYPE"
## 獲取OGG安裝目錄
# 使用查找mgr進(jìn)程的命令查找OGG安裝目錄
VAR1=`ps -ef|grep mgr.prm | grep -v grep`
# 從左邊開始,刪除PARAMFILE左邊所有的字符
VAR2=${VAR1#*PARAMFILE}
# 從右邊開始,刪除dirprm右邊所有的字符
OGG_HOME=${VAR2%dirprm*}
# 獲取OGG運(yùn)行狀態(tài)
cd $OGG_HOME
echo "info all" | ./ggsci
# 獲取OGG目錄使用率(當(dāng)前維護(hù)系統(tǒng)主要有LINUX, AIX和HP-UX三類)
if [ $OS_TYPE = 'Linux' ];then
VAR3=`df -h $OGG_HOME | sed -n '$p'|cut -d '%' -f 1|awk '{print $NF}'`
elif [ $OS_TYPE = 'AIX' ];then
VAR3=`df -g $OGG_HOME | sed -n '$p'|cut -d '%' -f 1|awk '{print $NF}'`
elif [ $OS_TYPE = 'HP-UX' ];then
VAR3=`bdf $OGG_HOME | sed -n '$p'|cut -d '%' -f 1|awk '{print $NF}'`
else
OGG_DIR_USAGE=100 # 如果操作系統(tǒng)無法識別,則輸出100
echo "`hostname`'s OS TYPE IS UNKNOWN!"
fi
OGG_DIR_USAGE=${VAR3#* }
# 輸出OGG目錄的實(shí)際使用率及關(guān)鍵字over_load(關(guān)鍵字用于給后面程序判斷是否發(fā)目錄告警時用)
if [ "$OGG_DIR_USAGE" -ge "$OGG_DIR_THRESHOLD" ];then
echo -e "\n`hostname`'s OGG directory usage is: $OGG_DIR_USAGE%, over_load"
fi
put_alert_file.sh(上傳監(jiān)控文件)
#!/usr/bin/sh
# 獲取IP地址
IP_ADD=$(awk '{print $1,$2}' /etc/hosts|grep "$(hostname)""$"|awk '{print $1}')
# 設(shè)置監(jiān)控文件絕對路徑
FILE_NAME=/home/oracle/ogg_mon/"$IP_ADD"_`hostname`.txt
# 設(shè)置監(jiān)控文件名稱
FILE_NAME_SHORT="$IP_ADD"_`hostname`.txt
# 將oggcheck.sh的執(zhí)行結(jié)果輸出到$FILE_NAME監(jiān)控文件中
/bin/sh oggcheck.sh>$FILE_NAME 2>&1
# 設(shè)置目錄名稱
dirdate=`date "+%Y%m%d"`
# 使用ftp創(chuàng)建當(dāng)日目錄,并上傳監(jiān)控文件
ftp -n <<!
open xxx.2.0.11 50191
user admin admin
pwd
binary
cd ogg
# 按當(dāng)天日期創(chuàng)建目錄
mkdir ${dirdate}
cd ${dirdate}
lcd /home/oracle/ogg_mon
prompt
put ${FILE_NAME_SHORT}
bye
!
rm -f /home/oracle/ogg_mon/*.txt
echo "finish"
創(chuàng)建配置文件
第二步就主要是對告警信息的處理了。在處理之前,我們需要先定義一個配置文件,里面存放例如需要監(jiān)控的系統(tǒng)信息、告警接收人的手機(jī)號碼、告警內(nèi)容等。如果以后這些內(nèi)容有變動,直接在配置文件中修改即可,便于維護(hù)。
代碼如下:
settings.py
class Settings():
def __init__(self):
""" 所有告警系統(tǒng)的配置(包括異地災(zāi)備系統(tǒng))
配置方法:采用鍵值對的方式,鍵為具體的告警文件名稱(帶擴(kuò)展名),值為對應(yīng)的系統(tǒng)名稱(可自定義).
告警內(nèi)容將使用自定義系統(tǒng)名稱,建議將IP也一并配置進(jìn)系統(tǒng)名稱。
例如:"xxx.0.0.1_xxxdb1.txt":"xxx.0.0.1_xxxdb1" 表示告警文件為 xxx.0.0.1_xxxdb1.txt,
自定義的系統(tǒng)名稱為 xxx.0.0.1_xxxdb1 ,如果有告警,該系統(tǒng)名稱會顯示在告警短信中。
注:修改配置信息后需重啟程序方可生效。
重啟方式:任務(wù)管理器中kill pyw.exe進(jìn)程,再雙擊程序目錄中的alert.pyw文件即可。可查看本地日志確認(rèn)是否啟動進(jìn)程。 """
self.all_systems = {"xxx.0.2.1_erpdb1.txt":"xxx.0.0.1_erpdb1","xxx.0.2.32_pmpdb1.txt":"xxx.0.2.32_pmpdb1",
"xxx.1.20.131_xnyx.txt": "xxx.1.20.131_xnyx", "xxx.1.18.79_ods.txt": "xxx.1.18.79_remote"
}
# 異地災(zāi)備告警系統(tǒng)配置(災(zāi)備系統(tǒng)告警閾值為5分鐘,需另單獨(dú)配置一份,只配置系統(tǒng)名稱即可,必須跟上面配置的系統(tǒng)名稱一致)
self.remote_systems = ['xnyx', 'xxx.1.18.79_remote']
# 配置接收告警的手機(jī)號碼
self.acc_nbr = [181xxxx9607, 152xxxx8230, 152xxxx3315, 133xxxx8640, 177xxxx213, 136xxxx6297]
# 設(shè)置本地日志路徑
self.logfile_name = 'D:\\ogg_alert\\log\\info.log'
# 設(shè)置告警文件路徑
self.alert_file_path = 'D:\\系統(tǒng)軟件\\oggxj\\'
# 設(shè)置告警相關(guān)的字符串,用于拼接告警信息
self.url1 = "http://xxx.xxx.0.2/sms/sendsms.php?Action=MSG_ALERT&DestTermID="
self.url2 = "&MsgContent="
self.abend_warning = "_Goldengate:ABENDED"
# 為方便起見,這里只提示目錄使用率大于60%。實(shí)際值可以從監(jiān)控文件中提取
self.dict_warning = "_Goldengate_directory_usage_>_60%!"
按照時間生成日志路徑
按照上面shell腳本的內(nèi)容,每天都會生成一個YYYYMMDD格式的文件夾,然后再將當(dāng)日的監(jiān)控文件放入該文件夾中(會覆蓋上次的文件)。所以我們在程序中也要按照日期動態(tài)生成路徑:
functions.py
import time
import os
def time_path(sys_settings):
# 生成固定格式的日期字符串并拼接
time_format = time.strftime('%Y%m%d', time.localtime())
alert_path = sys_settings.alert_file_path + time_format
# 改變當(dāng)前工作目錄至alert_path
os.chdir(alert_path)
按照要求,監(jiān)控每隔5分鐘就會掃描一次,所以在每次循環(huán)中都調(diào)用此函數(shù)即可。
處理告警信息
我們采用的方法是遍歷每個告警文件,并處理成列表,如果存在ABENDED或者over_load(OGG目錄告警關(guān)鍵字),就使用相關(guān)信息生成告警內(nèi)容,并記錄日志。
functions.py
def get_alert_list(sys_settings):
info_list = []
try:
# 遍歷當(dāng)前目錄下的文件
for filename in os.listdir():
with open(filename) as file:
lines = file.read()
# 使用空格分割成列表
line_list = lines.split()
if 'ABENDED' in line_list:
# 使用settings.py中配置的系統(tǒng)名稱及告警信息進(jìn)行拼接
info = sys_settings.all_systems[filename] + sys_settings.abend_warning
info_list.append(info)
# 將處理好的告警內(nèi)容寫入日志
log_write("WARNING: " + info + "\n", sys_settings)
if 'over_load' in line_list:
info = sys_settings.all_systems[filename] + sys_settings.dict_warning
info_list.append(info)
log_write("WARNING: " + info + "\n", sys_settings)
except PermissionError as e:
log_write("Alert file not found!\n")
""" 返回告警內(nèi)容 """
return info_list
def log_write(log_info, settings):
# 以固定格式寫入日志內(nèi)容
with open(settings.logfile_name, 'a') as logfile:
logfile.write("[" + time.strftime('%Y/%m/%d %H:%M:%S', time.localtime()) + "] " + log_info)
發(fā)送告警
收集并記錄好告警信息后,我們就可以使用這些信息給指定人員發(fā)送短信了。能夠成功發(fā)送請求的關(guān)鍵是對指定的url調(diào)用request.get()方法,從而獲得相應(yīng)的返回碼(一般的接口在處理完成后都會給請求方返回一個字符或數(shù)字作為返回碼,可以進(jìn)一步寫一個處理返回碼的函數(shù),記錄或者發(fā)送返回碼對應(yīng)的信息,這里為了簡便就省略了)。
因?yàn)槲覀円衙織l告警信息都發(fā)送給所有的告警接收人員,所以在遍歷告警信息的同時,也需要遍歷電話號碼:
functions.py
import requests
from urllib.error import URLError
def send_info(info_list, sys_settings):
for info in info_list:
for phone_num in sys_settings.acc_nbr:
# 按照http接口請求格式拼接字符串
url = sys_settings.url1 + str(phone_num) + sys_settings.url2 + info
try:
# get_code 為對應(yīng)的返回碼,這里為了簡便不做處理
get_code = requests.get(url)
# 在日志中記錄將告警發(fā)送給哪個電話號碼
log_write(info + " send to: " + str(phone_num) + "\n", sys_settings)
except URLError as e:
# 如果調(diào)用失敗,則記錄連接錯誤的日志
log_write("connect to the server failed!\n", sys_settings)
針對不同的業(yè)務(wù)系統(tǒng)發(fā)送告警
有了上面的send_info()函數(shù)后,我們只要傳入包含告警信息的列表info_list及配置信息sys_settings,就可以向指定人員發(fā)送告警了。但是在正式發(fā)送前,針對本地系統(tǒng)和異地容災(zāi)系統(tǒng)告警頻率的差異,需要分別寫兩個函數(shù)分別進(jìn)行處理:
functions.py
def send_remote_only(alert_list, sys_settings):
# 只發(fā)送異地容災(zāi)系統(tǒng)的告警
if len(alert_list) == 0:
log_write("There is no alert, process finished!\n\t"
"Remote process will restart after 5 min ... ...\n", sys_settings)
else:
for remote_system in sys_settings.remote_systems:
abend_warning = remote_system + sys_settings.abend_warning
dict_warning = remote_system + sys_settings.dict_warning
if abend_warning in alert_list:
send_info([abend_warning], sys_settings)
log_write("Remote process will restart after 5 min ... ...\n", sys_settings)
if dict_warning in alert_list:
send_info([dict_warning], sys_settings)
def send_all(alert_list, sys_settings):
# 發(fā)送所有系統(tǒng)的告警
if len(alert_list) == 0:
log_write("There is no alert, process finished!\n\t"
"Local process will restart after 60 min ... ...\n", sys_settings)
else:
send_info(alert_list, sys_settings)
log_write("Local process will restart after 60 min ... ...\n", sys_settings)
使用主程序文件
目前,我們已經(jīng)基本上完成了所有的功能,只差一個不斷調(diào)用這些函數(shù)的循環(huán)結(jié)構(gòu)以及控制定時發(fā)送的策略了。循環(huán)結(jié)構(gòu)使用while循環(huán)即可,對時間的控制可以使用time.sleep()方法。所以我們需要一個主程序文件來統(tǒng)一控制這些動作。
alert.pyw
from settings import Settings
from timepath import TimePath, time
from functions import send_all, send_remote_only, log_write, get_alert_list, time_path
# 初始化配置信息
sys_settings = Settings()
# 初始化用于計數(shù)的變量n
n = 0
# 主循環(huán)
while True:
try:
# 調(diào)用time_path生成日志路徑
time_path(sys_settings)
except FileNotFoundError as e:
# 如果發(fā)生FileNotFoundError,說明當(dāng)日目錄未生成,記錄到日志中
log_write("Alert Directory not exists!\n", sys_settings)
alert_list = get_alert_list(sys_settings)
""" 如果n == 12,就調(diào)用send_all()函數(shù),檢查所有系統(tǒng)
否則就調(diào)用send_remote_only()函數(shù),只檢查異地容災(zāi)系統(tǒng) """
n += 1
if n == 12:
send_all(alert_list, sys_settings)
n = 0
time.sleep(300)
else:
send_remote_only(alert_list, sys_settings)
# 使用time.sleep()方法,每5分鐘進(jìn)行一次循環(huán)
time.sleep(300)
注意到,我們的主程序文件alert.pyw的擴(kuò)展名是.pyw,這是因?yàn)樵赪indows環(huán)境下,.pyw文件可以通過直接雙擊在后臺運(yùn)行,不用再打開編輯器執(zhí)行了。
功能測試
程序運(yùn)行一段時間后查看記錄的日志:
正常運(yùn)行時的日志:
目錄使用率超過設(shè)定的60%時的日志:
本地系統(tǒng)(到達(dá)一小時后統(tǒng)一發(fā)送告警):
異地容災(zāi)系統(tǒng)(5分鐘掃描并發(fā)送告警):
OGG進(jìn)程異常ABENDED時的日志:
本地系統(tǒng):
異地容災(zāi)系統(tǒng):
可以看到,所有功能都測試正常。
監(jiān)控延遲
之前實(shí)現(xiàn)的是最基本的對進(jìn)程狀態(tài)的監(jiān)控。在有些對數(shù)據(jù)實(shí)時性要求較高的系統(tǒng)中,只監(jiān)控這些還不夠,還需要對延遲時間進(jìn)行監(jiān)控。
圖中標(biāo)出的Lag at Chkpt列即在事務(wù)能夠正常提交情況下的延遲總時間,如果有延遲,說明這個進(jìn)程里同步的表或數(shù)據(jù)過多,需要做拆分;Time Since Chkpt列是指距離上次事務(wù)提交的時間,如果該列出現(xiàn)延遲,說明有大事務(wù),或者有索引缺失導(dǎo)致DML操作執(zhí)行較慢等情況,也需要關(guān)注。所以在監(jiān)控延遲時,只需關(guān)注這兩列即可。
假設(shè)我們的目標(biāo)是當(dāng)延遲大于5分鐘時輸出告警信息,則需要提取這兩列表示分鐘的項(xiàng)并做判斷。這要比上面的只對Status列做判斷要稍微復(fù)雜一些,除了同時取多個列之外(進(jìn)程名稱、兩個延遲列),還涉及分割、數(shù)據(jù)類型轉(zhuǎn)換等操作。所以我們計劃使用numpy數(shù)組存放多個列的值,方便后續(xù)在時間上的判斷(numpy數(shù)組可以進(jìn)行矩陣運(yùn)算,比循環(huán)的效率要高)。寫日志也換一種方式,使用csv.reader()輸出延遲信息。
為了便于閱讀,我們將延遲信息單獨(dú)生成一個文件進(jìn)行判斷。
oggcheck_new.sh
## 獲取OGG安裝目錄
# 使用查找mgr進(jìn)程的命令查找OGG安裝目錄
VAR1=`ps -ef|grep mgr.prm | grep -v grep`
# 從左邊開始,刪除PARAMFILE左邊所有的字符
VAR2=${VAR1#*PARAMFILE}
# 從右邊開始,刪除dirprm右邊所有的字符
OGG_HOME=${VAR2%dirprm*}
# 獲取OGG運(yùn)行狀態(tài)
cd $OGG_HOME
# 每次覆蓋寫當(dāng)時的監(jiān)控信息
date > /acfs/dump/ogginfo.tmp
echo "info all" | /ogg/ggsci |grep -E "MANAGER|EXTRACT|REPLICAT" >> /acfs/dump/ogginfo.tmp
# 將監(jiān)控信息同時寫入備份監(jiān)控文件
date >> /oradump/ogg_tmp/ogginfo.bak
echo "info all" | /ogg/ggsci |grep -E "MANAGER|EXTRACT|REPLICAT" >> /acfs/dump/ogginfo.bak
使用crontab將整個腳本設(shè)置成5分鐘執(zhí)行一次:
*/5 * * * */home/ogg/chk_ogg_status.sh >> /home/ogg/chk_oggstatus.log 2>&1
我們先寫主程序文件,取進(jìn)程名稱和兩個延遲列的數(shù)據(jù),并將其放到numpy數(shù)組中。
ogg_lag_mon.py
import sys
sys.path.append('/ogg/dirsql/py_mon') # 進(jìn)入延遲監(jiān)控腳本所在目錄
import csv
import numpy as np
alert_file = '/acfs/dump/ogginfo.tmp' # 設(shè)置監(jiān)控文件路徑
alert_his_file = '/acfs/dump/ogginfo.bak' # 設(shè)置備份文件路徑
lag_min = 5 # 設(shè)置延遲時間
error_log = '/ogg/dirsql/py_mon/lag.log' # 設(shè)置本地錯誤日志路徑
lines = list(csv.reader(open(alert_file))) # 將監(jiān)控文件內(nèi)容轉(zhuǎn)換成列表
values = lines[2:] # 取實(shí)際的進(jìn)程信息(前兩個元素為時間和MANAGER進(jìn)程的狀態(tài))
group_name = [] # 進(jìn)程名稱(GROUP)
lag_time = [] # 延遲時間(Lag at Chkpt)
ckpt_time = [] # 事務(wù)提交延遲時間(Time Since Chkpt)
for value in values:
group_name.append(value[0].split()[2])
lag_time.append(value[0].split(':')[1])
ckpt_time.append(value[0].split(':')[-2])
result_arr = np.array((group_name, lag_time, ckpt_time))
注:將監(jiān)控文件內(nèi)容轉(zhuǎn)成lines列表時,我們按慣例就應(yīng)該查看一下lines列表里到底裝了些什么(為保持代碼的連貫性,在這里給出分析步驟):
可以看到,這是一個列表中嵌套列表的結(jié)構(gòu),而且前兩項(xiàng)不是我們要分析的數(shù)據(jù)(本例中暫不考慮MANAGER進(jìn)程的狀態(tài)),我們需要的元素的格式為:
[‘EXTRACT RUNNING EXT01 00:00:00 00:00:01 ‘]
這個列表元素只有一項(xiàng),取進(jìn)程名稱EXT01時可以按照空格分割,取后兩列時間的分鐘數(shù)值時可直接按照分號分割,分別添加到指定的列表中。最后將三個列表作為元素轉(zhuǎn)換成numpy數(shù)組result_arr。
查看result_arr的內(nèi)容:
>>> result_arr
array([['EXT01', 'EXT02', 'EXT03'],
['00', '08', '07'],
['00', '00', '00']],
dtype='|S8')
這實(shí)際上是一個3*3的數(shù)組,第0行為進(jìn)程名稱,第1行為延遲時間,第2行為事務(wù)提交延遲時間??梢钥吹剑靡呀?jīng)有超過lag_min的進(jìn)程了(第1行超過5的元素值)。我們先定義一個記錄日志的函數(shù)alert_writer(),然后再定義一個寫延遲信息的函數(shù)write_lag(),write_lag()函數(shù)可以調(diào)用alert_writer()函數(shù)記錄延遲信息:
alert_writer.py
import csv
def alert_writer(fileName, *contents):
with open(fileName, 'a') as file_obj:
writer = csv.writer(file_obj)
writer.writerow(contents)
注:因?yàn)槭褂胏sv.writer()寫數(shù)據(jù)時,每個元素之間都以逗號分隔,所以通過使用任意數(shù)量的實(shí)參*contents,來記錄你想記錄的任何信息。
write_lag.py
import numpy as np
from datetime import datetime
from pyfunc.alert_writer import alert_writer
def write_lag(result_arr, rows, lag_min, alert_his_file):
# 使用np.where()獲得對應(yīng)rows行中大于lag_min的元素的索引
# rows只需取1, 2行,第0行為進(jìn)程名稱
index_lag = np.where(result_arr[rows].astype(int) > lag_min)
if len(index_lag) != 0:
for indexes in index_lag:
for index in indexes:
# 將延遲信息寫入備份文件
alert_writer(alert_his_file, 'LAG', result_arr[0][index], result_arr[rows][index] + ' minutes', datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
最后,我們再完善主程序ogg_lag_mon.py中的代碼,將收集到的result_arr數(shù)組帶入write_lag()函數(shù)中進(jìn)行判斷,并記錄延遲信息:
ogg_lag_mon.py
import sys
sys.path.append('/ogg/dirsql/py_mon')
from pyfunc.alert_writer import alert_writer
from pyfunc.write_lag import write_lag
import csv
from datetime import datetime
import numpy as np
... ...
try:
for value in values:
group_name.append(value[0].split()[2])
lag_time.append(value[0].split(':')[1])
ckpt_time.append(value[0].split(':')[-2])
result_arr = np.array((group_name, lag_time, ckpt_time))
# row1為Lag at Chkpt列
write_lag(result_arr, rows=1, lag_min, alert_his_file)
# row2為Time Since Chkpt
write_lag(result_arr, rows=2, lag_min, alert_his_file)
except IndexError as e:
alert_writer(error_log, 'Lag exists, please try later!', datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
最后對存在延遲的OGG進(jìn)行測試,日志中記錄的信息為:
以上只是將進(jìn)程的相關(guān)信息輸出到了日志,同樣也可以組織成統(tǒng)一的格式,利用HTTP接口發(fā)送延遲的告警短信。具體方法與上面介紹的相似,不再贅述。有相同環(huán)境的同學(xué)可以自行實(shí)現(xiàn)。實(shí)際上,像這種比較成熟的應(yīng)用程序,輸出的日志格式基本上都是固定的,可以針對平時常用的幾個產(chǎn)品,對不同的格式先分別進(jìn)行格式化處理,然后統(tǒng)一生成相同格式的內(nèi)容,無論是發(fā)送告警,還是做進(jìn)一步的數(shù)據(jù)分析,都是非常方便的。
總結(jié)
在我們工程師日常運(yùn)維的過程中,除了做好每天份內(nèi)的工作外,有時候也經(jīng)常會接到客戶提出的一些超出我們職責(zé)范圍的需求。這時候,如果直接拒絕客戶,肯定是不明智的。作為技術(shù)服務(wù)人員,一定要以滿足客戶的要求為目標(biāo)。這時候,如果我們自己剛好有這樣的能力,或者借助同事、公司二線技術(shù)人員的力量來完成這些需求,肯定會給客戶留下更好的印象。