xwords/xwords4/linux/scripts/msgtrack.py
2021-03-19 12:50:32 -07:00

150 lines
5.4 KiB
Python
Executable file

#!/usr/bin/python3
import argparse, re, sys
from os import path
from enum import IntEnum
"""Given 2-4 logs from the same game (likely created by discon_ok2.py),
track all the messages they send (or don't.)
Let's track by msg (checksum). For each, track when
"""
class Message():
def __init__(self, msgID, sum, msgLen):
self.msgID = msgID
self.sum = sum
self.len = msgLen
self.sends = []
self.receives = []
self.sender = None
self.receiver = None
def __repr__(self):
str = '{}: '.format(self.key())
str += ' {} => {}'.format(self.sender, self.receiver)
firstReceipt = self.receives and self.receives[0][0] or None
str += ' sent: {}; arrived: {}'.format(self.firstSendTime(), firstReceipt)
(nReceives, nDrops) = self.countReceives();
str += '; nSents: {}; nReceives: {}; nDrops: {}'.format(len(self.sends), \
nReceives, nDrops)
str += '; nLost: {}'.format(len(self.sends) - (len(self.receives)))
return str
def addSend(self, sender, ts):
if not self.sender:
self.sender = sender
else:
assert(self.sender == sender)
self.sends.append(ts)
def addReceive(self, receiver, ts, dropped):
if not self.receiver:
self.receiver = receiver
else:
assert(self.receiver == receiver)
self.receives.append((ts, dropped))
def pruneEarlySends(self):
firstReceipt = self.receives and self.receives[0][0] or None
if firstReceipt:
while 1 < len(self.sends) and self.sends[1] < firstReceipt:
# print('{} < {}: removing from {}'.format(self.sends[1], firstReceipt, self.key()))
self.sends.pop()
def firstSendTime(self):
return self.sends[0]
def countReceives(self):
nAccepts = nDrops = 0
for tup in self.receives:
if tup[1]: nDrops += 1
else: nAccepts += 1
return (nAccepts, nDrops)
def key(self):
return Message.mkKey(self.msgID, self.sum, self.len)
@staticmethod
def mkKey(id, sum, len):
return '{:02d}:{}.{:03d}'.format(int(id), sum, len)
def errExit(msg):
print(msg, file=sys.stderr)
sys.exit(-1)
def mkParser():
parser = argparse.ArgumentParser()
parser.add_argument('--logs', nargs = '*', dest = 'LOGS',
help = 'two or more logfiles to scan')
parser.add_argument('--skip-below', dest = 'SKIP_BELOW', default = 16,
help = 'ignore messages this length or below (acks?)')
parser.add_argument('--drop-part', dest = 'DROP_PART', default = '_LOG.txt',
help = 'remove this from filename to shorten')
return parser
def getMkMessage(msgs, msgID, len, sum):
key = Message.mkKey(msgID, sum, len)
msg = msgs.get(key)
if not msg:
msg = Message(msgID, sum, len)
msgs[key] = msg
return msg
# pull everything relevant out of logfile
# <16330:7fcf30445a80> 07:54:24:953 <> sendMsg(): sending message of len 135 on cno: 674C|1 with sum 8b8b58399159afdcd54a106d3546423f
# sSendRE = re.compile('<(.*)> (\d\d:\d\d:\d\d:\d\d\d) .*sending message of len (\d+) on cno: (.*) with sum (.*)')
# <18137:7f9b3c16ba80> 08:52:56:750 <> sendMsg(): sending message on cno: C824|1: id: 1; len: 135; sum: e2eb9c89ad6062e1a1d65e9da649957f
sSendRE = re.compile('<(.*)> (\d\d:\d\d:\d\d:\d\d\d) .*sending message on cno: (.*): id: (\d+); len: (\d+); sum: (.*)')
# <16327:7f54562f4a80> 07:54:25:359 <> comms_checkIncomingStream(): got message of len 135 with sum 8b8b58399159afdcd54a106d3546423f
# sReceiveRE = re.compile('<(.*)> (\d\d:\d\d:\d\d:\d\d\d) .*got message of len (\d+) with sum (.*)')
# <23256:7fafba33fa80> 11:53:48:976 ../common/comms.c:comms_msgProcessed(): id: 0; len: 14; sum: 56ba9311510efffe43729241fad1a9b6; rejected: true
sProcessedRE = re.compile('<(.*)> (\d\d:\d\d:\d\d:\d\d\d) .*comms_msgProcessed.*: id: (\d+); len: (\d+); sum: (.+); rejected: (.+)')
def parse(logfile, shortName, msgs, skipLen):
print('parse({})'.format(shortName))
with open(logfile, 'r') as log:
for line in log:
line = line.strip()
match = sSendRE.match(line)
if match:
msgLen = int(match.group(5))
if msgLen > skipLen:
msg = getMkMessage(msgs, match.group(4), msgLen, match.group(6))
msg.addSend(shortName, match.group(2))
match = sProcessedRE.match(line)
if match:
msgLen = int(match.group(4))
if msgLen > skipLen:
msgID = match.group(3)
msg = getMkMessage(msgs, msgID, msgLen, match.group(5))
rejected = match.group(6)
msg.addReceive(shortName, match.group(2), rejected=='true')
def main():
args = mkParser().parse_args()
msgs = {}
for log in args.LOGS:
if not path.exists(log): errExit('file {} not found'.format(log))
shortName = path.basename(log).replace(args.DROP_PART, '')
parse(log, shortName, msgs, args.SKIP_BELOW)
asArr = [msgs[key] for key in msgs]
asArr.sort(key = lambda msg: msg.firstSendTime())
for msg in asArr:
# msg.pruneEarlySends()
print(msg)
##############################################################################
if __name__ == '__main__':
main()