Completed
Push — master ( 3dcd25...20576f )
by Nicolas
01:26
created

GlancesLogs.get_process_sort_key()   A

Complexity

Conditions 3

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2015 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 logs."""
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
# from glances.logger import logger
28
29
30
class GlancesLogs(object):
31
32
    """This class manages logs inside the Glances software.
33
34
    Logs is a list of list (stored in the self.logs_list var)
35
    item_state = "OK|CAREFUL|WARNING|CRITICAL"
36
    item_type = "CPU*|LOAD|MEM|MON"
37
    item_value = value
38
39
    Item is defined by:
40
      ["begin",
41
       "end",
42
       "WARNING|CRITICAL",
43
       "CPU|LOAD|MEM",
44
       MAX, AVG, MIN, SUM, COUNT,
45
       [top3 process list],
46
       "Processes description",
47
       "top sort key"]
48
    """
49
50
    def __init__(self):
51
        """Init the logs class."""
52
        # Maximum size of the logs list
53
        self.logs_max = 10
54
55
        # Init the logs list
56
        self.logs_list = []
57
58
    def get(self):
59
        """Return the raw logs list."""
60
        return self.logs_list
61
62
    def len(self):
63
        """Return the number of item in the logs list."""
64
        return self.logs_list.__len__()
65
66
    def __itemexist__(self, item_type):
67
        """Return the item position, if it exists.
68
69
        An item exist in the list if:
70
        * end is < 0
71
        * item_type is matching
72
        Return -1 if the item is not found.
73
        """
74
        for i in range(self.len()):
75
            if self.logs_list[i][1] < 0 and self.logs_list[i][3] == item_type:
76
                return i
77
        return -1
78
79
    def get_process_sort_key(self, item_type):
80
        """Return the process sort key"""
81
        # Process sort depending on alert type
82
        if item_type.startswith("MEM"):
83
            # Sort TOP process by memory_percent
84
            ret = 'memory_percent'
85
        elif item_type.startswith("CPU_IOWAIT"):
86
            # Sort TOP process by io_counters (only for Linux OS)
87
            ret = 'io_counters'
88
        else:
89
            # Default sort is...
90
            ret = 'cpu_percent'
91
        return ret
92
93
    def set_process_sort(self, item_type):
94
        """Define the process auto sort key from the alert type."""
95
        glances_processes.auto_sort = True
96
        glances_processes.sort_key = self.get_process_sort_key(item_type)
97
98
    def reset_process_sort(self):
99
        """Reset the process auto sort key."""
100
        # Default sort is...
101
        glances_processes.auto_sort = True
102
        glances_processes.sort_key = 'cpu_percent'
103
104
    def add(self, item_state, item_type, item_value,
105
            proc_list=None, proc_desc="", peak_time=6):
106
        """Add a new item to the logs list.
107
108
        If 'item' is a 'new one', add the new item at the beginning of
109
        the logs list.
110
        If 'item' is not a 'new one', update the existing item.
111
        If event < peak_time the the alert is not setoff.
112
        """
113
        proc_list = proc_list or glances_processes.getalllist()
114
115
        # Add or update the log
116
        item_index = self.__itemexist__(item_type)
117
        if item_index < 0:
118
            # Item did not exist, add if WARNING or CRITICAL
119
            self._create_item(item_state, item_type, item_value,
120
                              proc_list, proc_desc, peak_time)
121
        else:
122
            # Item exist, update
123
            self._update_item(item_index, item_state, item_type, item_value,
124
                              proc_list, proc_desc, peak_time)
125
126
        return self.len()
127
128
    def _create_item(self, item_state, item_type, item_value,
129
                     proc_list, proc_desc, peak_time):
130
        """Create a new item in the log list"""
131
        if item_state == "WARNING" or item_state == "CRITICAL":
132
            # Define the automatic process sort key
133
            self.set_process_sort(item_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
                item_state,  # STATE: WARNING|CRITICAL
142
                item_type,  # TYPE: CPU, LOAD, MEM...
143
                item_value,  # MAX
144
                item_value,  # AVG
145
                item_value,  # MIN
146
                item_value,  # SUM
147
                1,  # COUNT
148
                [],  # TOP 3 PROCESS LIST
149
                proc_desc,  # MONITORED PROCESSES DESC
150
                'cpu_percent']  # TOP PROCESS SORTKEY
151
152
            # Add the item to the list
153
            self.logs_list.insert(0, item)
154
            if self.len() > self.logs_max:
155
                self.logs_list.pop()
156
157
            return True
158
        else:
159
            return False
160
161
    def _update_item(self, item_index, item_state, item_type, item_value,
162
                     proc_list, proc_desc, peak_time):
163
        """Update a item in the log list"""
164
        if item_state == "OK" or item_state == "CAREFUL":
165
            # Reset the automatic process sort key
166
            self.reset_process_sort()
167
168
            endtime = time.mktime(datetime.now().timetuple())
169
            if endtime - self.logs_list[item_index][0] > peak_time:
170
                # If event is > peak_time seconds
171
                self.logs_list[item_index][1] = endtime
172
            else:
173
                # If event <= peak_time seconds, ignore
174
                self.logs_list.remove(self.logs_list[item_index])
175
        else:
176
            # Update the item
177
178
            # State
179
            if item_state == "CRITICAL":
180
                self.logs_list[item_index][2] = item_state
181
182
            # Value
183
            if item_value > self.logs_list[item_index][4]:
184
                # MAX
185
                self.logs_list[item_index][4] = item_value
186
            elif item_value < self.logs_list[item_index][6]:
187
                # MIN
188
                self.logs_list[item_index][6] = item_value
189
            # AVG (compute average value)
190
            self.logs_list[item_index][7] += item_value
191
            self.logs_list[item_index][8] += 1
192
            self.logs_list[item_index][5] = (self.logs_list[item_index][7] /
193
                                             self.logs_list[item_index][8])
194
195
            # TOP PROCESS LIST (only for CRITICAL ALERT)
196
            if item_state == "CRITICAL":
197
                # Sort the current process list to retreive the TOP 3 processes
198
                self.logs_list[item_index][9] = sort_stats(proc_list, glances_processes.sort_key)[0:3]
199
                self.logs_list[item_index][11] = glances_processes.sort_key
200
201
            # MONITORED PROCESSES DESC
202
            self.logs_list[item_index][10] = proc_desc
203
204
        return True
205
206
    def clean(self, critical=False):
207
        """Clean the logs list by deleting finished items.
208
209
        By default, only delete WARNING message.
210
        If critical = True, also delete CRITICAL message.
211
        """
212
        # Create a new clean list
213
        clean_logs_list = []
214
        while self.len() > 0:
215
            item = self.logs_list.pop()
216
            if item[1] < 0 or (not critical and item[2].startswith("CRITICAL")):
217
                clean_logs_list.insert(0, item)
218
        # The list is now the clean one
219
        self.logs_list = clean_logs_list
220
        return self.len()
221
222
glances_logs = GlancesLogs()
223