1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
"""Reader for many useful metrics in /proc on Linux.""" |
3
|
|
|
|
4
|
|
|
from collections import deque, Iterable |
5
|
|
|
|
6
|
|
|
import plumd |
7
|
|
|
|
8
|
|
|
from plumd.readers.linux.conntrack import Conntrack |
9
|
|
|
from plumd.readers.linux.diskstats import DiskStats |
10
|
|
|
from plumd.readers.linux.loadavg import LoadAverage |
11
|
|
|
from plumd.readers.linux.mem import Mem |
12
|
|
|
from plumd.readers.linux.netdev import NetDev |
13
|
|
|
from plumd.readers.linux.netsnmp import NetSnmp |
14
|
|
|
from plumd.readers.linux.netstat import Netstat |
15
|
|
|
from plumd.readers.linux.sockstat import SockStat |
16
|
|
|
from plumd.readers.linux.pstat import Stat |
17
|
|
|
from plumd.readers.linux.swap import Swap |
18
|
|
|
from plumd.readers.linux.uptime import Uptime |
19
|
|
|
from plumd.readers.linux.vmstat import VmStat |
20
|
|
|
|
21
|
|
|
__author__ = 'Kenny Freeman' |
22
|
|
|
__email__ = '[email protected]' |
23
|
|
|
__license__ = "ISCL" |
24
|
|
|
__docformat__ = 'reStructuredText' |
25
|
|
|
|
26
|
|
|
classes = [Conntrack, DiskStats, LoadAverage, Mem, NetDev, NetSnmp, Netstat, |
27
|
|
|
SockStat, Stat, Swap, Uptime, VmStat] |
28
|
|
|
|
29
|
|
|
|
30
|
|
|
class Proc(plumd.Reader): |
31
|
|
|
"""Plugin to measure various kernel metrics from /proc.""" |
32
|
|
|
|
33
|
|
|
defaults = { |
34
|
|
|
'poll.interval': 10, |
35
|
|
|
'disabled_readers': [] |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
def __init__(self, log, config): |
39
|
|
|
"""Plugin to measure various kernel metrics from /proc. |
40
|
|
|
|
41
|
|
|
:param log: A logger |
42
|
|
|
:type log: logging.RootLogger |
43
|
|
|
:param config: a plumd.config.Conf configuration helper instance. |
44
|
|
|
:type config: plumd.config.Conf |
45
|
|
|
""" |
46
|
|
|
super(Proc, self).__init__(log, config) |
47
|
|
|
config.defaults(Proc.defaults) |
48
|
|
|
self.readers = deque() |
49
|
|
|
disabled = config.get('disabled_readers') |
50
|
|
|
for cls in classes: |
51
|
|
|
if cls.__name__ in disabled: |
52
|
|
|
msg = "Proc: skipping disabled reader: {0}" |
53
|
|
|
self.log.warn(msg.format(cls.__name__)) |
54
|
|
|
continue |
55
|
|
|
self.log.debug( |
56
|
|
|
"Proc: initializing reader: {0}".format(cls.__name__)) |
57
|
|
|
self.readers.append(cls(log, config)) |
58
|
|
|
|
59
|
|
|
def poll(self): |
60
|
|
|
"""Poll for kernel metrics under /proc. |
61
|
|
|
|
62
|
|
|
:rtype: ResultSet |
63
|
|
|
""" |
64
|
|
|
ret = plumd.ResultSet([]) |
65
|
|
|
for rdr in self.readers: |
66
|
|
|
try: |
67
|
|
|
vals = rdr.check() |
68
|
|
|
if isinstance(vals, Iterable): |
69
|
|
|
ret.add_list(vals) |
70
|
|
|
else: |
71
|
|
|
msg = "Proc: invalid return from {0}" |
72
|
|
|
self.log.warn(msg.format(rdr)) |
73
|
|
|
except Exception as exc: |
|
|
|
|
74
|
|
|
msg = "Proc: exception polling: {0}: {1}" |
75
|
|
|
self.log.error(msg.format(rdr, exc)) |
76
|
|
|
return ret |
77
|
|
|
|
Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.
So, unless you specifically plan to handle any error, consider adding a more specific exception.