@cryptotaxi247 / netdata-1 / commits / 15928cc14

ovpn_status_log plugin: support for "static key" status log files added

Ilya committed Apr 15, 2017 at 16:09 UTC 15928cc14cc1748cabd7f503cd3feaa79b163402
1 file changed +54 -29
python.d/ovpn_status_log.chart.py
+54 -29
@@ -2,8 +2,10 @@
2 # Description: openvpn status log netdata python.d module
3 # Author: l2isbad
4
5 -from base import SimpleService
5 from re import compile as r_compile
6 +from collections import defaultdict
7 +from base import SimpleService
8 +
9 priority = 60000
10 retries = 60
11 update_every = 10
@@ -13,12 +15,12 @@ CHARTS = {
15 'users': {
16 'options': [None, 'OpenVPN Active Users', 'active users', 'users', 'openvpn_status.users', 'line'],
17 'lines': [
16 - ["users", None, "absolute"],
18 + ['users', None, 'absolute'],
19 ]},
20 'traffic': {
19 - 'options': [None, 'OpenVPN Traffic', 'Kb/s', 'traffic', 'openvpn_status.traffic', 'area'],
21 + 'options': [None, 'OpenVPN Traffic', 'KB/s', 'traffic', 'openvpn_status.traffic', 'area'],
22 'lines': [
21 - ["in", None, "incremental", 8, 1000], ["out", None, "incremental", 8, -1000]
23 + ['bytes_in', 'in', 'incremental', 1, 1 << 10], ['bytes_out', 'out', 'incremental', 1, -1 << 10]
24 ]},
25
26 }
@@ -30,23 +32,27 @@ class Service(SimpleService):
32 self.order = ORDER
33 self.definitions = CHARTS
34 self.log_path = self.configuration.get('log_path')
33 - self.regex_data_inter = r_compile(r'(?<=Since ).*?(?=.ROUTING)')
34 - self.regex_data_final = r_compile(r'\d{1,3}(?:\.\d{1,3}){3}[:0-9,. ]*')
35 - self.regex_users = r_compile(r'\d{1,3}(?:\.\d{1,3}){3}:\d+')
36 - self.regex_traffic = r_compile(r'(?<=(?:,| ))\d+(?=(?:,| ))')
35 + self.regex = dict(tls=r_compile(r'\d{1,3}(?:\.\d{1,3}){3}(?::\d+)? (?P<bytes_in>\d+) (?P<bytes_out>\d+)'),
36 + static_key=r_compile(r'TCP/[A-Z]+ (?P<direction>(?:read|write)) bytes,(?P<bytes>\d+)'))
37 + self.to_netdata = dict(bytes_in=0, bytes_out=0)
38
39 def check(self):
40 if not (self.log_path and isinstance(self.log_path, str)):
41 self.error('\'log_path\' is not defined')
42 return False
43
43 - data = self._get_data()
44 - if not data:
45 - self.error('Make sure that the openvpn status log file exists and netdata has permission to read it')
46 - return False
47 - else:
48 - self._data_from_check = data
44 + data = False
45 + for method in (self._get_data_tls, self._get_data_static_key):
46 + data = method()
47 + if data:
48 + self._get_data = method
49 + self._data_from_check = data
50 + break
51 +
52 + if data:
53 return True
54 + self.error('Make sure that the openvpn status log file exists and netdata has permission to read it')
55 + return False
56
57 def _get_raw_data(self):
58 """
@@ -55,34 +61,53 @@ class Service(SimpleService):
61 """
62
63 try:
58 - with open(self.log_path, 'rt') as log:
59 - result = log.read()
64 + with open(self.log_path) as log:
65 + raw_data = log.readlines() or None
66 except OSError:
67 return None
68 else:
63 - return result or None
69 + return raw_data
70
65 - def _get_data(self):
71 + def _get_data_static_key(self):
72 """
73 Parse openvpn-status log file.
68 - Current regex version is ok for status-version 1, 2 and 3. Both users and bytes in/out are collecting.
74 """
75
76 raw_data = self._get_raw_data()
77 if not raw_data:
78 return None
79
75 - data_inter = self.regex_data_inter.search(' '.join(raw_data.splitlines()))
76 - if not data_inter:
80 + data = defaultdict(lambda: 0)
81 +
82 + for row in raw_data:
83 + match = self.regex['static_key'].search(row)
84 + if match:
85 + match = match.groupdict()
86 + if match['direction'] == 'read':
87 + data['bytes_in'] += int(match['bytes'])
88 + else:
89 + data['bytes_out'] += int(match['bytes'])
90 +
91 + return data or None
92 +
93 + def _get_data_tls(self):
94 + """
95 + Parse openvpn-status log file.
96 + """
97 +
98 + raw_data = self._get_raw_data()
99 + if not raw_data:
100 return None
78 - else:
79 - data_inter = data_inter.group()
101
81 - data_final = ' '.join(self.regex_data_final.findall(data_inter))
82 - users = self.regex_users.subn('', data_final)[1]
83 - traffic = self.regex_traffic.findall(data_final)
102 + data = defaultdict(lambda: 0)
103 + for row in raw_data:
104 + row = ' '.join(row.split(',')) if ',' in row else ' '.join(row.split())
105 + match = self.regex['tls'].search(row)
106 + if match:
107 + match = match.groupdict()
108 + data['users'] += 1
109 + data['bytes_in'] += int(match['bytes_in'])
110 + data['bytes_out'] += int(match['bytes_out'])
111
85 - bytes_in = sum(int(traffic[i[0]]) for i in enumerate(traffic) if (i[0] + 1) % 2 is 1)
86 - bytes_out = sum(int(traffic[i[0]]) for i in enumerate(traffic) if (i[0] + 1) % 2 is 0)
112 + return data or None
113
88 - return {'users': users, 'in': bytes_in, 'out': bytes_out}