[ooni-probe/master] Work on the Director

commit 8ca9928040168b71dbf41ed092c30def4a129e48 Author: Arturo Filastò <art@fuffa.org> Date: Sun Jan 13 14:00:00 2013 +0100 Work on the Director Provide glue between Director, Tasks and Managers Director will keep track of the failure rate of measurements --- ooni/director.py | 89 +++++++++++++++++++++++++++++++++++++++++++----------- ooni/managers.py | 29 ++++++++++-------- ooni/reporter.py | 36 ++++++++++++++++++++++ ooni/tasks.py | 7 ++++ 4 files changed, 130 insertions(+), 31 deletions(-) diff --git a/ooni/director.py b/ooni/director.py index 0707664..beb9c3a 100644 --- a/ooni/director.py +++ b/ooni/director.py @@ -1,4 +1,6 @@ -from ooni.managers import ReportingEntryManager, MeasurementManager +from ooni.managers import ReportEntryManager, MeasurementManager +from ooni.reporter import Report + from ooni.nettest import NetTest class Director(object): @@ -45,29 +47,51 @@ class Director(object): """ _scheduledTests = 0 - def __init__(self): + def __init__(self, reporters): self.reporters = reporters self.netTests = [] - self.measurementManager = MeasurementManager(manager=self, - netTests=self.netTests) + self.measurementManager = MeasurementManager() self.measurementManager.director = self - self.reportEntryManager = ReportingEntryManager() + self.reportEntryManager = ReportEntryManager() self.reportEntryManager.director = self - def startTest(self, net_test_file, inputs, options): - """ - Create the Report for the NetTest and start the report NetTest. + self.successfulMeasurements = 0 + self.failedMeasurements = 0 + + self.totalMeasurements = 0 + + # The cumulative runtime of all the measurements + self.totalMeasurementRuntime = 0 + + self.failures = [] + + @property + def measurementSuccessRatio(self): + return self.successfulMeasurements / self.totalMeasurements + + @property + def measurementFailureRatio(self): + return self.failedMeasurements / self.totalMeasurements + + @property + def measurementSuccessRate(self): """ - report = Report() - report.reportEntryManager = self.reportEntryManager + The speed at which tests are succeeding globally. - net_test = NetTest(net_test_file, inputs, options, report) - net_test.director = self + This means that fast tests that perform a lot of measurements will + impact this value quite heavily. + """ + return self.successfulMeasurements / self.totalMeasurementRuntime - self.measurementManager.schedule(net_test.generateMeasurements()) + @property + def measurementFailureRate(self): + """ + The speed at which tests are failing globally. + """ + return self.failedMeasurements / self.totalMeasurementRuntime def measurementTimedOut(self, measurement): """ @@ -76,12 +100,41 @@ class Director(object): """ pass + def measurementStarted(self, measurement): + self.totalMeasurements += 1 + + def measurementSucceeded(self, measurement): + self.totalMeasurementRuntime += measurement.runtime + + self.successfulMeasurements += 1 + def measurementFailed(self, failure, measurement): - pass + self.totalMeasurementRuntime += measurement.runtime - def writeFailure(self, measurement, failure): - pass + self.failedMeasurements += 1 + self.failures.append((failure, measurement)) + + def startTest(self, net_test_file, options): + """ + Create the Report for the NetTest and start the report NetTest. + + Args: + net_test_file: + is either a file path or a file like object that will be used to + generate the test_cases. + + options: + is a dict containing the options to be passed to the chosen net + test. + """ + report = Report(self.reporters) + report.reportEntryManager = self.reportEntryManager + + net_test = NetTest(net_test_file, options, report) + net_test.measurmentManager = self.measurementManager - def writeReport(self, report_write_task): - self.reportingManager.write(report_write_task) + try: + net_test.start() + except Exception, e: + pass diff --git a/ooni/managers.py b/ooni/managers.py index cee6086..dd748ae 100644 --- a/ooni/managers.py +++ b/ooni/managers.py @@ -99,15 +99,22 @@ class TaskManager(object): self._fillSlots() def start(self): + """ + This is called to start the task manager. + """ self.failures = [] - self.tasksDone = defer.Deferred() self._fillSlots() + def started(self, task): + """ + This hook will get called every time a task has been started. + """ + pass + def failed(self, failure, task): """ - This method should be overriden by the subclass and should contains - logic for dealing with a failure that is subclass specific. + This hoook is called every time a task has failed. The default failure handling logic is to reschedule the task up until we reach the maximum number of retries. @@ -115,6 +122,9 @@ class TaskManager(object): raise NotImplemented def succeeded(self, result, task): + """ + This hook is called every time a task has been successfully executed. + """ raise NotImplemented class MeasurementManager(TaskManager): @@ -136,6 +146,9 @@ class MeasurementManager(TaskManager): director = None + def started(self, measurement): + self.director.measurementStarted(measurement) + def succeeded(self, result, measurement): self.director.measurementSucceeded(measurement) @@ -183,16 +196,6 @@ class ReportEntryManager(object): director = None - def __init__(self, manager, netTests=None): - self.netTests = netTests if netTests else [] - self.manager = manager - - def addNetTest(self, netTest): - self.netTests.append(netTest) - - def initializeTaskList(self): - pass - def succeeded(self, result, measurement): pass diff --git a/ooni/reporter.py b/ooni/reporter.py index 728c3f5..637131c 100644 --- a/ooni/reporter.py +++ b/ooni/reporter.py @@ -373,3 +373,39 @@ class OONIBReporter(OReporter): self.backend_version = parsed_response['backend_version'] log.debug("Created report with id %s" % parsed_response['report_id']) +class Report(object): + reportEntryManager = None + + def __init__(self, reporters): + """ + This will instantiate all the reporters and add them to the list of + available reporters. + + net_test: + is a reference to the net_test to which the report object belongs to. + """ + self.reporters = [] + for r in reporters: + reporter = r() + self.reporters.append(reporter) + + self.createReports() + + def createReports(self): + """ + This will create all the reports that need to be created. + """ + for reporter in self.reporters: + reporter.createReport() + + def write(self, measurement): + """ + This will write to all the reporters, by waiting on the created + callback to fire. + """ + for reporter in self.reporters: + @reporter.created.addCallback + def cb(result): + report_write_task = ReportWrite(reporter, measurement) + self.reportEntryManager.schedule(report_write_task) + diff --git a/ooni/tasks.py b/ooni/tasks.py index 3230732..981f5e1 100644 --- a/ooni/tasks.py +++ b/ooni/tasks.py @@ -1,3 +1,5 @@ +import time + from twisted.internet import defer, reactor class BaseTask(object): @@ -6,6 +8,10 @@ class BaseTask(object): def __init__(self): self.running = False self.failures = 0 + + self.startTime = time.time() + self.runtime = 0 + # This is a deferred that gets called when a test has reached it's # final status, this means: all retries have been attempted or the test # has successfully executed. @@ -17,6 +23,7 @@ class BaseTask(object): return failure def _succeeded(self, result): + self.runtime = time.time() - self.startTime self.succeeded(result) return result
participants (1)
-
isis@torproject.org