- 支持文件删除后重新监控日志
- 支持手动编辑文件后,继续报警
- 多进程,支持监听多个日志文件,自定义定义群
- 支持自定义日志处理方法,可以发送到kafka 做日志收集等等
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:
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
@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
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