Netstat.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 1
1
# -*- coding: utf-8 -*-
2
"""Reader for netstat metrics from /proc on Linux."""
3
4
import time
5
from collections import deque
6
7
import plumd
8
from plumd.util import Differential
9
10
__author__ = 'Kenny Freeman'
11
__email__ = '[email protected]'
12
__license__ = "ISCL"
13
__docformat__ = 'reStructuredText'
14
15
16
class Netstat(plumd.Reader):
17
    """Plugin to measure various kernel metrics from /proc."""
18
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
    def poll(self):
60
        """Poll for kernel metrics under proc file net/netstat.
61
62
        :rtype: ResultSet
63
        """
64
        return plumd.ResultSet(self.check())
65 View Code Duplication
66
    def check(self):
67
        """Return detailed network statitistics proc file net/netstat.
68
69
        Note: ECT1Pkts and ECT0Pkts relate to ECT congestion notifications.
70
71
        :rtype: plumd.Result
72
        """
73
        # what metrics do we want to record?
74
        result = plumd.Result("netstat")
75
76
        # read the proc file
77
        dat = None
78
        with open(self.proc_file, 'r') as f:
79
            dat = f.read().strip().split("\n")
80
81
        # timestamp for Differential calculations
82
        ts = time.time()
83
84
        # split values into lists
85
        dlist = deque([entry.split() for entry in dat])
86
87
        # put lists into key: value dict
88
        metrics = {}
89
        while dlist:
90
            headers = dlist.popleft()
91
            values = dlist.popleft()
92
            # { 'IpExt': {'InNoRoutes': 0, ...} } - [:-1] on IpExt: removes :
93
            metrics[headers[0][:-1]] = dict(zip(headers, values))
94
95
        # record gauges
96
        for ext, mnames in self.gauges.items():
97
            if ext not in metrics:
98
                self.log.warn("netstat: unknown extension: {0}".format(ext))
99
                del self.gauges[ext]
100
                continue
101
            values = metrics[ext]
102
            for mname in mnames:
103
                if mname in values:
104
                    mstr = "{0}.{1}".format(ext, mname)
105
                    result.add(plumd.Int(mstr, values[mname]))
106
                else:
107
                    self.log.warn("netstat: unknown metric {0}".format(mname))
108
                    self.gauges[ext].remove(mname)
109
110
        # record rates
111
        for ext, mnames in self.rates.items():
112
            if ext not in metrics:
113
                self.log.warn("netstat: unknown extension: {0}".format(ext))
114
                del self.rates[ext]
115
                continue
116
            values = metrics[ext]
117
            for mname in mnames:
118
                if mname in values:
119
                    mstr = "{0}.{1}".format(ext, mname)
120
                    mval = self.calc.per_second(mstr, float(values[mname]), ts)
121
                    result.add(plumd.Float(mstr, mval))
122
                else:
123
                    self.log.warn("netstat: unknown metric {0}".format(mname))
124
                    self.rates[ext].remove(mname)
125
126
        return [result]
127