Completed
Push — master ( 777314...e29a15 )
by Nicolas
06:47 queued 02:26
created

Plugin.update()   D

Complexity

Conditions 12

Size

Total Lines 56
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 40
nop 1
dl 0
loc 56
rs 4.8
c 0
b 0
f 0

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 glances.plugins.glances_connections.Plugin.update() 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
# This file is part of Glances.
4
#
5
# Copyright (C) 2019 Nicolargo <[email protected]>
6
#
7
# Glances is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU Lesser General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Glances is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Lesser General Public License for more details.
16
#
17
# You should have received a copy of the GNU Lesser General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
"""Connections plugin."""
21
from __future__ import unicode_literals
22
23
from glances.logger import logger
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
24
from glances.timer import getTimeSinceLastUpdate
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
Unused Code introduced by
Unused getTimeSinceLastUpdate imported from glances.timer
Loading history...
25
from glances.plugins.glances_plugin import GlancesPlugin
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
26
from glances.compat import n, u, b, nativestr
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
Unused Code introduced by
Unused b imported from glances.compat
Loading history...
Unused Code introduced by
Unused u imported from glances.compat
Loading history...
Unused Code introduced by
Unused n imported from glances.compat
Loading history...
27
28
import psutil
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
introduced by
Unable to import 'psutil'
Loading history...
29
30
# Define the history items list
31
# items_history_list = [{'name': 'rx',
32
#                        'description': 'Download rate per second',
33
#                        'y_unit': 'bit/s'},
34
#                       {'name': 'tx',
35
#                        'description': 'Upload rate per second',
36
#                        'y_unit': 'bit/s'}]
37
38
39
class Plugin(GlancesPlugin):
40
    """Glances connections plugin.
41
42
    stats is a dict
43
    """
44
45
    status_list = [psutil.CONN_LISTEN,
46
                   psutil.CONN_ESTABLISHED]
47
    initiated_states = [psutil.CONN_SYN_SENT,
48
                        psutil.CONN_SYN_RECV]
49
    terminated_states = [psutil.CONN_FIN_WAIT1,
50
                         psutil.CONN_FIN_WAIT2,
51
                         psutil.CONN_TIME_WAIT,
52
                         psutil.CONN_CLOSE,
53
                         psutil.CONN_CLOSE_WAIT,
54
                         psutil.CONN_LAST_ACK]
55
    conntrack = {'nf_conntrack_count': '/proc/sys/net/netfilter/nf_conntrack_count',
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (84/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
56
                 'nf_conntrack_max': '/proc/sys/net/netfilter/nf_conntrack_max'}
57
58
    def __init__(self, args=None, config=None):
59
        """Init the plugin."""
60
        super(Plugin, self).__init__(args=args,
61
                                     config=config,
62
                                     # items_history_list=items_history_list,
63
                                     stats_init_value={})
64
65
        # We want to display the stat in the curse interface
66
        self.display_curse = True
67
68
        # This plugin is composed if net_connections and nf_conntrack
69
        # Enabled by default
70
        self.net_connections_enabled = True
71
        self.nf_conntrack_enabled = True
72
73
    @GlancesPlugin._check_decorator
74
    @GlancesPlugin._log_result_decorator
75
    def update(self):
76
        """Update connections stats using the input method.
77
78
        Stats is a dict
79
        """
80
        # Init new stats
81
        stats = self.get_init_value()
82
83
        if self.input_method == 'local':
84
            # Update stats using the PSUtils lib
85
86
            # Grab network interface stat using the psutil net_connections method
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
87
            if self.net_connections_enabled:
88
                try:
89
                    net_connections = psutil.net_connections(kind="tcp")
90
                except Exception as e:
0 ignored issues
show
Best Practice introduced by
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
Coding Style Naming introduced by
The name e does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
91
                    logger.debug('Can not get network connections stats ({})'.format(e))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (88/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
92
                    self.net_connections_enabled = False
93
                    self.stats = stats
94
                    return self.stats
95
96
                for s in self.status_list:
0 ignored issues
show
Coding Style Naming introduced by
The name s does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
97
                    stats[s] = len([c for c in net_connections if c.status == s])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
98
                initiated = 0
99
                for s in self.initiated_states:
0 ignored issues
show
Coding Style Naming introduced by
The name s does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
100
                    stats[s] = len([c for c in net_connections if c.status == s])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
101
                    initiated += stats[s]
102
                stats['initiated'] = initiated
103
                terminated = 0
104
                for s in self.initiated_states:
0 ignored issues
show
Coding Style Naming introduced by
The name s does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
105
                    stats[s] = len([c for c in net_connections if c.status == s])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
106
                    terminated += stats[s]
107
                stats['terminated'] = terminated
108
109
            if self.nf_conntrack_enabled:
110
                # Grab connections track directly from the /proc file
111
                for i in self.conntrack:
112
                    try:
113
                        with open(self.conntrack[i], 'r') as f:
0 ignored issues
show
Coding Style Naming introduced by
The name f does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
114
                            stats[i] = float(f.readline().rstrip("\n"))
115
                    except IOError as e:
0 ignored issues
show
Coding Style Naming introduced by
The name e does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
116
                        logger.debug('Can not get network connections track ({})'.format(e))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (92/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
117
                        self.nf_conntrack_enabled = False
118
                        self.stats = stats
119
                        return self.stats
120
                stats['nf_conntrack_percent'] = stats['nf_conntrack_count'] * 100 / stats['nf_conntrack_max']
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (109/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
introduced by
division w/o __future__ statement
Loading history...
121
122
        elif self.input_method == 'snmp':
123
            # Update stats using SNMP
124
            pass
125
126
        # Update the stats
127
        self.stats = stats
128
        return self.stats
129
130
    def update_views(self):
131
        """Update stats views."""
132
        # Call the father's method
133
        super(Plugin, self).update_views()
134
135
        # Add specifics informations
136
        try:
137
            # Alert and log
138
            if self.nf_conntrack_enabled:
139
                self.views['nf_conntrack_percent']['decoration'] = self.get_alert(header='nf_conntrack_percent')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (112/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
140
        except KeyError:
141
            # try/except mandatory for Windows compatibility (no conntrack stats)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
142
            pass
143
144
    def msg_curse(self, args=None, max_width=None):
145
        """Return the dict to display in the curse interface."""
146
        # Init the return message
147
        ret = []
148
149
        # Only process if stats exist and display plugin enable...
150
        if not self.stats or self.is_disable():
151
            return ret
152
153
        # Header
154
        if self.net_connections_enabled or self.nf_conntrack_enabled:
155
            msg = '{}'.format('TCP CONNECTIONS')
156
            ret.append(self.curse_add_line(msg, "TITLE"))
157
        # Connections status
158
        if self.net_connections_enabled:
159
            for s in [psutil.CONN_LISTEN, 'initiated', psutil.CONN_ESTABLISHED, 'terminated']:
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (94/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style Naming introduced by
The name s does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
160
                ret.append(self.curse_new_line())
161
                msg = '{:{width}}'.format(nativestr(s).capitalize(), width=len(s))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
162
                ret.append(self.curse_add_line(msg))
163
                msg = '{:>{width}}'.format(self.stats[s], width=max_width - len(s) + 2)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (87/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
164
                ret.append(self.curse_add_line(msg))
165
        # Connections track
166
        if self.nf_conntrack_enabled:
167
            s = 'Tracked'
0 ignored issues
show
Coding Style Naming introduced by
The name s does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
168
            ret.append(self.curse_new_line())
169
            msg = '{:{width}}'.format(nativestr(s).capitalize(), width=len(s))
170
            ret.append(self.curse_add_line(msg))
171
            msg = '{:>{width}}'.format('{:0.0f}/{:0.0f}'.format(self.stats['nf_conntrack_count'],
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (97/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
172
                                                                self.stats['nf_conntrack_max']),
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (96/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
173
                                       width=max_width - len(s) + 2)
174
            ret.append(self.curse_add_line(msg,
175
                                           self.get_views(key='nf_conntrack_percent',
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (85/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
176
                                                          option='decoration')))
177
178
        return ret
179