Completed
Push — master ( a45803...5d2be7 )
by Kenny
01:16
created

NetSnmp.check()   C

Complexity

Conditions 9

Size

Total Lines 54

Duplication

Lines 54
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
c 1
b 0
f 0
dl 54
loc 54
rs 5.4234

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
# -*- coding: utf-8 -*-
2
3
__author__ = 'Kenny Freeman'
4
__email__ = '[email protected]'
5
__license__ = "ISCL"
6
__docformat__ = 'reStructuredText'
7
8
import time
9
from collections import deque
10
11
import plumd
12
import plumd.plugins
13
from plumd.calc import Differential
14
from plumd.util import Filter
15
16
17
## todo: switch from list with pop(0) to deque
18
class NetSnmp(plumd.plugins.Reader):
19
    """Plugin to measure various kernel metrics from /proc."""
20
    defaults = {
21
        'poll.interval': 10,
22
        'proc_path': '/proc',
23
        'proc_netsnmp_record': {
24
            'Ip': [ 'Forwarding', 'InReceives', 'InHdrErrors', 'InAddrErrors',
25
                    'ForwDatagrams', 'InUnknownProtos', 'InDiscards',
26
                    'InDelivers', 'OutRequests', 'OutDiscards',
27
                    'ReasmTimeout', 'ReasmReqds', 'ReasmOKs', 'ReasmFails',
28
                    'FragOKs', 'FragFails', 'FragCreates' ],
29
            'Icmp': [ 'InMsgs','InErrors', 'InCsumErrors', 'InDestUnreachs',
30
                     'InTimeExcds', 'InParmProbs', 'InSrcQuenchs',
31
                     'InRedirects', 'InEchos', 'InEchoReps',  'OutMsgs',
32
                     'OutErrors', 'OutDestUnreachs', 'OutTimeExcds',
33
                     'OutParmProbs', 'OutSrcQuenchs', 'OutRedirects',
34
                     'OutEchos', 'OutEchoReps' ],
35
            'IcmpMsg': [ 'OutType3' ],
36
            'Tcp': [ 'MaxConn', 'ActiveOpens', 'PassiveOpens', 'AttemptFails',
37
                    'EstabResets', 'CurrEstab', 'InSegs', 'OutSegs',
38
                    'RetransSegs', 'InErrs', 'OutRsts', 'InCsumErrors' ],
39
            'Udp': [ 'InDatagrams', 'NoPorts', 'InErrors', 'OutDatagrams',
40
                    'RcvbufErrors', 'SndbufErrors', 'InCsumErrors' ]
41
        }
42
    }
43
44
    def __init__(self, log, config):
45
        """Plugin to measure various kernel metrics from /proc.
46
47
        :param log: A logger
48
        :type log: logging.RootLogger
49
        :param config: a plumd.config.Conf configuration helper instance.
50
        :type config: plumd.config.Conf
51
        """
52
        super(NetSnmp, self).__init__(log, config)
53
        self.config.defaults(NetSnmp.defaults)
54
        self.calc = Differential()
55
        self.proc_file = "{0}/net/snmp".format(config.get('proc_path'))
56
        self.filter = Filter()
57
58
59
60
    def poll(self):
61
        """Poll for kernel metrics under /proc.
62
63
        :rtype: ResultSet
64
        """
65
        return plumd.ResultSet(self.check())
66
67
68 View Code Duplication
    def check(self):
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
69
        """Return network protocol metrics from proc file net/snmp.
70
71
        Add entries to the configuration value 'skip_proc_net_snmp' to skip
72
        metrics.
73
74
        Add entries to the configuration value 'net_snmp_items' to match the
75
        format/order of the proc file net/snmp entries on the system.
76
77
        :rtype: plumd.Result
78
        """
79
        record = self.config.get('proc_netsnmp_record')
80
        result = plumd.Result("net_snmp")
81
82
        # read the proc file
83
        dat = None
84
        with open(self.proc_file, 'r') as f:
85
            dat = f.read().strip().split("\n")
86
87
        # timestamp for Differential calculations
88
        ts = time.time()
89
90
        # should always have a header row and value row, ie. divisible by 2
91
        if len(dat) % 2 != 0:
92
            self.log.error("netsnmp: cannot parse {0}".format(self.proc_file))
93
            return result
94
95
        # split values into lists
96
        dlist = deque()
97
        for entry in dat:
98
            dlist.append(entry.split())
99
100
        # put lists into key: value dict
101
        metrics = {}
102
        while dlist:
103
            headers = dlist.popleft()
104
            values = dlist.popleft()
105
            # { 'IpExt': {'InNoRoutes': 0, ...} } - [:-1] on IpExt: removes :
106
            metrics[headers[0][:-1]] = dict(zip(headers, values))
107
108
        # now, we have a list of items to record, just need to record them
109
        for proto, mnames in record.items():
110
            if proto not in metrics:
111
                self.log.warn("netsnmp: unknown protocol: {0}".format(proto))
112
                continue
113
            values = metrics[proto]
114
            for mname in mnames:
115
                if mname in values:
116
                    mstr = "{0}.{1}".format(proto, mname)
117
                    mval = self.calc.per_second(mstr, int(values[mname]), ts)
118
                    result.add(plumd.Int(mstr, mval))
119
                else:
120
                    self.log.warn("netstat: unknown metric {0}".format(mname))
121
        return [result]
122