-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtransResponseTime.py
executable file
·172 lines (139 loc) · 5.27 KB
/
transResponseTime.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/python
"""
Transaction Utils,
the following code is a framework was writen for handle, manage, and get transaction statistics.
it also extends profilehooks, and expose some additional capabilities.
some of advantages is the ability to publish stats directly to influxDB.
"""
import os
import time
import psutil
import transInfluxClient
from multiprocessing import Lock
transactions = [] # structure is {name: (timestamp, response time, rec, sent)}
lock = Lock()
results_format = "%.4f"
influx = None
net_dev = 'en0'
collect_net = False
def singleton(class_):
instances = {}
def get_instance(*args, **kwargs):
if class_ not in instances:
with lock:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return get_instance
@singleton
class TransResponse(object):
def __init__(self):
import ConfigParser
config = None
try:
config = ConfigParser.ConfigParser(allow_no_value=True)
os.path.dirname(__file__)
config.read(os.path.dirname(__file__) + '/config.cfg')
if config.getboolean('run', 'collect_net_io'):
global collect_net, net_dev
collect_net = True
# TODO::// may be replace it with automatic manner.
net_dev = config.get('run', 'net_device')
if config.getboolean('run', 'report_to_influx'):
# TODO:// fix the log format arg.
global influx
influx = transInfluxClient.GetInflux(config.get('influx', 'server'), config.get('influx', 'port'),
config.get('influx', 'dbname'), config.get('influx', 'table'),
config.get('influx', 'log_file'),
config.get('influx', 'log_level'),
pattern=config.get('influx', 'time_pattern'))
except Exception as e:
print e
finally:
del config
TransResponse()
def send_influx(trans, timestamp, duration, bsent=0, brecv=0):
try:
influx.send(trans, timestamp, duration, bsent, brecv)
except Exception as e:
print e
def get_results():
print ["{0} : {1}, {2}".format(entry, results_format % mapper[entry][0], mapper[entry][1])
for mapper in transactions for entry in mapper]
def measure(method_name, func_to_run=None, *args):
"""
Context manager to log request response time
"""
_start_time = 0
net_io_dump = None
global net_dev, collect_net
if collect_net:
net_io_dump = psutil.net_io_counters(True).get(net_dev)
try:
_start_time = time.time()
if len(args) >= 1:
func_to_run(*args)
else:
func_to_run()
except Exception as e:
# TODO:// function failure needs to be handled.
raise e
finally:
_duration = (time.time() - _start_time)
finalize(False, True, method_name, _start_time, _duration, net_io_dump)
def store_transaction(name=None, start_time=None, duration=None, recive=0, sent=0):
trans_map = dict()
try:
trans_map[name] = (duration, start_time, sent, recive)
transactions.append(trans_map)
except Exception as e:
print 'failed to store trans' + str(e)
def measure_time(fn=None, immediate=False, store=True):
"""Wrap `fn` and print its execution time, plus handled dictionary of a transactions.
this extends logic of profilehooks.py
and provide more flexibility, it save the execution time and save it to a dictionary.
it can be collected by TranResponseTime.get_results()
"""
if fn is None:
def decorator(fnc):
return measure_time(fnc, immediate, store)
return decorator
fp = FuncTimer(fn, immediate, store)
def new_fn(*args, **kw):
return fp(*args, **kw)
return new_fn
def finalize(toprint, tostore, name, start_time, duration, net_io_dump):
sent = 0
recv = 0
global influx, collect_net
if collect_net:
net_io_dump2 = psutil.net_io_counters(True).get(net_dev)
sent = net_io_dump2[0] - net_io_dump[0]
recv = net_io_dump2[1] - net_io_dump[1]
if influx:
send_influx(name, start_time, duration, sent, recv)
with lock:
if toprint:
print "{0} : {1} ".format(name, results_format % duration)
if tostore:
store_transaction(name, start_time, duration, sent, recv)
class FuncTimer(object):
def __init__(self, fnc, immediate=True, store=True):
self.sfn = fnc
self.print_now = immediate
self.store_now = store
def __call__(self, *args, **kw):
"""Profile a singe call to the function."""
global net_dev, collect_net
fn = self.sfn
net_io_dump = None
if collect_net:
net_io_dump = psutil.net_io_counters(True).get(net_dev)
start_time = time.time()
try:
return fn(*args, **kw)
except Exception as e:
# TODO:// function failure needs to be handled.
print e
finally:
_duration = time.time() - start_time
finalize(self.print_now, self.store_now, fn.__name__, start_time, _duration, net_io_dump)