2016-05-08 15:32:37 -04:00
|
|
|
import logging
|
|
|
|
import re
|
|
|
|
from datetime import datetime
|
|
|
|
from glob import glob
|
|
|
|
|
2016-05-18 16:42:42 -04:00
|
|
|
from tsstats.client import Client, Clients
|
2016-05-08 15:32:37 -04:00
|
|
|
|
2016-05-24 16:30:16 -04:00
|
|
|
re_log_entry = re.compile('(?P<timestamp>\d{4}-\d\d-\d\d\ \d\d:\d\d:\d\d.\d+)'
|
|
|
|
'\|(?P<level>\w+)\ +\|(?P<component>\w+)'
|
|
|
|
'\|\ +(?P<sid>\d+)\|\ (?P<message>.*)')
|
2016-05-08 15:32:37 -04:00
|
|
|
re_dis_connect = re.compile(r"'(.*)'\(id:(\d*)\)")
|
|
|
|
re_disconnect_invoker = re.compile(
|
|
|
|
r'invokername=(.*)\ invokeruid=(.*)\ reasonmsg'
|
|
|
|
)
|
|
|
|
|
2016-05-25 14:08:48 -04:00
|
|
|
log_timestamp_format = '%Y-%m-%d %H:%M:%S.%f'
|
|
|
|
|
2016-05-08 15:32:37 -04:00
|
|
|
|
2016-05-10 16:50:34 -04:00
|
|
|
logger = logging.getLogger('tsstats')
|
|
|
|
|
|
|
|
|
2016-05-23 15:50:10 -04:00
|
|
|
def parse_logs(log_glob, ident_map=None):
|
2016-05-24 15:48:11 -04:00
|
|
|
clients = Clients(ident_map)
|
2016-05-23 15:50:10 -04:00
|
|
|
for log_file in sorted(log_file for log_file in glob(log_glob)):
|
2016-05-24 15:48:11 -04:00
|
|
|
clients = parse_log(log_file, ident_map, clients)
|
|
|
|
return clients
|
2016-05-23 15:50:10 -04:00
|
|
|
|
2016-05-08 15:32:37 -04:00
|
|
|
|
2016-05-24 15:48:11 -04:00
|
|
|
def parse_log(log_path, ident_map=None, clients=None):
|
|
|
|
if not clients:
|
|
|
|
clients = Clients(ident_map)
|
2016-05-23 15:50:10 -04:00
|
|
|
log_file = open(log_path)
|
|
|
|
# process lines
|
|
|
|
logger.debug('Started parsing of %s', log_file.name)
|
|
|
|
for line in log_file:
|
2016-05-24 16:30:16 -04:00
|
|
|
match = re_log_entry.match(line)
|
|
|
|
if not match:
|
|
|
|
logger.debug('No match: "%s"', line)
|
|
|
|
continue
|
|
|
|
match = match.groupdict()
|
2016-05-25 14:08:48 -04:00
|
|
|
stripped_time = datetime.strptime(match['timestamp'],
|
|
|
|
log_timestamp_format)
|
2016-05-23 15:50:10 -04:00
|
|
|
logdatetime = int((stripped_time - datetime(1970, 1, 1))
|
|
|
|
.total_seconds())
|
2016-05-24 16:30:16 -04:00
|
|
|
message = match['message']
|
|
|
|
if message.startswith('client'):
|
|
|
|
nick, clid = re_dis_connect.findall(message)[0]
|
2016-05-23 15:50:10 -04:00
|
|
|
client = clients.setdefault(clid, Client(clid, nick))
|
|
|
|
client.nick = nick # set nick to display changes
|
2016-05-24 16:30:16 -04:00
|
|
|
if message.startswith('client connected'):
|
2016-05-23 15:50:10 -04:00
|
|
|
client.connect(logdatetime)
|
2016-05-24 16:30:16 -04:00
|
|
|
elif message.startswith('client disconnected'):
|
2016-05-23 15:50:10 -04:00
|
|
|
client.disconnect(logdatetime)
|
2016-05-24 16:30:16 -04:00
|
|
|
if 'invokeruid' in message:
|
2016-05-23 15:50:10 -04:00
|
|
|
re_disconnect_data = re_disconnect_invoker.findall(
|
2016-05-24 16:30:16 -04:00
|
|
|
message)
|
2016-05-23 15:50:10 -04:00
|
|
|
invokernick, invokeruid = re_disconnect_data[0]
|
|
|
|
invoker = clients.setdefault(invokeruid,
|
|
|
|
Client(invokeruid))
|
|
|
|
invoker.nick = invokernick
|
2016-05-24 16:30:16 -04:00
|
|
|
if 'bantime' in message:
|
2016-05-23 15:50:10 -04:00
|
|
|
invoker.ban(client)
|
|
|
|
else:
|
|
|
|
invoker.kick(client)
|
|
|
|
logger.debug('Finished parsing of %s', log_file.name)
|
2016-05-08 15:32:37 -04:00
|
|
|
return clients
|