]> git.treefish.org Git - logalert.git/blob - src/logalert.py
c8eed192577ef7bba95265168eef10ca6eeadac7
[logalert.git] / src / logalert.py
1 #!/usr/bin/env python3
2
3 import argparse
4 import logging
5 import time
6
7 import misc
8
9 MAX_LINES = 10
10 ALERT_INTERVAL = 86400
11
12 parser = argparse.ArgumentParser(description='Alert on excessive number of error log lines.')
13 parser.add_argument('logfile', type=str, help='logfile to be watched')
14 parser.add_argument('handler', type=str,
15                     help='alert will be delivered to standard input of handler')
16 parser.add_argument('-s', '--interval-size', type=int, default=600, dest='interval_size',
17                     help='sample interval size in seconds (default: 600)')
18 parser.add_argument('-n', '--num-intervals', type=int, default=6, dest='num_intervals',
19                     help='number of intervals to keep in history (default: 6)')
20 parser.add_argument('-l', '--log-level', type=str, default='INFO', dest='log_lvl',
21                     choices=['DEBUG', 'INFO', 'WARNING'], help='select log level')
22
23 args = parser.parse_args()
24
25 logging.basicConfig(format='[%(asctime)s] %(levelname)s: %(message)s',
26                     level=logging.getLevelName(args.log_lvl),
27                     datefmt='%m/%d/%Y %H:%M:%S')
28
29 kept_times = []
30 lines = []
31 last_slot_time = None
32 error_state = False
33 last_alert_time = 0
34
35 for line in misc.follow_file(args.logfile):
36     time_now = time.time()
37     slot_now = int(time_now) // args.interval_size
38
39     if line != None:
40         if not last_slot_time or slot_now > last_slot_time:
41             kept_times.append(slot_now)
42             last_slot_time = slot_now
43         lines.append(line)
44         if len(lines) > MAX_LINES:
45             lines.pop(0)
46
47     while len(kept_times) > 0 and \
48           kept_times[0] <= slot_now - (args.num_intervals + 1):
49         kept_times.pop(0)
50
51     intervals = [False] * (args.num_intervals + 1)
52     for kept_time in kept_times:
53         intervals[slot_now - kept_time] = True
54
55     logging.debug(intervals)
56
57     if not False in intervals[1:]:
58         if not error_state or time_now - last_alert_time > ALERT_INTERVAL:
59             last_alert_time = time_now
60             misc.feed_handler( args.handler,
61                                misc.create_msg("Log Alert",
62                                                "&#9760;",
63                                                args.logfile,
64                                                "Number of errors exceeded!",
65                                                lines) )
66         if not error_state:
67             logging.warning("Entering error state!")
68             error_state = True
69
70     else:
71         if error_state:
72             logging.info("Leaving error state.")
73             error_state = False