2016-06-04 06:07:50 +00:00
|
|
|
from __future__ import print_function, absolute_import, unicode_literals
|
2016-03-02 01:13:33 +00:00
|
|
|
import json, time
|
2017-02-24 01:29:56 +00:00
|
|
|
from zope.interface import implementer
|
|
|
|
from ._interfaces import ITiming
|
2016-03-02 01:13:33 +00:00
|
|
|
|
2016-04-29 21:27:29 +00:00
|
|
|
class Event:
|
|
|
|
def __init__(self, name, when, **details):
|
|
|
|
# data fields that will be dumped to JSON later
|
2016-05-06 02:06:27 +00:00
|
|
|
self._name = name
|
2016-04-29 21:27:29 +00:00
|
|
|
self._start = time.time() if when is None else float(when)
|
|
|
|
self._stop = None
|
|
|
|
self._details = details
|
|
|
|
|
|
|
|
def detail(self, **details):
|
|
|
|
self._details.update(details)
|
|
|
|
|
2016-05-06 02:06:27 +00:00
|
|
|
def finish(self, when=None, **details):
|
2016-04-30 22:48:43 +00:00
|
|
|
self._stop = time.time() if when is None else float(when)
|
2016-04-29 21:27:29 +00:00
|
|
|
self.detail(**details)
|
|
|
|
|
|
|
|
def __enter__(self):
|
|
|
|
return self
|
|
|
|
|
|
|
|
def __exit__(self, exc_type, exc_value, exc_tb):
|
|
|
|
if exc_type:
|
|
|
|
# inlineCallbacks uses a special exception (defer._DefGen_Return)
|
|
|
|
# to deliver returnValue(), so if returnValue is used inside our
|
|
|
|
# with: block, we'll mistakenly think it means something broke.
|
|
|
|
# I've moved all returnValue() calls outside the 'with
|
|
|
|
# timing.add()' blocks to avoid this, but if a new one
|
|
|
|
# accidentally pops up, it'll get marked as an error. I used to
|
|
|
|
# catch-and-release _DefGen_Return to avoid this, but removed it
|
|
|
|
# because it requires referencing defer.py's private class
|
|
|
|
self.finish(exception=str(exc_type))
|
|
|
|
else:
|
|
|
|
self.finish()
|
|
|
|
|
2017-02-24 01:29:56 +00:00
|
|
|
@implementer(ITiming)
|
2016-03-02 01:13:33 +00:00
|
|
|
class DebugTiming:
|
|
|
|
def __init__(self):
|
2016-04-29 21:27:29 +00:00
|
|
|
self._events = []
|
|
|
|
|
|
|
|
def add(self, name, when=None, **details):
|
|
|
|
ev = Event(name, when, **details)
|
|
|
|
self._events.append(ev)
|
|
|
|
return ev
|
|
|
|
|
2016-03-02 01:13:33 +00:00
|
|
|
def write(self, fn, stderr):
|
2016-05-26 05:06:26 +00:00
|
|
|
with open(fn, "wt") as f:
|
2016-05-06 02:06:27 +00:00
|
|
|
data = [ dict(name=e._name,
|
|
|
|
start=e._start, stop=e._stop,
|
|
|
|
details=e._details,
|
|
|
|
)
|
2016-04-29 21:27:29 +00:00
|
|
|
for e in self._events ]
|
2016-05-06 02:06:27 +00:00
|
|
|
json.dump(data, f, indent=1)
|
2016-03-02 01:13:33 +00:00
|
|
|
f.write("\n")
|
|
|
|
print("Timing data written to %s" % fn, file=stderr)
|