Completed
Push — master ( c845e9...7e8cc2 )
by Kenny
02:02
created

NetSnmp.check()   F

Complexity

Conditions 13

Size

Total Lines 73

Duplication

Lines 73
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
c 1
b 0
f 0
dl 73
loc 73
rs 2.3081

How to fix   Long Method    Complexity   

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:

Complexity

Complex classes like NetSnmp.check() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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_gauges': {
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
        'proc_netsnmp_rates': {}
43
    }
44
45 View Code Duplication
    def __init__(self, log, config):
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
46
        """Plugin to measure various kernel metrics from /proc.
47
48
        :param log: A logger
49
        :type log: logging.RootLogger
50
        :param config: a plumd.config.Conf configuration helper instance.
51
        :type config: plumd.config.Conf
52
        """
53
        super(NetSnmp, self).__init__(log, config)
54
        self.config.defaults(NetSnmp.defaults)
55
        self.calc = Differential()
56
        self.proc_file = "{0}/net/snmp".format(config.get('proc_path'))
57
        self.filter = Filter()
58
        self.gauges = self.config.get('proc_netsnmp_gauges')
59
        self.rates = self.config.get('proc_netsnmp_rates')
60
61
62
    def poll(self):
63
        """Poll for kernel metrics under /proc.
64
65
        :rtype: ResultSet
66
        """
67
        return plumd.ResultSet(self.check())
68
69
70 View Code Duplication
    def check(self):
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
71
        """Return network protocol metrics from proc file net/snmp.
72
73
        Add entries to the configuration value 'skip_proc_net_snmp' to skip
74
        metrics.
75
76
        Add entries to the configuration value 'net_snmp_items' to match the
77
        format/order of the proc file net/snmp entries on the system.
78
79
        :rtype: plumd.Result
80
        """
81
        result = plumd.Result("netsnmp")
82
83
        # read the proc file
84
        dat = None
85
        with open(self.proc_file, 'r') as f:
86
            dat = f.read().strip().split("\n")
87
88
        # timestamp for Differential calculations
89
        ts = time.time()
90
91
        # should always have a header row and value row, ie. divisible by 2
92
        if len(dat) % 2 != 0:
93
            self.log.error("netsnmp: cannot parse {0}".format(self.proc_file))
94
            return result
95
96
        # split values into lists
97
        dlist = deque()
98
        for entry in dat:
99
            dlist.append(entry.split())
100
101
        # put lists into key: value dict
102
        metrics = {}
103
        while dlist:
104
            headers = dlist.popleft()
105
            values = dlist.popleft()
106
            # { 'IpExt': {'InNoRoutes': 0, ...} } - [:-1] on IpExt: removes :
107
            metrics[headers[0][:-1]] = dict(zip(headers, values))
108
109
        # record gauges
110
        for proto, mnames in self.gauges.items():
111
            if proto not in metrics:
112
                self.log.warn("netsnmp: unknown protocol: {0}".format(proto))
113
                del(self.gauges[proto])
114
                continue
115
            values = metrics[proto]
116
            for mname in mnames:
117
                if mname in values:
118
                    mstr = "{0}.{1}".format(proto, mname)
119
                    result.add(plumd.Int(mstr, values[mname]))
120
                else:
121
                    self.log.warn("netstat: unknown metric {0}".format(mname))
122
                    del(self.gauges[proto][mname])
123
                    continue
124
125
        # record rates
126
        for proto, mnames in self.rates.items():
127
            if proto not in metrics:
128
                self.log.warn("netsnmp: unknown protocol: {0}".format(proto))
129
                del(self.gauges[proto])
130
                continue
131
            values = metrics[proto]
132
            for mname in mnames:
133
                if mname in values:
134
                    mstr = "{0}.{1}".format(proto, mname)
135
                    mval = self.calc.per_second(mstr, int(values[mname]), ts)
136
                    result.add(plumd.Int(mstr, mval))
137
                else:
138
                    self.log.warn("netstat: unknown metric {0}".format(mname))
139
                    del(self.gauges[proto][mname])
140
                    continue
141
142
        return [result]
143