Skip to content

Commit e4a6527

Browse files
author
Woody Yang
committed
Add rsyslog collector
1 parent f2bece4 commit e4a6527

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed

docs/collectors/RsyslogCollector.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!--This file was generated from the python source
2+
Please edit the source to make changes
3+
-->
4+
RsyslogCollector
5+
=====
6+
7+
Collects stats from rsyslog server with impstats module loaded
8+
Impstats formats are json/json-elasticsearch/cee/legacy, but
9+
only json and legacy formats are supported
10+
11+
#### Dependencies
12+
* Rsyslog Plugin – impstats (rsyslog 7.5.3+)
13+
(http://www.rsyslog.com/rsyslog-statistic-counter-plugin-impstats/)
14+
(http://www.rsyslog.com/doc/v8-stable/configuration/modules/impstats.html)
15+
16+
#### Metrics
17+
* [Rsyslog statistic counter ](http://www.rsyslog.com/rsyslog-statistic-counter/)
18+
19+
#### Options
20+
21+
Setting | Default | Description | Type
22+
--------|---------|-------------|-----
23+
byte_unit | byte | Default numeric output(s) | str
24+
enabled | False | Enable collecting these metrics | bool
25+
measure_collector_time | False | Collect the collector run time in ms | bool
26+
metrics_blacklist | None | Regex to match metrics to block. Mutually exclusive with metrics_whitelist | NoneType
27+
metrics_whitelist | None | Regex to match metrics to transmit. Mutually exclusive with metrics_blacklist | NoneType
28+
pstats_path | /var/log/rsyslog_stats.log | Path to get syslog stats. | str
29+
30+
#### Example Output
31+
32+
```
33+
__EXAMPLESHERE__
34+
```
35+

src/collectors/rsyslog/rsyslog.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# coding=utf-8
2+
3+
"""
4+
Collects stats from rsyslog server with impstats module loaded
5+
Impstats formats are json/json-elasticsearch/cee/legacy, but
6+
only json and legacy formats are supported
7+
8+
#### Dependencies
9+
* Rsyslog Plugin – impstats (rsyslog 7.5.3+)
10+
(http://www.rsyslog.com/rsyslog-statistic-counter-plugin-impstats/)
11+
(http://www.rsyslog.com/doc/v8-stable/configuration/modules/impstats.html)
12+
13+
#### Metrics
14+
* [Rsyslog statistic counter ]
15+
(http://www.rsyslog.com/rsyslog-statistic-counter/)
16+
"""
17+
18+
from collections import deque
19+
import re
20+
import diamond.collector
21+
import socket
22+
import time
23+
import json
24+
25+
26+
class RsyslogCollector(diamond.collector.Collector):
27+
def get_default_config_help(self):
28+
config_help = super(RsyslogCollector, self).get_default_config_help()
29+
config_help.update({
30+
'pstats_path': "Path to get syslog stats.",
31+
})
32+
return config_help
33+
34+
def get_default_config(self):
35+
"""
36+
Returns the RsyslogCollector settings
37+
"""
38+
config = super(RsyslogCollector, self).get_default_config()
39+
config.update({
40+
'pstats_path': '/var/log/rsyslog_stats.log',
41+
'path': 'rsyslog'
42+
})
43+
return config
44+
45+
def _get_summary(self):
46+
count = 0
47+
with open(self.config['pstats_path']) as f:
48+
for line in reversed(f.readlines()):
49+
if "global" in line.rstrip():
50+
if count > 1:
51+
break
52+
count += 1
53+
elif count > 0:
54+
count += 1
55+
f.seek(0)
56+
summary_fp = deque(f, count)
57+
return summary_fp
58+
59+
def legacyformat(self, stat_lines):
60+
self.rsyslog_stats = []
61+
for line in stat_lines:
62+
metrics = {}
63+
parsed = line.split(': ', 2)
64+
if parsed[1].count("(") > 0:
65+
name = re.sub(r"(^im[ut][dc]p)\(\*?\:?(\d?[\d|\w]?\d)\)",
66+
r'\1_\2', parsed[1])
67+
else:
68+
name = parsed[1].replace(' ', '_')
69+
_metrics = parsed[2].split(' ', -1)
70+
metrics.update({"name": name})
71+
for m in _metrics:
72+
if "\n" not in m:
73+
metrics.update({m.split('=', 1)[0]: m.split('=', 1)[1]})
74+
self.rsyslog_stats.append(metrics)
75+
return self.rsyslog_stats
76+
77+
def jsonformat(self, stat_lines):
78+
self.rsyslog_stats = []
79+
for line in stat_lines:
80+
parsed = line.split('rsyslogd-pstats: ', 2)
81+
parsed = json.loads(parsed[1])
82+
if parsed['name'].count("(") > 0:
83+
parsed['name'] = re.sub(
84+
r"(^im[ut][dc]p)\(\*?\:?(\d?[\d|\w]?\d)\)",
85+
r'\1_\2', parsed['name']
86+
)
87+
else:
88+
parsed['name'] = parsed['name'].replace(' ', '_')
89+
self.rsyslog_stats.append(parsed)
90+
return self.rsyslog_stats
91+
92+
def is_json(self, str):
93+
try:
94+
json_object = json.loads(str)
95+
except ValueError, e:
96+
return False
97+
return True
98+
99+
def collect(self):
100+
legacy_format = False
101+
stats = self._get_summary()
102+
for line in stats:
103+
parsed = line.split('rsyslogd-pstats: ', 2)
104+
if self.is_json(parsed[1]):
105+
rsyslog_stats = self.jsonformat(stats)
106+
else:
107+
rsyslog_stats = self.legacyformat(stats)
108+
legacy_format = True
109+
break
110+
for metrics in self.rsyslog_stats:
111+
metric_prefix = metrics['name']
112+
for k in metrics:
113+
if k != 'origin' and k != 'name':
114+
metric_name = metric_prefix + '.' + k
115+
metric_value = metrics[k]
116+
if legacy_format is True:
117+
self.publish(metric_name, metric_value)
118+
else:
119+
if isinstance(metric_value, int):
120+
self.publish(metric_name, metric_value)

0 commit comments

Comments
 (0)