Completed
Branch master (7e8cc2)
by Kenny
03:21 queued 19s
created

Netstat.check()   F

Complexity

Conditions 13

Size

Total Lines 68

Duplication

Lines 68
Ratio 100 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 13
c 2
b 1
f 0
dl 68
loc 68
rs 2.5418

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 Netstat.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 get_file_list
15
16
17
class Netstat(plumd.plugins.Reader):
18
    """Plugin to measure various kernel metrics from /proc."""
19
    defaults = {
20
        'poll.interval': 10,
21
        'proc_path': '/proc',
22
        'proc_netstat_gauges': {
23
            'TcpExt': ["SyncookiesSent", "SyncookiesRecv",
24
                "SyncookiesFailed","OutOfWindowIcmps","TW","TWRecycled",
25
                "TWKilled","DelayedACKLost", "ListenOverflows",
26
                "ListenDrops","TCPLostRetransmit","TCPRenoFailures",
27
                "TCPSackFailures","TCPLossFailures","TCPFastRetrans",
28
                "TCPForwardRetrans","TCPSlowStartRetrans","TCPTimeouts",
29
                "TCPLossProbes","TCPLossProbeRecovery", "TCPAbortOnData",
30
                "TCPAbortOnClose", "TCPAbortOnMemory","TCPAbortOnTimeout",
31
                "TCPAbortOnLinger","TCPAbortFailed", "TCPMemoryPressures",
32
                "TCPBacklogDrop", "TCPMinTTLDrop","TCPTimeWaitOverflow",
33
                "TCPFastOpenActive","TCPFastOpenActiveFail",
34
                "TCPFastOpenPassive","TCPFastOpenPassiveFail",
35
                "TCPFastOpenListenOverflow","TCPSynRetrans"],
36
            'IpExt': ["InNoRoutes", "InTruncatedPkts", "InBcastPkts",
37
                "OutBcastPkts", "InOctets", "OutOctets", "InBcastOctets",
38
                "OutBcastOctets","InCsumErrors","InNoECTPkts","InECT1Pkts",
39
                "InECT0Pkts","InCEPkts"]
40
        },
41
        'proc_netstat_rates': {}
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(Netstat, self).__init__(log, config)
53
        self.config.defaults(Netstat.defaults)
54
        self.calc = Differential()
55
        self.proc_file = "{0}/net/netstat".format(config.get('proc_path'))
56
        self.gauges = self.config.get('proc_netstat_gauges')
57
        self.rates = self.config.get('proc_netstat_rates')
58
59
60
    def poll(self):
61
        """Poll for kernel metrics under proc file net/netstat.
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 detailed network statitistics proc file net/netstat.
70
71
        Note: ECT1Pkts and ECT0Pkts relate to ECT congestion notifications.
72
73
        :rtype: plumd.Result
74
        """
75
        # what metrics do we want to record?
76
        result = plumd.Result("netstat")
77
78
        # read the proc file
79
        dat = None
80
        with open(self.proc_file, 'r') as f:
81
            dat = f.read().strip().split("\n")
82
83
        # timestamp for Differential calculations
84
        ts = time.time()
85
86
        # should always have a header row and value row, ie. divisible by 2
87
        if len(dat) % 2 != 0:
88
            self.log.error("netstat: cannot parse {0}".format(self.proc_file))
89
            return result
90
91
        # split values into lists
92
        dlist = deque()
93
        for entry in dat:
94
            dlist.append(entry.split())
95
96
        # put lists into key: value dict
97
        metrics = {}
98
        while dlist:
99
            headers = dlist.popleft()
100
            values = dlist.popleft()
101
            # { 'IpExt': {'InNoRoutes': 0, ...} } - [:-1] on IpExt: removes :
102
            metrics[headers[0][:-1]] = dict(zip(headers, values))
103
104
        # record gauges
105
        for ext, mnames in self.gauges.items():
106
            if ext not in metrics:
107
                self.log.warn("netstat: unknown extension: {0}".format(ext))
108
                del(self.gauges[ext])
109
                continue
110
            values = metrics[ext]
111
            for mname in mnames:
112
                if mname in values:
113
                    mstr = "{0}.{1}".format(ext, mname)
114
                    result.add(plumd.Int(mstr, values[mname]))
115
                else:
116
                    self.log.warn("netstat: unknown metric {0}".format(mname))
117
                    del(self.gauges[ext][mname])
118
119
        # record rates
120
        for ext, mnames in self.rates.items():
121
            if ext not in metrics:
122
                self.log.warn("netstat: unknown extension: {0}".format(ext))
123
                del(self.rates[ext])
124
                continue
125
            values = metrics[ext]
126
            for mname in mnames:
127
                if mname in values:
128
                    mstr = "{0}.{1}".format(ext, mname)
129
                    mval = self.calc.per_second(mstr, int(values[mname]), ts)
130
                    result.add(plumd.Float(mstr, mval))
131
                else:
132
                    self.log.warn("netstat: unknown metric {0}".format(mname))
133
                    del(self.rates[ext][mname])
134
135
        return [result]
136