Test Failed
Push — master ( 183265...afa1da )
by Nicolas
03:15 queued 16s
created

glances.cpu_percent.CpuPercent.get_percpu()   C

Complexity

Conditions 10

Size

Total Lines 38
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 30
nop 1
dl 0
loc 38
rs 5.9999
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like glances.cpu_percent.CpuPercent.get_percpu() 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
#
2
# This file is part of Glances.
3
#
4
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <[email protected]>
5
#
6
# SPDX-License-Identifier: LGPL-3.0-only
7
#
8
9
"""CPU percent stats shared between CPU and Quicklook plugins."""
10
11
import psutil
12
13
from glances.logger import logger
14
from glances.timer import Timer
15
16
17
class CpuPercent:
18
    """Get and store the CPU percent."""
19
20
    def __init__(self, cached_timer_cpu=2):
21
        # cached_timer_cpu is the minimum time interval between stats updates
22
        # since last update is passed (will retrieve old cached info instead)
23
        self.cached_timer_cpu = cached_timer_cpu
24
        # psutil.cpu_freq() consumes lots of CPU
25
        # So refresh CPU frequency stats every refresh * 2
26
        self.cached_timer_cpu_info = cached_timer_cpu * 2
27
28
        # Get CPU name
29
        self.timer_cpu_info = Timer(0)
30
        self.cpu_info = {'cpu_name': self.__get_cpu_name(), 'cpu_hz_current': None, 'cpu_hz': None}
31
32
        # Warning from PsUtil documentation
33
        # The first time this function is called with interval = 0.0 or None
34
        # it will return a meaningless 0.0 value which you are supposed to ignore.
35
        self.timer_cpu = Timer(0)
36
        self.cpu_percent = self.get_cpu()
37
        self.timer_percpu = Timer(0)
38
        self.percpu_percent = self.get_percpu()
39
40
    def get_key(self):
41
        """Return the key of the per CPU list."""
42
        return 'cpu_number'
43
44
    def get_info(self):
45
        """Get additional information about the CPU"""
46
        # Never update more than 1 time per cached_timer_cpu_info
47
        if self.timer_cpu_info.finished() and hasattr(psutil, 'cpu_freq'):
48
            # Get the CPU freq current/max
49
            try:
50
                cpu_freq = psutil.cpu_freq()
51
            except Exception as e:
52
                logger.debug(f'Can not grab CPU information ({e})')
53
            else:
54
                if hasattr(cpu_freq, 'current'):
55
                    self.cpu_info['cpu_hz_current'] = cpu_freq.current
56
                else:
57
                    self.cpu_info['cpu_hz_current'] = None
58
                if hasattr(cpu_freq, 'max'):
59
                    self.cpu_info['cpu_hz'] = cpu_freq.max
60
                else:
61
                    self.cpu_info['cpu_hz'] = None
62
                # Reset timer for cache
63
                self.timer_cpu_info.reset(duration=self.cached_timer_cpu_info)
64
        return self.cpu_info
65
66
    def __get_cpu_name(self):
67
        # Get the CPU name once from the /proc/cpuinfo file
68
        # Read the first line with the "model name" ("Model" for Raspberry Pi)
69
        ret = None
70
        try:
71
            cpuinfo_file = open('/proc/cpuinfo').readlines()
72
        except (FileNotFoundError, PermissionError):
73
            pass
74
        else:
75
            for line in cpuinfo_file:
76
                if line.startswith('model name') or line.startswith('Model') or line.startswith('cpu model'):
77
                    ret = line.split(':')[1].strip()
78
                    break
79
        return ret if ret else 'CPU'
80
81
    def get_cpu(self):
82
        """Update and/or return the CPU using the psutil library."""
83
        # Never update more than 1 time per cached_timer_cpu
84
        if self.timer_cpu.finished():
85
            # Reset timer for cache
86
            self.timer_cpu.reset(duration=self.cached_timer_cpu)
87
            # Update the stats
88
            self.cpu_percent = psutil.cpu_percent(interval=0.0)
89
        return self.cpu_percent
90
91
    def get_percpu(self):
92
        """Update and/or return the per CPU list using the psutil library."""
93
        # Never update more than 1 time per cached_timer_cpu
94
        if self.timer_percpu.finished():
95
            # Reset timer for cache
96
            self.timer_percpu.reset(duration=self.cached_timer_cpu)
97
            # Get stats
98
            percpu_percent = []
99
            psutil_percpu = enumerate(psutil.cpu_times_percent(interval=0.0, percpu=True))
100
            for cpu_number, cputimes in psutil_percpu:
101
                cpu = {
102
                    'key': self.get_key(),
103
                    'cpu_number': cpu_number,
104
                    'total': round(100 - cputimes.idle, 1),
105
                    'user': cputimes.user,
106
                    'system': cputimes.system,
107
                    'idle': cputimes.idle,
108
                }
109
                # The following stats are for API purposes only
110
                if hasattr(cputimes, 'nice'):
111
                    cpu['nice'] = cputimes.nice
112
                if hasattr(cputimes, 'iowait'):
113
                    cpu['iowait'] = cputimes.iowait
114
                if hasattr(cputimes, 'irq'):
115
                    cpu['irq'] = cputimes.irq
116
                if hasattr(cputimes, 'softirq'):
117
                    cpu['softirq'] = cputimes.softirq
118
                if hasattr(cputimes, 'steal'):
119
                    cpu['steal'] = cputimes.steal
120
                if hasattr(cputimes, 'guest'):
121
                    cpu['guest'] = cputimes.guest
122
                if hasattr(cputimes, 'guest_nice'):
123
                    cpu['guest_nice'] = cputimes.guest_nice
124
                # Append new CPU to the list
125
                percpu_percent.append(cpu)
126
            # Update stats
127
            self.percpu_percent = percpu_percent
128
        return self.percpu_percent
129
130
131
# CpuPercent instance shared between plugins
132
cpu_percent = CpuPercent()
133