-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpybtp.py
More file actions
124 lines (96 loc) · 3.24 KB
/
pybtp.py
File metadata and controls
124 lines (96 loc) · 3.24 KB
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
"""
Python api for btp (https://github.com/mambaru/btp-daemon)
Example:
import pybtp
conn = pybtp.Connection('example.com', 22400)
conn.connect()
req = pybtp.Request(conn, 'btp.test')
req.append('btp.test.service', 'srv1', 'test', 4321)
cntr = pybtp.Counter(req, 'btp.counter.test', 'srv1', 'test.counter')
cntr.stop()
req.close()
conn.disconnect()
"""
import json
import re
import socket
import time
try:
import resource
except ImportError:
resource = None
def micro_delta(b, a):
return int(1000000 * (b - a))
class Connection(object):
def __init__(self, host, port):
self._address = (host, port)
self.failed = False
def connect(self):
self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._socket.connect(self._address)
def _send(self, data):
self._socket.sendall(json.dumps(data, separators=(',',':')) + "\r\n")
def disconnect(self):
self._socket.close()
def notify(self, method, params):
self._send(dict(jsonrpc='2.0', method=method, params=params))
class Request(object):
farm_re = re.compile(r'\d')
def __init__(self, connection, script):
"""
@type connection Connection
"""
self._connection = connection
self.script = script
self.ts = time.time()
self.items = {}
self.items_count = 0
self.server = socket.gethostname()
if resource:
self._start_rusage = resource.getrusage(resource.RUSAGE_SELF)
def _send(self):
data = dict(
srv=self.server,
script=self.script,
time=self.ts,
items=self.items
)
self._connection.notify('put', data)
self.items = {}
self.items_count = 0
def _append_script_timings(self):
script_service = "SCRIPT_%s" % self.server
farm = re.sub(self.farm_re, '', self.server)
farm_stats = self.items.setdefault(script_service, {}).setdefault(farm, {})
farm_stats['all'] = [micro_delta(time.time(), self.ts)]
if resource:
end_rusage = resource.getrusage(resource.RUSAGE_SELF)
farm_stats['user'] = [
micro_delta(end_rusage.ru_utime, self._start_rusage.ru_utime)]
farm_stats['system'] = [
micro_delta(end_rusage.ru_stime, self._start_rusage.ru_stime)]
def append(self, service, server, operation, timing):
server_stats = self.items.setdefault(service, {}).setdefault(server, {})
if operation not in server_stats:
server_stats[operation] = []
self.items_count += 1
server_stats[operation].append(timing)
if self.items_count > 30 or time.time() - self.ts > 1:
self._send()
def close(self):
self._append_script_timings()
self._send()
class Counter(object):
def __init__(self, request, service, server, operation):
"""
@type request Request
"""
self.request = request
self.service = service
self.server = server
self.operation = operation
self.ts = time.time()
def stop(self):
self.request.append(
self.service, self.server, self.operation,
micro_delta(time.time(), self.ts))