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

Netstat.check()   C

Complexity

Conditions 9

Size

Total Lines 55

Duplication

Lines 55
Ratio 100 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 9
c 2
b 1
f 0
dl 55
loc 55
rs 5.4159

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 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_record': {
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
    }
42
43
    def __init__(self, log, config):
44
        """Plugin to measure various kernel metrics from /proc.
45
46
        :param log: A logger
47
        :type log: logging.RootLogger
48
        :param config: a plumd.config.Conf configuration helper instance.
49
        :type config: plumd.config.Conf
50
        """
51
        super(Netstat, self).__init__(log, config)
52
        self.config.defaults(Netstat.defaults)
53
        self.calc = Differential()
54
        self.proc_file = "{0}/net/netstat".format(config.get('proc_path'))
55
56
57
    def poll(self):
58
        """Poll for kernel metrics under proc file net/netstat.
59
60
        :rtype: ResultSet
61
        """
62
        return plumd.ResultSet(self.check())
63
64
65 View Code Duplication
    def check(self):
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
66
        """Return detailed network statitistics proc file net/netstat.
67
68
        Note: add entries to the configuration value 'proc_netstat_record'
69
        to record them. See /proc/net/netstat for a list of available metrics.
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
        record = self.config.get('proc_netstat_record')
77
        result = plumd.Result("netstat")
78
79
        # read the proc file
80
        dat = None
81
        with open(self.proc_file, 'r') as f:
82
            dat = f.read().strip().split("\n")
83
84
        # timestamp for Differential calculations
85
        ts = time.time()
86
87
        # should always have a header row and value row, ie. divisible by 2
88
        if len(dat) % 2 != 0:
89
            self.log.error("netstat: cannot parse {0}".format(self.proc_file))
90
            return result
91
92
        # split values into lists
93
        dlist = deque()
94
        for entry in dat:
95
            dlist.append(entry.split())
96
97
        # put lists into key: value dict
98
        metrics = {}
99
        while dlist:
100
            headers = dlist.popleft()
101
            values = dlist.popleft()
102
            # { 'IpExt': {'InNoRoutes': 0, ...} } - [:-1] on IpExt: removes :
103
            metrics[headers[0][:-1]] = dict(zip(headers, values))
104
105
        # now, we have a list of items to record, just need to record them
106
        for ext, mnames in record.items():
107
            if ext not in metrics:
108
                self.log.warn("netstat: unknown extension: {0}".format(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
                    mval = self.calc.per_second(mstr, int(values[mname]), ts)
115
                    result.add(plumd.Int(mstr, mval))
116
                else:
117
                    self.log.warn("netstat: unknown metric {0}".format(mname))
118
119
        return [result]
120