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

Netstat   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 119
Duplicated Lines 57.14 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 68
loc 119
rs 10
wmc 15

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __init__() 0 14 1
F check() 68 68 13
A poll() 0 6 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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