glances.amps.amp.GlancesAmp.time_until_refresh()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
#
2
# This file is part of Glances.
3
#
4
# SPDX-FileCopyrightText: 2024 Nicolas Hennion <[email protected]>
5
#
6
# SPDX-License-Identifier: LGPL-3.0-only
7
#
8
9
"""
10
I am your father...
11
12
...for all Glances Application Monitoring Processes (AMP).
13
14
AMP (Application Monitoring Process)
15
A Glances AMP is a Python script called (every *refresh* seconds) if:
16
- the AMP is *enabled* in the Glances configuration file
17
- a process is running (match the *regex* define in the configuration file)
18
The script should define a Amp (GlancesAmp) class with, at least, an update method.
19
The update method should call the set_result method to set the AMP return string.
20
The return string is a string with one or more line (\n between lines).
21
If the *one_line* var is true then the AMP will be displayed in one line.
22
"""
23
24
from glances.globals import u
25
from glances.logger import logger
26
from glances.timer import Timer
27
28
29
class GlancesAmp:
30
    """Main class for Glances AMP."""
31
32
    NAME = '?'
33
    VERSION = '?'
34
    DESCRIPTION = '?'
35
    AUTHOR = '?'
36
    EMAIL = '?'
37
38
    def __init__(self, name=None, args=None):
39
        """Init AMP class."""
40
        logger.debug(f"AMP - Init {self.NAME} version {self.VERSION}")
41
42
        # AMP name (= module name without glances_)
43
        if name is None:
44
            self.amp_name = self.__class__.__module__
45
        else:
46
            self.amp_name = name
47
48
        # Init the args
49
        self.args = args
50
51
        # Init the configs
52
        self.configs = {}
53
54
        # A timer is needed to only update every refresh seconds
55
        # Init to 0 in order to update the AMP on startup
56
        self.timer = Timer(0)
57
58
    def load_config(self, config):
59
        """Load AMP parameters from the configuration file."""
60
61
        # Read AMP configuration.
62
        # For ex, the AMP foo should have the following section:
63
        #
64
        # [foo]
65
        # enable=true
66
        # regex=\/usr\/bin\/nginx
67
        # refresh=60
68
        #
69
        # and optionally:
70
        #
71
        # one_line=false
72
        # option1=opt1
73
74
        amp_section = 'amp_' + self.amp_name
75
        if hasattr(config, 'has_section') and config.has_section(amp_section):
76
            logger.debug(f"AMP - {self.NAME}: Load configuration")
77
            for param, _ in config.items(amp_section):
78
                try:
79
                    self.configs[param] = config.get_float_value(amp_section, param)
80
                except ValueError:
81
                    self.configs[param] = config.get_value(amp_section, param).split(',')
82
                    if len(self.configs[param]) == 1:
83
                        self.configs[param] = self.configs[param][0]
84
                logger.debug(f"AMP - {self.NAME}: Load parameter: {param} = {self.configs[param]}")
85
        else:
86
            logger.debug(f"AMP - {self.NAME}: Can not find section {self.amp_name} in the configuration file")
87
            return False
88
89
        if self.enable():
90
            # Refresh option is mandatory
91
            for k in ['refresh']:
92
                if k not in self.configs:
93
                    logger.warning(
94
                        f"AMP - {self.NAME}: Can not find configuration key {k} in section {self.amp_name} "
95
                        f"(the AMP will be disabled)"
96
                    )
97
                    self.configs['enable'] = 'false'
98
        else:
99
            logger.debug(f"AMP - {self.NAME} is disabled")
100
101
        # Init the count to 0
102
        self.configs['count'] = 0
103
104
        return self.enable()
105
106
    def get(self, key):
107
        """Generic method to get the item in the AMP configuration"""
108
        if key in self.configs:
109
            return self.configs[key]
110
        return None
111
112
    def enable(self):
113
        """Return True|False if the AMP is enabled in the configuration file (enable=true|false)."""
114
        ret = self.get('enable')
115
        if ret is None:
116
            return False
117
        return ret.lower().startswith('true')
118
119
    def regex(self):
120
        """Return regular expression used to identified the current application."""
121
        return self.get('regex')
122
123
    def refresh(self):
124
        """Return refresh time in seconds for the current application monitoring process."""
125
        return self.get('refresh')
126
127
    def one_line(self):
128
        """Return True|False if the AMP should be displayed in one line (one_line=true|false)."""
129
        ret = self.get('one_line')
130
        if ret is None:
131
            return False
132
        return ret.lower().startswith('true')
133
134
    def time_until_refresh(self):
135
        """Return time in seconds until refresh."""
136
        return self.timer.get()
137
138
    def should_update(self):
139
        """Return True is the AMP should be updated
140
141
        Conditions for update:
142
        - AMP is enable
143
        - only update every 'refresh' seconds
144
        """
145
        if self.timer.finished():
146
            self.timer.set(self.refresh())
147
            self.timer.reset()
148
            return self.enable()
149
        return False
150
151
    def set_count(self, count):
152
        """Set the number of processes matching the regex"""
153
        self.configs['count'] = count
154
155
    def count(self):
156
        """Get the number of processes matching the regex"""
157
        return self.get('count')
158
159
    def count_min(self):
160
        """Get the minimum number of processes"""
161
        return self.get('countmin')
162
163
    def count_max(self):
164
        """Get the maximum number of processes"""
165
        return self.get('countmax')
166
167
    def set_result(self, result, separator=''):
168
        """Store the result (string) into the result key of the AMP
169
170
        If one_line is true then it replaces `\n` by the separator
171
        """
172
        if self.one_line():
173
            self.configs['result'] = u(result).replace('\n', separator)
174
        else:
175
            self.configs['result'] = u(result)
176
177
    def result(self):
178
        """Return the result of the AMP (as a string)"""
179
        ret = self.get('result')
180
        if ret is not None:
181
            ret = u(ret)
182
        return ret
183
184
    def update_wrapper(self, process_list):
185
        """Wrapper for the children update"""
186
        # Set the number of running process
187
        self.set_count(len(process_list))
188
        # Call the children update method
189
        if self.should_update():
190
            return self.update(process_list)
191
        return self.result()
192