zabbix 日誌監控(自定義插件開發)

拖了很久終於下定決心來寫這篇博客,希望真的能對有需要的朋友有所幫助

    先說一下背景,有服務跑的地方就有監控,有監控的地方往往少不了zabbix的優美身影,搞監控我大膽猜一下,朋友們很多都有監控日誌的需求,比如老闆讓你監控一下服務的 "ERROR"  日誌,監控一下java 的 NPE,Full GC 等等

    zabbix 內部自帶了日誌的監控模塊,但是我在使用的時候發現確實很不好用(可能是我不會用

先看一下效果, 下面是監控java 服務 Full GC 的場景,配置好之後,就可以查看數據,在latest data 中可以看到獲取到的日誌信息

選擇你關聯配置了日誌監控的主機,查看數據

zabbix 日誌監控(自定義插件開發)

其中None 爲沒匹配到關鍵詞的輸出,轉換爲None 來輸出是爲了簡化數據的輸出 

zabbix 日誌監控(自定義插件開發)

輸出還有一種情況下是 Noline , 不要慌,這種情況是因爲兩次採集的間隔時間段沒有新的記錄,使用時間戳來解決會重複讀取記錄而誤報的問題 zabbix 日誌監控(自定義插件開發)

如何配置

1、配置模板

和配置其他item 沒有太大的區別

Key :這裏 需要配置的4個參數依次爲:

logpath : 日誌的路徑

50:表示一次讀取的行數,可以根據自己日誌刷新頻率適當設置

'stringkey' : 要檢索的字符串

60 : 執行腳本的間隔 (和 Update interval 的必須值一致)

Type of information :配置爲 log 類型

zabbix 日誌監控(自定義插件開發)

trigger 的配置,可以根據自己的需求來定義告警閾值

Name: 根據場景 設置容易識別的醒目的內容

Severity:  告警的級別

Expression: 如圖 配置,我這裏使用了count, 表示連續8次檢測, 檢測到關鍵詞的次數大於3次就告警

zabbix 日誌監控(自定義插件開發)

2、模本配置完了,咱們搞一下插件

 在你的agent 的 bin 目錄先增加 monitorlogs.py 腳本(注意增加執行權限)


#!/usr/bin/env  python
# *_* coding:utf8 *_*

__author__ = 'xbzy007'

import subprocess, os, sys
import time, datetime
import re
import traceback

class FindOut(object):
    def __init__(self, logfile, linenums, stringkeys, interval):
        self.logfile = logfile
        self.linenums = linenums
        self.stringkeys = stringkeys
        self.interval = interval
        self.logtype_a = '^([0-9]+\-){2}[0-9]+T[0-9]*'
        self.logtype_b = '^([0-9]+\-){2}[0-9]+ [0-9]*'

    def getlogtimetype(self, loglinelist):
        logtype_tag = ''
        for i in range(0,len(loglinelist),1):
            line = loglinelist[i]
            if re.match(self.logtype_a, line, flags=0):
                logtype_tag = self.logtype_a
            elif re.match(self.logtype_b, line, flags=0):
                logtype_tag = self.logtype_b

        return logtype_tag

    def filterthelogfile(self):
        #if not os.path.exists(self.logfile):
        #    print "{0} not exist".format(self.logfile)
        #    sys.exit(0)
        match_logname = self.logfile
        logdir = os.path.abspath(os.path.dirname(self.logfile) + os.path.sep + ".")
        logfilenamelist = []
        lastlogfile = ''
        lastmtime = 338054400.0
        for tfile in os.listdir(logdir):  
            filepath = os.path.join(logdir, tfile)  
            matchx = re.match(match_logname, filepath, flags=0)
            if matchx :
                if os.path.isfile(filepath):  
                    logfilenamelist.append(filepath)
        if len(logfilenamelist):
            for onelogfile in logfilenamelist:
                filemtime = os.path.getmtime(onelogfile)
                if filemtime > lastmtime:
                    lastmtime = filemtime
                    lastlogfile = onelogfile

        if lastlogfile:
            return lastlogfile
        else:
            print "not found newest logfile"
            return None

    def findoutstring(self):
        logfile = self.filterthelogfile()
        if logfile :
            p = subprocess.Popen("tail -%s %s" % (self.linenums, logfile), \
                                env=None, shell=True, stdout=subprocess.PIPE)
            out, err = p.communicate()
            p.wait()
            if (p.returncode == 0):
                res = out.strip('\n')
            else:
                print "open  %s Failed" % logfile
                sys.exit(1)
        else :
            print "%s not found" % logfile
            sys.exit(2)

        ####  標記值,標記在給定的時間段是否有記錄
        tags = 0
        curtimestamp = time.time()
        getlineslist = res.split('\n')
        logtype = self.getlogtimetype(getlineslist)
        if logtype == self.logtype_b :
            ######  查找符合時間區域的第一條記錄
            for i in range(0,len(getlineslist),1):
                line = getlineslist[i]
                var = line.strip()
                try:
                    strtime = var.split()[0] + ' ' +var.split()[1]
                    strtime = strtime.split(',')[0]
                    timeArray = time.strptime(strtime, "%Y-%m-%d %H:%M:%S")
                    timestamp = time.mktime(timeArray)
                    contrasttime = int(curtimestamp) - self.interval
                    if int(timestamp) > contrasttime :
                        tags += 1
                        break
                except :
                    #traceback.print_exc()
                    continue
        elif logtype == self.logtype_a :

            ######  查找符合時間區域的第一條記錄
            for i in range(0,len(getlineslist),1):
                line = getlineslist[i]
                var = line.strip()
                try:
                    strtime = var.split()[0]
                    strtime = strtime.split('.')[0]
                    strtime = strtime.replace('T', ' ')
                    timeArray = time.strptime(strtime, "%Y-%m-%d %H:%M:%S")
                    timestamp = time.mktime(timeArray)
                    contrasttime = int(curtimestamp) - self.interval
                    if int(timestamp) > contrasttime :
                        tags += 1
                        break
                except :
                    #traceback.print_exc()
                    continue
        else:
            print  'logtype can not be analysis'
            sys.exit(4)
        ###########  在符合的記錄中查找 關鍵字,起始位置爲上一步查到的標記位i 
        if tags:
            for j in range(i, len(getlineslist), 1):
                line = getlineslist[j].strip()
                res = re.search(self.stringkeys, getlineslist[j], flags=0)
                if res:
                    line = line + ' logsmonitor'
                    return line
            return None  ###沒有找到有關鍵字的記錄
        else :
            return 'Noline' ### 在規定的時間段沒有找到符合的記錄(老的數據)

if __name__ == '__main__' :
    if len(sys.argv) < 4 :
        print "need 4 args: [ logfile ] [ readline nums ] [ stringkeys ] [ interval time ]" 
        sys.exit(-1)
    logfile= sys.argv[1]
    getlinenums = int(sys.argv[2])
    if getlinenums > 1000 :
        getlinenums = 1000
    stringkeys = sys.argv[3]
    interval = int(sys.argv[4])
    #x = FindOut(logfile, , 'to active state', interval)
    x = FindOut(logfile, getlinenums, stringkeys, interval)
    res = x.findoutstring()
    print res

在你的agent 的 etc/zabbix_agentd.conf.d/ 下面增加插件對應的配置文件:UserParametermonitorlogs.conf

UserParameter=mlogs[*],/usr/local/zmonitor/bin/monitorlogs.py "$1" "$2" "$3" "$4"

然後重啓 agent 

最後給你需要監控日誌的主機關聯上模板就可以完成日誌的監控, 是不是想實戰驗證一把,希望能解決你同樣的困擾,讓世上沒有難搞的監控
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章