def get_selector(query): """Returns a callable object that returns true when `query` matches dictionary. Args: query: An object that specifies the query. It can be one of the following: - A string: - Load JSON object from this string if possible ELSE - Treat it as a file name and load JSON objects from there. The parsed/loaded object must be either dict or list. - A list of dict. Wrap it into a function that calls match method of a DictUtils class. - Callable object. Return as is. Returns: Callable object. """ # If it's a string, assume it's a JSON parsable string and if not - assume it's a JSON file name. if isinstance(query, Six.string_types): try: query = json.loads(query) except ValueError: query = IOUtils.read_json(query) selector = query # If it's a list of dict, wrap it into a function. if isinstance(query, (list, dict)): def dict_matcher(bench): return DictUtils.match(bench, query, policy='strict') selector = dict_matcher # Here, it must be a callable object. if not callable(selector): raise ValueError("Invalid type of object that holds parameters (%s)" % type(selector)) return selector
def load(inputs, **kwargs): """Load benchmark data (parsed from log files) from a JSON file. A file name is a JSON file that contains object with 'data' field. This field is a list with dictionaries, each dictionary contains parameters for one benchmark: {"data":[{...}, {...}, {...}]} Args: inputs (str): File name of a JSON (*.json) or a compressed JSON (.json.gz) file. Returns: Instance of this class. """ is_json_file = IOUtils.is_json_file(inputs) if not is_json_file and isinstance(inputs, list) and len(inputs) == 1: is_json_file = IOUtils.is_json_file(inputs[0]) inputs = inputs[0] if is_json_file else inputs if is_json_file: benchmarks = IOUtils.read_json(inputs, check_extension=True) if 'data' not in benchmarks: benchmarks = {'data': []} print("[WARNING]: No benchmark data found in '{}'".format( inputs)) return BenchData(benchmarks['data'], create_copy=False) # is_csv_file = IOUtils.is_csv_file(inputs) if not is_csv_file and isinstance(inputs, list) and len(inputs) == 1: is_csv_file = IOUtils.is_csv_file(inputs[0]) inputs = inputs[0] if is_csv_file else inputs if is_csv_file: with OpenFile(inputs, 'r') as fobj: reader = csv.DictReader(fobj) benchmarks = list(reader) return BenchData(benchmarks, create_copy=False) # is_compressed_tarball = IOUtils.is_compressed_tarball(inputs) if not is_compressed_tarball and isinstance(inputs, list) and len(inputs) == 1: is_compressed_tarball = IOUtils.is_json_file(inputs[0]) inputs = inputs[0] if is_compressed_tarball else inputs if is_compressed_tarball: benchmarks = [] with tarfile.open(inputs, "r:gz") as archive: for member in archive.getmembers(): if member.isfile() and member.name.endswith('.log'): log_file = archive.extractfile(member) if log_file is not None: parameters = {} DictUtils.add( parameters, log_file, pattern= '[ \t]*__(.+?(?=__[ \t]*[=]))__[ \t]*=(.+)', must_match=False, ignore_errors=True) benchmarks.append(parameters) return BenchData(benchmarks, create_copy=False) # return BenchData.parse(inputs, **kwargs)
def load_data(**kwargs): is_dir = os.path.isdir(kwargs['input']) is_file = os.path.isfile(kwargs['input']) is_log_file = is_file and kwargs['input'].endswith('.log') is_json_file = is_file and (kwargs['input'].endswith('.json') or kwargs['input'].endswith('.json.gz')) if is_dir or is_log_file: files = IOUtils.find_files(config['input'], "*.log", config['recursive']) benchmarks, failed_benchmarks = LogParser.parse_log_files(files) benchmarks.extend(failed_benchmarks) elif is_json_file: benchmarks = IOUtils.read_json(kwargs['input']) benchmarks = benchmarks['data'] else: raise ValueError("Invalid input descriptor: {}".format( kwargs['input'])) return benchmarks
def main(): """Entry point when invoking this scrip from a command line.""" parser = argparse.ArgumentParser() parser.add_argument('inputs', nargs='*', help='Log directory or a JSON file') parser.add_argument( '--recursive', required=False, default=False, action='store_true', help='If input is folder, scan it recursively for log files.') parser.add_argument('--xparam', type=str, required=True, default=None, help='A parameter that is associated with x axis.') parser.add_argument('--yparam', type=str, required=True, default=None, help='A parameter that is associated with y axis.') parser.add_argument('--series', type=str, required=True, default=None, help='A json array with filters for series.') parser.add_argument( '--aggregation', type=str, required=True, default="avg", help= 'In case of multiple matches, use this to aggregate values (min, max, avg)' ) parser.add_argument('--chart_file', '--chart-file', type=str, required=False, default=None, help='If present, write chart into this file.') parser.add_argument( '--series_file', '--series-file', type=str, required=False, default=None, help='If present, write series JSON data into this file.') parser.add_argument( '--chart_opts', '--chart-opts', type=str, required=False, default=None, help='If present, a json object specifying chart options.') parser.add_argument('--chart_type', '--chart-type', type=str, required=False, default='line', help='Type of a chart ("line" or "bar").') parser.add_argument( '--baseline_xvalue', '--baseline-xvalue', type=str, required=False, default=None, help= "A value that's used to normalize one series. Useful to plot speedup charts." ) parser.add_argument( '--baseline_series', '--baseline-series', type=int, required=False, default=None, help="An index of a baseline series to use to normalize all series.") args = parser.parse_args() if len(args.inputs) == 0: raise ValueError("Must be at least one input ('--input')") # Parse log files and load benchmark data logfiles = [] # Original raw log files with benchmark data benchmarks = [] # Parsed benchmarks for input_path in args.inputs: if os.path.isdir(input_path): logfiles.extend( IOUtils.find_files(input_path, "*.log", args.recursive)) elif os.path.isfile(input_path) and input_path.endswith( ('.json', '.json.gz')): file_benchmarks = IOUtils.read_json(input_path) if 'data' in file_benchmarks and isinstance( file_benchmarks['data'], list): benchmarks.extend(file_benchmarks['data']) else: logging.warn("Cannot parse file (%s). Invalid content.", input_path) else: logging.warn("Cannot parse file (%s). Unknown extension. ", input_path) if len(logfiles) > 0: benchmarks.extend(LogParser.parse_log_files(logfiles)) else: logging.warn("No input log files have been found") if len(benchmarks) == 0: raise ValueError("No benchmarks have been loaded.") # Build data for series chart_data = SeriesBuilder.build(benchmarks, args) # Write it if args.series_file: DictUtils.dump_json_to_file(chart_data, args) # Plot it if args.chart_file: SeriesBuilder.plot(chart_data, args)