~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/services/timeline/timedaction.py

  • Committer: Robert Collins
  • Date: 2011-08-10 01:00:53 UTC
  • mto: This revision was merged to the branch mainline in revision 13644.
  • Revision ID: robertc@robertcollins.net-20110810010053-w2tcm21i87fwqr3s
Use the new extracted timeline module.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2010 Canonical Ltd.  This software is licensed under the
2
 
# GNU Affero General Public License version 3 (see the file LICENSE).
3
 
 
4
 
"""Time a single categorised action."""
5
 
 
6
 
 
7
 
__all__ = ['TimedAction']
8
 
 
9
 
__metaclass__ = type
10
 
 
11
 
 
12
 
import datetime
13
 
 
14
 
import pytz
15
 
 
16
 
 
17
 
UTC = pytz.utc
18
 
 
19
 
 
20
 
class TimedAction:
21
 
    """An individual action which has been timed.
22
 
 
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(*) ..."
29
 
    """
30
 
 
31
 
    def __init__(self, category, detail, timeline=None):
32
 
        """Create a TimedAction.
33
 
 
34
 
        New TimedActions have a start but no duration.
35
 
 
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.
39
 
        """
40
 
        self.start = datetime.datetime.now(UTC)
41
 
        self.duration = None
42
 
        self.category = category
43
 
        self.detail = detail
44
 
        self.timeline = timeline
45
 
        self._init()
46
 
 
47
 
    def _init(self):
48
 
        # hook for child classes.
49
 
        pass
50
 
 
51
 
    def __repr__(self):
52
 
        return "<%s %s[%s]>" % (self.__class__, self.category,
53
 
            self.detail[:20])
54
 
 
55
 
    def logTuple(self):
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())
67
 
        else:
68
 
            length = self._td_to_ms(self.duration)
69
 
        return (offset, offset + length, self.category, self.detail)
70
 
 
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
75
 
 
76
 
    def finish(self):
77
 
        """Mark the TimedAction as finished."""
78
 
        self.duration = self._interval_to_now()
79
 
 
80
 
    def _interval_to_now(self):
81
 
        return datetime.datetime.now(UTC) - self.start