-
Notifications
You must be signed in to change notification settings - Fork 13
/
log_execute_console.py
135 lines (99 loc) · 3.81 KB
/
log_execute_console.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
""" Simple extension which makes all
``client.services.object.execute`` calls to be logged
*NOTE*: this exension is not included in ``openerp_proxy.ext.all``
so it should be enabled (imported) manualy
Also allows to measure tim spent on rpc calls
Ususaly used for debug and performance tests
"""
import time
import logging
from ..service.object import ObjectService
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
class TimeTracker(object):
""" Context manager to track separatly total time that some request took and
time spent on rpc queries.
Example::
with TimeTracker('my-code-block') as t:
product = db._product_product.serch_records([], limit=400000)
print("Query time: %s, Total time: %s" % (p.query_time, p.total_time))
"""
# TODO: implement query counter, which may be used for performance tests
query_timers = {}
@classmethod
def start_timing(cls, name):
""" Start timer named *name*
:param str name: name of timer to be started
"""
cls.query_timers[name] = 0.0
@classmethod
def get_query_times(cls, name):
""" Get time spent for queries for timer named *name*
:param str name: name of timer to be started
"""
return cls.query_timers.get(name, 0.0)
@classmethod
def _update_times(cls, time):
""" This method should be called internaly only.
Updates all timers
"""
for timer in cls.query_timers:
cls.query_timers[timer] += time
@classmethod
def remove_timer(cls, name):
""" Remove timer for timers list.
"""
del cls.query_timers[name]
def __init__(self, name):
self.name = name
self._result_time = None
self._total_time = None
self._start_time = None
@property
def query_time(self):
""" Return current query time (if not finished) or total query time
"""
if self._result_time is None:
return self.get_query_times(self.name)
return self._result_time
@property
def total_time(self):
""" if not started, returns 0.0
if started and not finished returns current time - start time
if finished return total time (time finished - start time
"""
if self._start_time is None:
return 0.0
if self._total_time is not None:
return self._total_time
return time.time() - self._start_time
def __enter__(self):
self._start_time = time.time()
self.start_timing(self.name)
return self
def __exit__(self, type, value, tb):
if type is not None:
raise value
self._result_time = self.query_time
self._total_time = self.total_time
self.remove_timer(self.name)
# If set to False, then all arguments of 'execute' methon will be printed,
# otherwise only first two arguments and time spent will be printed
LOG_SIMPLE = True
class ObjectServiceLog(ObjectService):
""" Simply logs all calls to ``execute`` method of `object` service
to console (displying all arguments).
If module level variable ``LOG_SIMPLE`` set to True,then
only simple lines like 'Execute [<obj>, <method>] will be displayed
"""
def execute(self, obj, method, *args, **kwargs):
if LOG_SIMPLE:
msg = "Execute [%s, %s]" % (obj, method)
else:
msg = "Execute [%s, %s] (%s, %s)" % (obj, method, args, kwargs)
startTime = time.time()
res = super(ObjectServiceLog, self).execute(obj, method, *args, **kwargs)
elapsedTime = time.time() - startTime
TimeTracker._update_times(elapsedTime)
logger.info('{} finished in {} ms'.format(msg, int(elapsedTime * 1000)))
return res