The purpose of this cluster of functions is to tail the log file and kill/restart processes from shell (the latter is not yet implemented).
import sys
import time
import datetime
import os
import re
def read_log(f):
"""
Basically tail -f
"""
logfile = open(f)
logfile.seek(0, os.SEEK_END)
while True:
new_line = logfile.readline()
if new_line:
yield new_line
else:
time.sleep(0.1)
def find_error(line, base_time, line_time):
"""
Search for ERROR keyword in log line. Return True if found, False if not.
"""
match = re.search('.*ERROR.*', line)
if match and line_time < base_time:
return True
return False
def parse_time(line):
"""
Parse string to datetime
"""
date_regex = r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'
date_string = re.search(date_regex, line).group(0)
return datetime.datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
def increase_base_time(line_time):
"""
Return a datetime that is line_time plus one minute
"""
return line_time + datetime.timedelta(minutes=1)
def monitor(filename):
"""
Read from a log file.
For each line check if log line time is later than base comparison time.
If so, update the base time and set error count to 0.
Check for errors in line. Increment error count if any are found.
Check the total error count. If it's greater than five, restart the logged
process.
Check if process has been restarted before. If so, kill the logged process.
"""
count = 0
base_time = datetime.datetime.min
log = read_log(filename)
restarted = False
for line in log:
line_time = parse_time(line)
if line_time > base_time:
base_time = increase_base_time(line_time)
count = 0
if find_error(line, base_time, line_time):
count += 1
if count >= 5:
if restarted:
print("Kill the process") # A placeholder, sorry
else:
print("Restart the process") # Also a placeholder, sorry
count = 0
restarted = True
monitor(sys.argv[1])
There are a lot of if-statement for doing checks. I thought about making this class based, but it really doesn't make sense to do it (functions don't need to share states and it is a rather small program). Is the number of if's acceptable? How could I refactor the code to make it flow a bit better?
EDIT: As this was brought up, is it necessary that the tailing function would be non blocking? As I understand I wont be doing nothing until a line is yielded. What would be the benefits of going one way or the other?