conference-stats/jitsi-log.py

209 lines
6.0 KiB
Python
Executable File

#!/bin/env python3
#
import re
import sys
import threading
from time import sleep
from os.path import basename
from datetime import datetime
from argparse import ArgumentParser
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse
try:
from sh import tail
except ImportError as e:
print('[Error] Please install sh via pip! {}'.format(e))
sys.exit(1)
# active room dictionary
roomList = {}
# @see https://regex101.com/r/R1B1OL/1
regex = r"(Jicofo)\s(\d+-\d+-\d+)\s(\d+\:\d+\:\d+\.\d+)\s(\w+):\s\[(\d+)\]\s(.*)\(\)\s(.*)"
prog = re.compile(regex)
##
# new jitsi room
room_regex = r"(^Joining\sthe\sroom):(.*)"
room = re.compile(room_regex)
# disposed room
disposed_regex = r"^Disposed\sconference\sfor\sroom\:\s(.*)@(.*)\sconference\scount:\s(\d+)"
disposed = re.compile(disposed_regex)
##
# get the room owner
owner_regex = r"Granted\sowner\sto\s([a-z0-9-]+)\@(.*)\/(.*)"
owner = re.compile(owner_regex)
# get member for room
member_regex = r"^Member\s(.*)@(.*)\/(.*)\sjoined."
member = re.compile(member_regex)
class MeetingRoom():
"""
represent a Jitsi Meetingroom
jid: eg room@conference.meet.leinelab.org
ctime: eg 2020-06-01 12:32:02 ..
"""
def __init__(self, jid, ctime):
self.jid = jid
self.ctime = ctime
self.members = []
def setOwner(self, name):
self.owner = name
def getOwner(self):
if hasattr(self, 'owner'):
return self.owner
else:
return None
def addMember(self, name):
self.members.append(name)
def getMembers(self):
return self.members
def __str__(self):
return '{}: {}'.format(self.jid, self.owner)
class logThread(threading.Thread):
def __init__(self, threadID, name, filename):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.filename = filename
def run(self):
while True:
getLogMsg(self.filename)
sleep(5)
class MyServer(BaseHTTPRequestHandler):
def do_GET(self):
if basename(self.path) in roomList:
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
response_string = bytes(basename(self.path)
+ '|'
+ str(roomList[basename(self.path)].ctime)
+ '|'
+ str(len(roomList[basename(self.path)].members))
+ '|', "utf-8")
self.wfile.write(response_string)
else:
self.send_response(404)
self.send_header("Content-type", "text/plain")
self.end_headers()
def getRoomName(jid):
return jid.split("@")[0].strip()
def mkDatetime(str_date, str_time):
return datetime.fromisoformat('{} {}'.format(str_date, str_time))
def process_line(line):
"""
process a logfile line, using global object and vars
globals: prog, disposed, owner, member, roomList
line: string
"""
erg = prog.match(line)
if erg:
# detect room creation
new_room = room.match(erg.group(7))
if new_room:
room_name = getRoomName(new_room.group(2))
room_date = mkDatetime(erg.group(2), erg.group(3))
print('{} {}'.format(room_date, room_name))
currentRoom = MeetingRoom(room_name, room_date)
if room_name in roomList:
# delete old room and recreate it
del roomList[room_name]
roomList[room_name] = currentRoom
else:
roomList[room_name] = currentRoom
disposed_room = disposed.match(erg.group(7))
if disposed_room:
room_name = disposed_room.group(1)
print('-> room disposed: {}'.format(room_name))
if room_name in roomList:
del roomList[room_name]
owner_match = owner.match(erg.group(7))
if owner_match:
room_name = owner_match.group(1).strip()
room_owner = owner_match.group(3).strip()
# print('{}: {}'.format(room_name, room_owner))
if room_name in roomList:
roomList[room_name].setOwner(room_owner)
member_match = member.match(erg.group(7))
if member_match:
room_name = member_match.group(1).strip()
room_member = member_match.group(3).strip()
print('--> {}: {}'.format(room_name, room_member))
if room_name in roomList:
roomList[room_name].addMember(room_member)
def getLogMsg(logfile):
"""
get log messages and commit it to process_line
used pytail module
"""
# for line in Pygtail(logfile, full_lines=True):
# process_line(line)
for line in tail("-f", logfile, _iter=True):
process_line(line)
if __name__ == '__main__':
# start cmdline processing
parser = ArgumentParser(description='Jitsi Meet Conference Stats')
parser.add_argument('--log', '-l',
help='full path to jicofo logfile eg.' +
' /var/log/jitsi/jicofo.log')
parser.add_argument('--verbose', '-v',
help='be verbose eg. for debugging',
action='store_true')
parser.add_argument('--logwatch', '-w',
help='run as logwatch module, ' +
' dont start the webserver and only run once')
args = parser.parse_args()
if args.log:
try:
loggerThread = logThread(1, "Thread-Logger", args.log)
loggerThread.start()
except:
print('Error: unable to start threads')
hostName = 'localhost'
serverPort = 9999
webServer = HTTPServer((hostName, serverPort), MyServer)
try:
print("Server started http://%s:%s" % (hostName, serverPort))
webServer.serve_forever()
except:
pass