GitLab is used only for code review, issue tracking and project management. Canonical locations for source code are still https://gitweb.torproject.org/ https://git.torproject.org/ and git-rw.torproject.org.

Commit 053da92c authored by Karsten Loesing's avatar Karsten Loesing

Also accept a directory in `onionperf filter -i`.

And clarify that we're leaving statistics unchanged as part of the
filtering.
parent d9f8b8fe
# Changes in version 0.7 - 2020-??-?? # Changes in version 0.7 - 2020-??-??
- Add a new `onionperf filter` mode that takes an OnionPerf analysis - Add a new `onionperf filter` mode that takes an OnionPerf analysis
results file as input, applies filters, and produces a new results file or directory as input, applies filters, and produces
OnionPerf analysis results file as output. new OnionPerf analysis results file(s) as output.
# Changes in version 0.6 - 2020-08-08 # Changes in version 0.6 - 2020-08-08
......
...@@ -15,9 +15,6 @@ class Filtering(object): ...@@ -15,9 +15,6 @@ class Filtering(object):
self.fingerprints_to_exclude = None self.fingerprints_to_exclude = None
self.fingerprint_pattern = re.compile("\$?([0-9a-fA-F]{40})") self.fingerprint_pattern = re.compile("\$?([0-9a-fA-F]{40})")
def read_input(self, path):
self.analysis = OPAnalysis.load(filename=path)
def include_fingerprints(self, path): def include_fingerprints(self, path):
self.fingerprints_to_include = [] self.fingerprints_to_include = []
with open(path, 'rt') as f: with open(path, 'rt') as f:
...@@ -36,7 +33,8 @@ class Filtering(object): ...@@ -36,7 +33,8 @@ class Filtering(object):
fingerprint = fingerprint_match.group(1).upper() fingerprint = fingerprint_match.group(1).upper()
self.fingerprints_to_exclude.append(fingerprint) self.fingerprints_to_exclude.append(fingerprint)
def apply_filters(self): def apply_filters(self, input_path, output_dir, output_file):
self.analysis = OPAnalysis.load(filename=input_path)
if self.fingerprints_to_include is None and self.fingerprints_to_exclude is None: if self.fingerprints_to_include is None and self.fingerprints_to_exclude is None:
return return
for source in self.analysis.get_nodes(): for source in self.analysis.get_nodes():
...@@ -94,7 +92,5 @@ class Filtering(object): ...@@ -94,7 +92,5 @@ class Filtering(object):
retained_tgen_transfers[transfer_id] = transfer_data retained_tgen_transfers[transfer_id] = transfer_data
self.analysis.set_tgen_streams(source, retained_tgen_streams) self.analysis.set_tgen_streams(source, retained_tgen_streams)
self.analysis.set_tgen_transfers(source, retained_tgen_transfers) self.analysis.set_tgen_transfers(source, retained_tgen_transfers)
self.analysis.save(filename=output_file, output_prefix=output_dir)
def write_output(self, path):
self.analysis.save(filename=path)
...@@ -76,8 +76,11 @@ Analyze Tor and TGen output ...@@ -76,8 +76,11 @@ Analyze Tor and TGen output
""" """
DESC_FILTER = """ DESC_FILTER = """
Takes an OnionPerf analysis results file as input, applies filters, Takes an OnionPerf analysis results file or directory as input, applies filters,
and produces a new OnionPerf analysis results file as output. and produces new OnionPerf analysis results file(s) as output.
This subcommand only filters measurements in `data/[source]/tgen/transfers`
and `data/[source]/tgen/streams`, but leaves any summaries unchanged.
""" """
HELP_FILTER = """ HELP_FILTER = """
Filter OnionPerf analysis results Filter OnionPerf analysis results
...@@ -295,7 +298,8 @@ files generated by this script will be written""", ...@@ -295,7 +298,8 @@ files generated by this script will be written""",
filter_parser.set_defaults(func=filter, formatter_class=my_formatter_class) filter_parser.set_defaults(func=filter, formatter_class=my_formatter_class)
filter_parser.add_argument('-i', '--input', filter_parser.add_argument('-i', '--input',
help="""read the OnionPerf analysis results at PATH as input""", help="""a file or directory PATH from which OnionPerf analysis results
files are read""",
metavar="PATH", required="True", metavar="PATH", required="True",
action="store", dest="input") action="store", dest="input")
...@@ -314,8 +318,8 @@ files generated by this script will be written""", ...@@ -314,8 +318,8 @@ files generated by this script will be written""",
default=None) default=None)
filter_parser.add_argument('-o', '--output', filter_parser.add_argument('-o', '--output',
help="""write the filtered output OnionPerf analysis results file to help="""a file or directory PATH where filtered output OnionPerf
PATH""", analysis results files are written""",
metavar="PATH", required="True", metavar="PATH", required="True",
action="store", dest="output") action="store", dest="output")
...@@ -439,17 +443,26 @@ def analyze(args): ...@@ -439,17 +443,26 @@ def analyze(args):
def filter(args): def filter(args):
from onionperf.filtering import Filtering from onionperf.filtering import Filtering
p = os.path.abspath(os.path.expanduser(args.input)) input_path = os.path.abspath(os.path.expanduser(args.input))
if not os.path.exists(p): if not os.path.exists(input_path):
raise argparse.ArgumentTypeError("path '%s' does not exist" % args.input) raise argparse.ArgumentTypeError("input path '%s' does not exist" % args.input)
output_path = os.path.abspath(os.path.expanduser(args.output))
if os.path.exists(output_path):
raise argparse.ArgumentTypeError("output path '%s' already exists" % args.output)
filtering = Filtering() filtering = Filtering()
filtering.read_input(args.input)
if args.include_fingerprints is not None: if args.include_fingerprints is not None:
filtering.include_fingerprints(args.include_fingerprints) filtering.include_fingerprints(args.include_fingerprints)
if args.exclude_fingerprints is not None: if args.exclude_fingerprints is not None:
filtering.exclude_fingerprints(args.exclude_fingerprints) filtering.exclude_fingerprints(args.exclude_fingerprints)
filtering.apply_filters() if os.path.isfile(input_path):
filtering.write_output(args.output) output_dir, output_file = os.path.split(output_path)
filtering.apply_filters(input_path=input_path, output_dir=output_dir, output_file=output_file)
else:
for dirpath, dirnames, filenames in os.walk(input_path):
for filename in filenames:
input_file = os.path.join(dirpath, filename)
output_dir = os.path.join(output_path, os.path.relpath(dirpath, input_path))
filtering.apply_filters(input_path=input_file, output_dir=output_dir, output_file=filename)
def visualize(args): def visualize(args):
from onionperf.visualization import TGenVisualization from onionperf.visualization import TGenVisualization
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment