#!/usr/bin/env python3 # This script is used for building reports on message sending for E2E integration tests import re import glob import os import logging as log import datetime import statistics resultsDir = "./results/clients" def err(s): """ Helper for printing errors and exiting :param s: Error string to print """ log.error(s) exit(1) def find_files(): """Obtains list of files to search.""" if not os.path.isdir(resultsDir): err("Directory {} does not exist!".format(resultsDir)) return glob.glob('{}/client*.log'.format(resultsDir)) def main(): log.basicConfig(format='[%(levelname)s] %(asctime)s: %(message)s', level=log.INFO, datefmt='%d-%b-%y %H:%M:%S') log_files = find_files() messages_sent = dict() messages_received = dict() rounds_sent = dict() # Scan each log file for path in log_files: log.info("Scanning {}".format(path)) with open(path, 'r') as file: while True: line = file.readline() if not line: break else: if "Successfully sent to EphID" in line: # Capture message sending sent_message = re.findall('msgDigest: (.{20})\)', line)[0] log.debug("Located sent message: {}".format(sent_message)) messages_sent[sent_message] = {"sender": os.path.basename(path)} # Capture message timestamp sent_timestamp_str = re.findall('INFO (.{19}\.{0,1}\d{0,6})', line)[0] try: sent_timestamp = datetime.datetime.strptime(sent_timestamp_str, '%Y/%m/%d %H:%M:%S.%f') except ValueError: sent_timestamp = datetime.datetime.strptime(sent_timestamp_str, '%Y/%m/%d %H:%M:%S') log.debug("Located sent timestamp: {}".format(sent_timestamp)) messages_sent[sent_message]["sent"] = sent_timestamp # Capture rounds messages were sent in sent_round = re.findall('\) in round ([0-9]+)', line)[0] log.debug("Located sent round: {}".format(sent_round)) messages_sent[sent_message]["round"] = sent_round if sent_round not in rounds_sent: rounds_sent[sent_round] = False elif "Received message of type" in line or "Received AuthRequest from" in line or "Received AuthConfirm from" in line: # Capture message receiving received_message = re.findall(' msgDigest: (.{20})', line)[0] log.debug("Located received message: {}".format(received_message)) messages_received[received_message] = {"receiver": os.path.basename(path)} # Capture message timestamp received_timestamp_str = re.findall('INFO (.{19}\.{0,1}\d{0,6})', line)[0] try: received_timestamp = datetime.datetime.strptime(received_timestamp_str, '%Y/%m/%d %H:%M:%S.%f') except ValueError: received_timestamp = datetime.datetime.strptime(received_timestamp_str, '%Y/%m/%d %H:%M:%S') log.debug("Located received timestamp: {}".format(received_timestamp)) messages_received[received_message]["received"] = received_timestamp elif "Round(s)" in line: # Capture round success successful_rounds = re.findall('Round\(s\) ([0-9]+) successful', line) for successful_round in successful_rounds: log.debug("Located successful round: {}".format(successful_round)) rounds_sent[successful_round] = True # Print results num_successful = 0 # Keep track of how many messages were received successfully total_latency = datetime.timedelta() # Keep track of the total message latencies to calculate a mean latencies = [] # Keep track of each message's latency in order to calculate a median for msgDigest, senderDict in messages_sent.items(): if msgDigest in messages_received: num_successful += 1 time_sent = messages_sent[msgDigest]["sent"] time_received = messages_received[msgDigest]["received"] message_latency = time_received - time_sent latencies.append(message_latency) total_latency += message_latency log.info("Message {} sent by {} on round {} was received after {}".format(msgDigest, senderDict["sender"], senderDict["round"], message_latency)) log.info("\tSent: {}, Received: {}".format(time_sent, time_received)) else: log.error("Message {} sent by {} on round {} was NOT received".format(msgDigest, senderDict["sender"], senderDict["round"])) for round_id, was_successful in rounds_sent.items(): if was_successful: log.debug("Round {} was successful".format(round_id)) else: log.warning("Round {} was NOT confirmed successful, messages may have been dropped".format(round_id)) log.info("{}/{} messages received successfully!".format(num_successful, len(messages_sent))) log.info("\tMean: {}, Median: {}".format(total_latency / num_successful, statistics.median(latencies))) if __name__ == "__main__": main() # INFO 2021/05/07 15:25:14 Received message of type None from ouQD89J4YdmlzcAkdjjgVa49SANsi1JL5JLVjrWjZtED, msgDigest: inDu2/zmGD+vtCMVHXdg # INFO 2021/05/19 15:29:09 Received 2 messages in Round 65253 for -7 (AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD) # INFO 2021/05/07 15:25:03 Sending to EphID -15 (ouQD89J4YdmlzcAkdjjgVa49SANsi1JL5JLVjrWjZtED) on round 797, (msgDigest: YTuZd9p8759GBMNz8Dw7, ecrMsgDigest: JshXEJ4WTBsbRFWQDBYq) via gateway sAtfNaRd1jePhfRrcDgZgHHAAmhZ/F0jDbD4JgAfkMsB # INFO 2021/05/07 15:25:04 Successfully sent to EphID -15 (source: ouQD89J4YdmlzcAkdjjgVa49SANsi1JL5JLVjrWjZtED) in round 797 (msgDigest: YTuZd9p8759GBMNz8Dw7) # INFO 2021/05/07 15:25:04 Result of sending message "Hello from Rick42, with E2E Encryption" to "ouQD89J4YdmlzcAkdjjgVa49SANsi1JL5JLVjrWjZtED": # INFO 2021/05/07 15:25:04 Round(s) 795 successful