1
# Copyright 2010 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
"""Time a single categorised action."""
7
__all__ = ['TimedAction']
21
"""An individual action which has been timed.
23
:ivar timeline: The timeline that this action took place within.
24
:ivar start: A datetime object with tz for the start of the action.
25
:ivar duration: A timedelta for the duration of the action. None for
26
actions which have not completed.
27
:ivar category: The category of the action. E.g. "sql".
28
:ivar detail: The detail about the action. E.g. "SELECT COUNT(*) ..."
31
def __init__(self, category, detail, timeline=None):
32
"""Create a TimedAction.
34
New TimedActions have a start but no duration.
36
:param category: The category for the action.
37
:param detail: The detail about the action being timed.
38
:param timeline: The timeline for the action.
40
self.start = datetime.datetime.now(UTC)
42
self.category = category
44
self.timeline = timeline
48
# hook for child classes.
52
return "<%s %s[%s]>" % (self.__class__, self.category,
56
"""Return a 4-tuple suitable for errorlog's use."""
57
offset = self._td_to_ms(self.start - self.timeline.baseline)
58
if self.duration is None:
59
# This action wasn't finished: pretend it has finished now
60
# (even though it hasn't). This is pretty normal when action ends
61
# are recorded by callbacks rather than stack-like structures. E.g.
62
# storm tracers in launchpad:
63
# log-trace START : starts action
64
# timeout-trace START : raises
65
# log-trace FINISH is never called.
66
length = self._td_to_ms(self._interval_to_now())
68
length = self._td_to_ms(self.duration)
69
return (offset, offset + length, self.category, self.detail)
71
def _td_to_ms(self, td):
72
"""Tweak on a backport from python 2.7"""
73
return (td.microseconds + (
74
td.seconds + td.days * 24 * 3600) * 10**6) / 10**3
77
"""Mark the TimedAction as finished."""
78
self.duration = self._interval_to_now()
80
def _interval_to_now(self):
81
return datetime.datetime.now(UTC) - self.start