简易报警监控 tail -f 最后一条日志,通知到钉钉

  1. 支持文件删除后重新监控日志
  2. 支持手动编辑文件后,继续报警
  3. 多进程,支持监听多个日志文件,自定义定义群
  4. 支持自定义日志处理方法,可以发送到kafka 做日志收集等等
# coding=utf-8
import json
import os
import sys
import time
from multiprocessing import Process, Queue, Pool

import requests


class Tail(object):
    def __init__(self, file_list):
        self.fileList = file_list
        self.author = "banxia"
        self.__callBack = sys.stdout.write

    def logger(self, message="", type="error"):
        error_log = "./" + type + ".log"
        if message:
            with open(error_log, 'a+') as f:
                f.write(json.dumps({'message': str(message)}))
                f.write("\n")

    def register_callback(self, func):
        self.__callBack = func

    def main_tail(self, file_name, config):
        last_position = 0
        while True:
            last_position = self.__tail(file_name, last_position, config)
            time.sleep(0.1)

    def __tail(self, file_name, last_position=0, config=None):
        count = 0
        if not os.path.isfile(file_name):
            return 0

        with open(file_name, 'r') as f:
            if last_position == 0:
                f.seek(0, 2)
            else:
                f.seek(last_position)
            while True:
                position = f.tell()
                content = f.readline()
                if not content:
                    if count > 60:
                        # print("重新读取文件:" + str(count))
                        return position
                    time.sleep(0.1)
                    count += 1
                else:
                    try:
                        self.__callBack(content, config)
                    except Exception as e:
                        print(e)
                        self.logger(str(e))

    def run(self):
        pool = Pool(len(self.fileList))
        for config in self.fileList:
            if 'path' not in config:
                continue
            filename = config.get('path')
            func = self.main_tail
            pool.apply_async(func, (filename, config,))
        pool.close()
        pool.join()


class httpclient(object):
    @staticmethod
    def get(url, params=None):
        res = requests.get(url, params)
        return res
        # return res.text.encode('utf-8').decode('unicode_escape')

    @staticmethod
    def postJosn(url, params=None, hds={}):
        hds['Content-Type'] = 'application/json'
        params = json.dumps(params)
        res = requests.post(url, params, headers=hds)
        # return res.text.encode('utf-8').decode('unicode_escape')
        return res


def ding_push(content, config):
    token = config.get('token')
    url = "https://oapi.dingtalk.com/robot/send?access_token=" + token
    msg = {
        "msgtype": "text",
        "text": {
            "content": "通知"
        },
        "at": {
            "atMobiles": [
            ],
            "isAtAll": 'true'
        }
    }
    msg['text']['content'] = "【通知】" + config.get('path') + ":\n" + content
    ret = httpclient.postJosn(url, msg)
    ret_json = ret.json()
    if ret_json['errcode'] != 0:
        print(ret.text)


if __name__ == '__main__':
    file_list = [
        {'path': 'test.log', 'token': '1'},
        {'path': 'test1.log', 'token': '2'}
    ]
    tail = Tail(file_list)
    tail.register_callback(ding_push)
    tail.run()

 运行: python3 tail.py
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值