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}