mirror of
https://github.com/nicolargo/glances.git
synced 2024-11-24 05:15:47 +03:00
Rename Glances logs to Glances events
This commit is contained in:
parent
dce2f6a5f6
commit
ea84db45ae
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
@ -1,17 +1,16 @@
|
||||
.. _logs:
|
||||
.. _events:
|
||||
|
||||
Logs
|
||||
====
|
||||
events
|
||||
======
|
||||
|
||||
.. image:: ../_static/logs.png
|
||||
.. image:: ../_static/events.png
|
||||
|
||||
A log messages list is displayed in the bottom of the screen if and only
|
||||
if:
|
||||
Events list is displayed in the bottom of the screen if and only if:
|
||||
|
||||
- at least one ``WARNING`` or ``CRITICAL`` alert was occurred
|
||||
- space is available in the bottom of the console/terminal
|
||||
|
||||
Each alert message displays the following information:
|
||||
Each event message displays the following information:
|
||||
|
||||
1. start datetime
|
||||
2. duration if alert is terminated or `ongoing` if the alert is still in
|
@ -37,6 +37,6 @@ Legend:
|
||||
ps
|
||||
monitor
|
||||
amps
|
||||
logs
|
||||
events
|
||||
docker
|
||||
actions
|
||||
|
233
glances/events.py
Normal file
233
glances/events.py
Normal file
@ -0,0 +1,233 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# Copyright (C) 2018 Nicolargo <nicolas@nicolargo.com>
|
||||
#
|
||||
# Glances is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Glances is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Manage Glances events (previously Glances logs in Glances <3.1)."""
|
||||
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from glances.compat import range
|
||||
from glances.processes import glances_processes, sort_stats
|
||||
|
||||
|
||||
class GlancesEvents(object):
|
||||
|
||||
"""This class manages events inside the Glances software.
|
||||
|
||||
Events is a list of event (stored in the self.events_list var)
|
||||
event_state = "OK|CAREFUL|WARNING|CRITICAL"
|
||||
event_type = "CPU*|LOAD|MEM|MON"
|
||||
event_value = value
|
||||
|
||||
Item (or event) is defined by:
|
||||
["begin",
|
||||
"end",
|
||||
"WARNING|CRITICAL",
|
||||
"CPU|LOAD|MEM",
|
||||
MAX, AVG, MIN, SUM, COUNT,
|
||||
[top3 process list],
|
||||
"Processes description",
|
||||
"top sort key"]
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Init the events class."""
|
||||
# Maximum size of the events list
|
||||
self.events_max = 10
|
||||
|
||||
# Init the logs list
|
||||
self.events_list = []
|
||||
|
||||
def get(self):
|
||||
"""Return the raw events list."""
|
||||
return self.events_list
|
||||
|
||||
def len(self):
|
||||
"""Return the number of events in the logs list."""
|
||||
return self.events_list.__len__()
|
||||
|
||||
def __event_exist(self, event_type):
|
||||
"""Return the event position, if it exists.
|
||||
|
||||
An event exist if:
|
||||
* end is < 0
|
||||
* event_type is matching
|
||||
Return -1 if the item is not found.
|
||||
"""
|
||||
for i in range(self.len()):
|
||||
if self.events_list[i][1] < 0 and self.events_list[i][3] == event_type:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def get_process_sort_key(self, event_type):
|
||||
"""Return the process sort key"""
|
||||
# Process sort depending on alert type
|
||||
if event_type.startswith("MEM"):
|
||||
# Sort TOP process by memory_percent
|
||||
ret = 'memory_percent'
|
||||
elif event_type.startswith("CPU_IOWAIT"):
|
||||
# Sort TOP process by io_counters (only for Linux OS)
|
||||
ret = 'io_counters'
|
||||
else:
|
||||
# Default sort is...
|
||||
ret = 'cpu_percent'
|
||||
return ret
|
||||
|
||||
def set_process_sort(self, event_type):
|
||||
"""Define the process auto sort key from the alert type."""
|
||||
glances_processes.auto_sort = True
|
||||
glances_processes.sort_key = self.get_process_sort_key(event_type)
|
||||
|
||||
def reset_process_sort(self):
|
||||
"""Reset the process auto sort key."""
|
||||
# Default sort is...
|
||||
glances_processes.auto_sort = True
|
||||
glances_processes.sort_key = 'cpu_percent'
|
||||
|
||||
def add(self, event_state, event_type, event_value,
|
||||
proc_list=None, proc_desc="", peak_time=6):
|
||||
"""Add a new item to the logs list.
|
||||
|
||||
If 'event' is a 'new one', add it at the beginning of the list.
|
||||
If 'event' is not a 'new one', update the list .
|
||||
If event < peak_time then the alert is not set.
|
||||
"""
|
||||
proc_list = proc_list or glances_processes.getlist()
|
||||
|
||||
# Add or update the log
|
||||
event_index = self.__event_exist(event_type)
|
||||
if event_index < 0:
|
||||
# Event did not exist, add it
|
||||
self._create_event(event_state, event_type, event_value,
|
||||
proc_list, proc_desc, peak_time)
|
||||
else:
|
||||
# Event exist, update it
|
||||
self._update_event(event_index, event_state, event_type, event_value,
|
||||
proc_list, proc_desc, peak_time)
|
||||
|
||||
return self.len()
|
||||
|
||||
def _create_event(self, event_state, event_type, event_value,
|
||||
proc_list, proc_desc, peak_time):
|
||||
"""Add a new item in the log list.
|
||||
|
||||
Item is added only if the criticity (event_state) is WARNING or CRITICAL.
|
||||
"""
|
||||
if event_state == "WARNING" or event_state == "CRITICAL":
|
||||
# Define the automatic process sort key
|
||||
self.set_process_sort(event_type)
|
||||
|
||||
# Create the new log item
|
||||
# Time is stored in Epoch format
|
||||
# Epoch -> DMYHMS = datetime.fromtimestamp(epoch)
|
||||
item = [
|
||||
time.mktime(datetime.now().timetuple()), # START DATE
|
||||
-1, # END DATE
|
||||
event_state, # STATE: WARNING|CRITICAL
|
||||
event_type, # TYPE: CPU, LOAD, MEM...
|
||||
event_value, # MAX
|
||||
event_value, # AVG
|
||||
event_value, # MIN
|
||||
event_value, # SUM
|
||||
1, # COUNT
|
||||
[], # TOP 3 PROCESS LIST
|
||||
proc_desc, # MONITORED PROCESSES DESC
|
||||
glances_processes.sort_key] # TOP PROCESS SORTKEY
|
||||
|
||||
# Add the item to the list
|
||||
self.events_list.insert(0, item)
|
||||
|
||||
# Limit the list to 'events_max' items
|
||||
if self.len() > self.events_max:
|
||||
self.events_list.pop()
|
||||
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _update_event(self, event_index, event_state, event_type, event_value,
|
||||
proc_list, proc_desc, peak_time):
|
||||
"""Update an event in the list"""
|
||||
if event_state == "OK" or event_state == "CAREFUL":
|
||||
# Reset the automatic process sort key
|
||||
self.reset_process_sort()
|
||||
|
||||
# Set the end of the events
|
||||
endtime = time.mktime(datetime.now().timetuple())
|
||||
if endtime - self.events_list[event_index][0] > peak_time:
|
||||
# If event is > peak_time seconds
|
||||
self.events_list[event_index][1] = endtime
|
||||
else:
|
||||
# If event <= peak_time seconds, ignore
|
||||
self.events_list.remove(self.events_list[event_index])
|
||||
else:
|
||||
# Update the item
|
||||
|
||||
# State
|
||||
if event_state == "CRITICAL":
|
||||
self.events_list[event_index][2] = event_state
|
||||
|
||||
# Value
|
||||
# if event_value > self.events_list[event_index][4]:
|
||||
# # MAX
|
||||
# self.events_list[event_index][4] = event_value
|
||||
# elif event_value < self.events_list[event_index][6]:
|
||||
# # MIN
|
||||
# self.events_list[event_index][6] = event_value
|
||||
# Min value
|
||||
self.events_list[event_index][6] = min(self.events_list[event_index][6],
|
||||
event_value)
|
||||
# Max value
|
||||
self.events_list[event_index][4] = max(self.events_list[event_index][4],
|
||||
event_value)
|
||||
# Average value
|
||||
self.events_list[event_index][7] += event_value
|
||||
self.events_list[event_index][8] += 1
|
||||
self.events_list[event_index][5] = (self.events_list[event_index][7] /
|
||||
self.events_list[event_index][8])
|
||||
|
||||
# TOP PROCESS LIST (only for CRITICAL ALERT)
|
||||
if event_state == "CRITICAL":
|
||||
# Sort the current process list to retreive the TOP 3 processes
|
||||
self.events_list[event_index][9] = sort_stats(proc_list, glances_processes.sort_key)[0:3]
|
||||
self.events_list[event_index][11] = glances_processes.sort_key
|
||||
|
||||
# MONITORED PROCESSES DESC
|
||||
self.events_list[event_index][10] = proc_desc
|
||||
|
||||
return True
|
||||
|
||||
def clean(self, critical=False):
|
||||
"""Clean the logs list by deleting finished items.
|
||||
|
||||
By default, only delete WARNING message.
|
||||
If critical = True, also delete CRITICAL message.
|
||||
"""
|
||||
# Create a new clean list
|
||||
clean_events_list = []
|
||||
while self.len() > 0:
|
||||
item = self.events_list.pop()
|
||||
if item[1] < 0 or (not critical and item[2].startswith("CRITICAL")):
|
||||
clean_events_list.insert(0, item)
|
||||
# The list is now the clean one
|
||||
self.events_list = clean_events_list
|
||||
return self.len()
|
||||
|
||||
|
||||
glances_events = GlancesEvents()
|
222
glances/logs.py
222
glances/logs.py
@ -1,222 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# Copyright (C) 2018 Nicolargo <nicolas@nicolargo.com>
|
||||
#
|
||||
# Glances is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Glances is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Manage logs."""
|
||||
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from glances.compat import range
|
||||
from glances.processes import glances_processes, sort_stats
|
||||
|
||||
|
||||
class GlancesLogs(object):
|
||||
|
||||
"""This class manages logs inside the Glances software.
|
||||
|
||||
Logs is a list of list (stored in the self.logs_list var)
|
||||
item_state = "OK|CAREFUL|WARNING|CRITICAL"
|
||||
item_type = "CPU*|LOAD|MEM|MON"
|
||||
item_value = value
|
||||
|
||||
Item is defined by:
|
||||
["begin",
|
||||
"end",
|
||||
"WARNING|CRITICAL",
|
||||
"CPU|LOAD|MEM",
|
||||
MAX, AVG, MIN, SUM, COUNT,
|
||||
[top3 process list],
|
||||
"Processes description",
|
||||
"top sort key"]
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Init the logs class."""
|
||||
# Maximum size of the logs list
|
||||
self.logs_max = 10
|
||||
|
||||
# Init the logs list
|
||||
self.logs_list = []
|
||||
|
||||
def get(self):
|
||||
"""Return the raw logs list."""
|
||||
return self.logs_list
|
||||
|
||||
def len(self):
|
||||
"""Return the number of item in the logs list."""
|
||||
return self.logs_list.__len__()
|
||||
|
||||
def __itemexist__(self, item_type):
|
||||
"""Return the item position, if it exists.
|
||||
|
||||
An item exist in the list if:
|
||||
* end is < 0
|
||||
* item_type is matching
|
||||
Return -1 if the item is not found.
|
||||
"""
|
||||
for i in range(self.len()):
|
||||
if self.logs_list[i][1] < 0 and self.logs_list[i][3] == item_type:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def get_process_sort_key(self, item_type):
|
||||
"""Return the process sort key"""
|
||||
# Process sort depending on alert type
|
||||
if item_type.startswith("MEM"):
|
||||
# Sort TOP process by memory_percent
|
||||
ret = 'memory_percent'
|
||||
elif item_type.startswith("CPU_IOWAIT"):
|
||||
# Sort TOP process by io_counters (only for Linux OS)
|
||||
ret = 'io_counters'
|
||||
else:
|
||||
# Default sort is...
|
||||
ret = 'cpu_percent'
|
||||
return ret
|
||||
|
||||
def set_process_sort(self, item_type):
|
||||
"""Define the process auto sort key from the alert type."""
|
||||
glances_processes.auto_sort = True
|
||||
glances_processes.sort_key = self.get_process_sort_key(item_type)
|
||||
|
||||
def reset_process_sort(self):
|
||||
"""Reset the process auto sort key."""
|
||||
# Default sort is...
|
||||
glances_processes.auto_sort = True
|
||||
glances_processes.sort_key = 'cpu_percent'
|
||||
|
||||
def add(self, item_state, item_type, item_value,
|
||||
proc_list=None, proc_desc="", peak_time=6):
|
||||
"""Add a new item to the logs list.
|
||||
|
||||
If 'item' is a 'new one', add the new item at the beginning of
|
||||
the logs list.
|
||||
If 'item' is not a 'new one', update the existing item.
|
||||
If event < peak_time the the alert is not setoff.
|
||||
"""
|
||||
proc_list = proc_list or glances_processes.getlist()
|
||||
|
||||
# Add or update the log
|
||||
item_index = self.__itemexist__(item_type)
|
||||
if item_index < 0:
|
||||
# Item did not exist, add if WARNING or CRITICAL
|
||||
self._create_item(item_state, item_type, item_value,
|
||||
proc_list, proc_desc, peak_time)
|
||||
else:
|
||||
# Item exist, update
|
||||
self._update_item(item_index, item_state, item_type, item_value,
|
||||
proc_list, proc_desc, peak_time)
|
||||
|
||||
return self.len()
|
||||
|
||||
def _create_item(self, item_state, item_type, item_value,
|
||||
proc_list, proc_desc, peak_time):
|
||||
"""Create a new item in the log list"""
|
||||
if item_state == "WARNING" or item_state == "CRITICAL":
|
||||
# Define the automatic process sort key
|
||||
self.set_process_sort(item_type)
|
||||
|
||||
# Create the new log item
|
||||
# Time is stored in Epoch format
|
||||
# Epoch -> DMYHMS = datetime.fromtimestamp(epoch)
|
||||
item = [
|
||||
time.mktime(datetime.now().timetuple()), # START DATE
|
||||
-1, # END DATE
|
||||
item_state, # STATE: WARNING|CRITICAL
|
||||
item_type, # TYPE: CPU, LOAD, MEM...
|
||||
item_value, # MAX
|
||||
item_value, # AVG
|
||||
item_value, # MIN
|
||||
item_value, # SUM
|
||||
1, # COUNT
|
||||
[], # TOP 3 PROCESS LIST
|
||||
proc_desc, # MONITORED PROCESSES DESC
|
||||
glances_processes.sort_key] # TOP PROCESS SORTKEY
|
||||
|
||||
# Add the item to the list
|
||||
self.logs_list.insert(0, item)
|
||||
if self.len() > self.logs_max:
|
||||
self.logs_list.pop()
|
||||
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _update_item(self, item_index, item_state, item_type, item_value,
|
||||
proc_list, proc_desc, peak_time):
|
||||
"""Update a item in the log list"""
|
||||
if item_state == "OK" or item_state == "CAREFUL":
|
||||
# Reset the automatic process sort key
|
||||
self.reset_process_sort()
|
||||
|
||||
endtime = time.mktime(datetime.now().timetuple())
|
||||
if endtime - self.logs_list[item_index][0] > peak_time:
|
||||
# If event is > peak_time seconds
|
||||
self.logs_list[item_index][1] = endtime
|
||||
else:
|
||||
# If event <= peak_time seconds, ignore
|
||||
self.logs_list.remove(self.logs_list[item_index])
|
||||
else:
|
||||
# Update the item
|
||||
|
||||
# State
|
||||
if item_state == "CRITICAL":
|
||||
self.logs_list[item_index][2] = item_state
|
||||
|
||||
# Value
|
||||
if item_value > self.logs_list[item_index][4]:
|
||||
# MAX
|
||||
self.logs_list[item_index][4] = item_value
|
||||
elif item_value < self.logs_list[item_index][6]:
|
||||
# MIN
|
||||
self.logs_list[item_index][6] = item_value
|
||||
# AVG (compute average value)
|
||||
self.logs_list[item_index][7] += item_value
|
||||
self.logs_list[item_index][8] += 1
|
||||
self.logs_list[item_index][5] = (self.logs_list[item_index][7] /
|
||||
self.logs_list[item_index][8])
|
||||
|
||||
# TOP PROCESS LIST (only for CRITICAL ALERT)
|
||||
if item_state == "CRITICAL":
|
||||
# Sort the current process list to retreive the TOP 3 processes
|
||||
self.logs_list[item_index][9] = sort_stats(proc_list, glances_processes.sort_key)[0:3]
|
||||
self.logs_list[item_index][11] = glances_processes.sort_key
|
||||
|
||||
# MONITORED PROCESSES DESC
|
||||
self.logs_list[item_index][10] = proc_desc
|
||||
|
||||
return True
|
||||
|
||||
def clean(self, critical=False):
|
||||
"""Clean the logs list by deleting finished items.
|
||||
|
||||
By default, only delete WARNING message.
|
||||
If critical = True, also delete CRITICAL message.
|
||||
"""
|
||||
# Create a new clean list
|
||||
clean_logs_list = []
|
||||
while self.len() > 0:
|
||||
item = self.logs_list.pop()
|
||||
if item[1] < 0 or (not critical and item[2].startswith("CRITICAL")):
|
||||
clean_logs_list.insert(0, item)
|
||||
# The list is now the clean one
|
||||
self.logs_list = clean_logs_list
|
||||
return self.len()
|
||||
|
||||
|
||||
glances_logs = GlancesLogs()
|
@ -25,7 +25,7 @@ import sys
|
||||
from glances.compat import u, itervalues
|
||||
from glances.globals import MACOS, WINDOWS
|
||||
from glances.logger import logger
|
||||
from glances.logs import glances_logs
|
||||
from glances.events import glances_events
|
||||
from glances.processes import glances_processes
|
||||
from glances.timer import Timer
|
||||
|
||||
@ -375,10 +375,10 @@ class _GlancesCurses(object):
|
||||
self.args.disable_folders = not self.args.disable_folders
|
||||
elif self.pressedkey == ord('w'):
|
||||
# 'w' > Delete finished warning logs
|
||||
glances_logs.clean()
|
||||
glances_events.clean()
|
||||
elif self.pressedkey == ord('x'):
|
||||
# 'x' > Delete finished warning and critical logs
|
||||
glances_logs.clean(critical=True)
|
||||
glances_events.clean(critical=True)
|
||||
elif self.pressedkey == ord('z'):
|
||||
# 'z' > Enable or disable processes
|
||||
self.args.disable_process = not self.args.disable_process
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from glances.logs import glances_logs
|
||||
from glances.events import glances_events
|
||||
from glances.thresholds import glances_thresholds
|
||||
# from glances.logger import logger
|
||||
from glances.plugins.glances_plugin import GlancesPlugin
|
||||
@ -96,8 +96,8 @@ class Plugin(GlancesPlugin):
|
||||
|
||||
def update(self):
|
||||
"""Nothing to do here. Just return the global glances_log."""
|
||||
# Set the stats to the glances_logs
|
||||
self.stats = glances_logs.get()
|
||||
# Set the stats to the glances_events
|
||||
self.stats = glances_events.get()
|
||||
# Define the global message thanks to the current thresholds
|
||||
# and the decision tree
|
||||
# !!! Call directly in the msg_curse function
|
||||
@ -119,7 +119,7 @@ class Plugin(GlancesPlugin):
|
||||
# Header
|
||||
# msg = 'Warning or critical alerts'
|
||||
# ret.append(self.curse_add_line(msg, "TITLE"))
|
||||
# logs_len = glances_logs.len()
|
||||
# logs_len = glances_events.len()
|
||||
# if logs_len > 1:
|
||||
# msg = ' (last {} entries)'.format(logs_len)
|
||||
# else:
|
||||
|
@ -32,7 +32,7 @@ from glances.compat import iterkeys, itervalues, listkeys, map, mean
|
||||
from glances.actions import GlancesActions
|
||||
from glances.history import GlancesHistory
|
||||
from glances.logger import logger
|
||||
from glances.logs import glances_logs
|
||||
from glances.events import glances_events
|
||||
from glances.thresholds import glances_thresholds
|
||||
|
||||
|
||||
@ -600,7 +600,7 @@ class GlancesPlugin(object):
|
||||
# So stats will be highlited with a specific color
|
||||
log_str = "_LOG"
|
||||
# Add the log to the list
|
||||
glances_logs.add(ret, stat_name.upper(), value)
|
||||
glances_events.add(ret, stat_name.upper(), value)
|
||||
|
||||
# Manage threshold
|
||||
self.manage_threshold(stat_name, ret)
|
||||
|
Loading…
Reference in New Issue
Block a user