Test Failed
Push — develop ( abf64f...1d1151 )
by Nicolas
02:59
created

glances/events.py (1 issue)

Checks old division

Minor
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
"""Manage Glances events (previously Glances logs in Glances < 3.1)."""
21
22
import time
23
from datetime import datetime
24
25
from glances.compat import range
26
from glances.processes import glances_processes, sort_stats
27
28
29
class GlancesEvents(object):
30
31
    """This class manages events inside the Glances software.
32
33
    Events is a list of event (stored in the self.events_list var)
34
    event_state = "OK|CAREFUL|WARNING|CRITICAL"
35
    event_type = "CPU*|LOAD|MEM|MON"
36
    event_value = value
37
38
    Item (or event) is defined by:
39
      ["begin",
40
       "end",
41
       "WARNING|CRITICAL",
42
       "CPU|LOAD|MEM",
43
       MAX, AVG, MIN, SUM, COUNT,
44
       [top3 process list],
45
       "Processes description",
46
       "top sort key"]
47
    """
48
49
    def __init__(self):
50
        """Init the events class."""
51
        # Maximum size of the events list
52
        self.events_max = 10
53
54
        # Init the logs list
55
        self.events_list = []
56
57
    def get(self):
58
        """Return the raw events list."""
59
        return self.events_list
60
61
    def len(self):
62
        """Return the number of events in the logs list."""
63
        return self.events_list.__len__()
64
65
    def __event_exist(self, event_type):
66
        """Return the event position, if it exists.
67
68
        An event exist if:
69
        * end is < 0
70
        * event_type is matching
71
        Return -1 if the item is not found.
72
        """
73
        for i in range(self.len()):
74
            if self.events_list[i][1] < 0 and self.events_list[i][3] == event_type:
75
                return i
76
        return -1
77
78
    def get_event_sort_key(self, event_type):
79
        """Return the process sort key"""
80
        # Process sort depending on alert type
81
        if event_type.startswith("MEM"):
82
            # Sort TOP process by memory_percent
83
            ret = 'memory_percent'
84
        elif event_type.startswith("CPU_IOWAIT"):
85
            # Sort TOP process by io_counters (only for Linux OS)
86
            ret = 'io_counters'
87
        else:
88
            # Default sort is...
89
            ret = 'cpu_percent'
90
        return ret
91
92
    def set_process_sort(self, event_type):
93
        """Define the process auto sort key from the alert type."""
94
        if glances_processes.auto_sort:
95
            glances_processes.sort_key = self.get_event_sort_key(event_type)
96
97
    def reset_process_sort(self):
98
        """Reset the process auto sort key."""
99
        if glances_processes.auto_sort:
100
            glances_processes.sort_key = 'cpu_percent'
101
102
    def add(self, event_state, event_type, event_value,
103
            proc_list=None, proc_desc="", peak_time=6):
104
        """Add a new item to the logs list.
105
106
        If 'event' is a 'new one', add it at the beginning of the list.
107
        If 'event' is not a 'new one', update the list .
108
        If event < peak_time then the alert is not set.
109
        """
110
        proc_list = proc_list or glances_processes.getlist()
111
112
        # Add or update the log
113
        event_index = self.__event_exist(event_type)
114
        if event_index < 0:
115
            # Event did not exist, add it
116
            self._create_event(event_state, event_type, event_value,
117
                               proc_list, proc_desc, peak_time)
118
        else:
119
            # Event exist, update it
120
            self._update_event(event_index, event_state, event_type, event_value,
121
                               proc_list, proc_desc, peak_time)
122
123
        return self.len()
124
125
    def _create_event(self, event_state, event_type, event_value,
126
                      proc_list, proc_desc, peak_time):
127
        """Add a new item in the log list.
128
129
        Item is added only if the criticity (event_state) is WARNING or CRITICAL.
130
        """
131
        if event_state == "WARNING" or event_state == "CRITICAL":
132
            # Define the automatic process sort key
133
            self.set_process_sort(event_type)
134
135
            # Create the new log item
136
            # Time is stored in Epoch format
137
            # Epoch -> DMYHMS = datetime.fromtimestamp(epoch)
138
            item = [
139
                time.mktime(datetime.now().timetuple()),  # START DATE
140
                -1,  # END DATE
141
                event_state,  # STATE: WARNING|CRITICAL
142
                event_type,  # TYPE: CPU, LOAD, MEM...
143
                event_value,  # MAX
144
                event_value,  # AVG
145
                event_value,  # MIN
146
                event_value,  # SUM
147
                1,  # COUNT
148
                [],  # TOP 3 PROCESS LIST
149
                proc_desc,  # MONITORED PROCESSES DESC
150
                glances_processes.sort_key]  # TOP PROCESS SORTKEY
151
152
            # Add the item to the list
153
            self.events_list.insert(0, item)
154
155
            # Limit the list to 'events_max' items
156
            if self.len() > self.events_max:
157
                self.events_list.pop()
158
159
            return True
160
        else:
161
            return False
162
163
    def _update_event(self, event_index, event_state, event_type, event_value,
164
                      proc_list, proc_desc, peak_time):
165
        """Update an event in the list"""
166
        if event_state == "OK" or event_state == "CAREFUL":
167
            # Reset the automatic process sort key
168
            self.reset_process_sort()
169
170
            # Set the end of the events
171
            endtime = time.mktime(datetime.now().timetuple())
172
            if endtime - self.events_list[event_index][0] > peak_time:
173
                # If event is > peak_time seconds
174
                self.events_list[event_index][1] = endtime
175
            else:
176
                # If event <= peak_time seconds, ignore
177
                self.events_list.remove(self.events_list[event_index])
178
        else:
179
            # Update the item
180
            self.set_process_sort(event_type)
181
182
            # State
183
            if event_state == "CRITICAL":
184
                self.events_list[event_index][2] = event_state
185
            # Min value
186
            self.events_list[event_index][6] = min(self.events_list[event_index][6],
187
                                                   event_value)
188
            # Max value
189
            self.events_list[event_index][4] = max(self.events_list[event_index][4],
190
                                                   event_value)
191
            # Average value
192
            self.events_list[event_index][7] += event_value
193
            self.events_list[event_index][8] += 1
194
            self.events_list[event_index][5] = (self.events_list[event_index][7] /
0 ignored issues
show
division w/o __future__ statement
Loading history...
195
                                                self.events_list[event_index][8])
196
197
            # TOP PROCESS LIST (only for CRITICAL ALERT)
198
            if event_state == "CRITICAL":
199
                events_sort_key = self.get_event_sort_key(event_type)
200
                # Sort the current process list to retreive the TOP 3 processes
201
                self.events_list[event_index][9] = sort_stats(proc_list,
202
                                                              events_sort_key)[0:3]
203
                self.events_list[event_index][11] = events_sort_key
204
205
            # MONITORED PROCESSES DESC
206
            self.events_list[event_index][10] = proc_desc
207
208
        return True
209
210
    def clean(self, critical=False):
211
        """Clean the logs list by deleting finished items.
212
213
        By default, only delete WARNING message.
214
        If critical = True, also delete CRITICAL message.
215
        """
216
        # Create a new clean list
217
        clean_events_list = []
218
        while self.len() > 0:
219
            item = self.events_list.pop()
220
            if item[1] < 0 or (not critical and item[2].startswith("CRITICAL")):
221
                clean_events_list.insert(0, item)
222
        # The list is now the clean one
223
        self.events_list = clean_events_list
224
        return self.len()
225
226
227
glances_events = GlancesEvents()
228