"""A repeatable process for measuring analytics latency. Process - 1. Create new tab in Google Chrome browser. 2. Open DevTools to track this page. 3. Enable Preserve log option if you want to save data for several pages in one file. 4. Start recording in DevTools. 5. Load page/pages using links. https://workstation.theorchard.com/analytics/engagement https://workstation.theorchard.com/analytics/audience https://workstation.theorchard.com/analytics/index https://workstation.theorchard.com/analytics/overview https://workstation.qaorch.com/analytics/comparison?ids=USJMZ1800051&ids=USJMZ1800057 This is very important especially for getting correct results from one file for several pages. 6. Click Export Har in DevTools and save a file. 7. Launch script python measure.py path --result filename.csv path - can be directory with multiple .har files --result filename.csv - The name of the result file(default result.csv). An example of result file https://docs.google.com/spreadsheets/d/14eit5nCMqQ-siMn2F6srV0t5-EOQAEjtbQ0_A_jyUd4/edit#gid=0 """ import argparse from collections import defaultdict from collections import namedtuple import csv import json import os fieldnames = [ 'filename', 'date', 'page', 'type', 'url', 'time', 'onContentLoad', 'onLoad'] RequestInfo = namedtuple('RequestInfo', 'type url time') def get_request_type(url): """Analyze url and return type of request.""" if '/images/'in url or url.endswith('js') or url.endswith('css'): return 'frontend' elif url.startswith('https://workstation.theorchard.com'): return 'api' return 'other' def parse_file(filename, pages): """Analyze .har file with json data from DevTools.""" with open(filename) as json_file: try: data = json.load(json_file) # save overall information about each page in the file for page in data['log']['pages']: pages[page['id']] = { 'title': page['title'], 'onContentLoad': page['pageTimings']['onContentLoad'], 'onLoad': page['pageTimings']['onLoad'], 'date': page['startedDateTime'], 'requests': []} # save information about each request in the file for d in data['log']['entries']: r = RequestInfo( type=get_request_type(d['request']['url']), url=d['request']['url'], time=d['time']) # relate a request with particular page try: pages[d['pageref']]['requests'].append(r) except KeyError: print('url {} doesn\'t have pageref'.format(r.url)) print('File {file} was successfully loaded') except Exception as err: print('An error occurred while loading {file} {error}'.format( file=filename, error=err)) def parse_data(path): """Parse one file or all files in the directory.""" result = defaultdict(dict) # try to analyze all files in the directory if path is a folder if os.path.isdir(path): for file in os.listdir(path): parse_file(os.path.join(path, file), result[file]) elif os.path.isfile(path): filename = os.path.basename(path) parse_file(path, result[filename]) return result def write_results(filename, pages): """Save results in csv file.""" with open(filename, 'w', newline='') as csvfile: writer = csv.writer(csvfile) writer.writerow(fieldnames) for filename, data in pages.items(): for page, info in data.items(): for r in sorted( info['requests'], key=lambda x: (x.type, x.url)): if r.url == info['title']: onContentLoad = info['onContentLoad'] onLoad = info['onLoad'] else: onContentLoad, onLoad = None, None row = [ filename, info['date'], info['title'], r.type, r.url, r.time, onContentLoad, onLoad] writer.writerow(row) if __name__ == '__main__': parser = argparse.ArgumentParser( description='Collect information about latency') parser.add_argument( 'path', help='name of the directory or filename with data to analyze') parser.add_argument( '--result', help='The result file name', default='result.csv') args = parser.parse_args() pages = parse_data(args.path) write_results(args.result, pages)