summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicolargo <nicolas@nicolargo.com>2024-03-17 17:07:13 +0100
committernicolargo <nicolas@nicolargo.com>2024-03-17 17:07:13 +0100
commit77167b8bce794db9383e748cfa0eee8577687cf6 (patch)
tree61033b8f6ef10fac78eedb2b7220f29f6179fb5c
parent272dc23443ab364fcbad2294627ac43e5688cb4c (diff)
Event is now a Dataclass
-rw-r--r--README.rst5
-rw-r--r--glances/events.py410
-rw-r--r--glances/outputs/glances_curses.py2
-rw-r--r--glances/outputs/static/js/components/plugin-alert.vue1
-rw-r--r--glances/outputs/static/public/glances.js2
-rw-r--r--glances/plugins/alert/__init__.py11
-rw-r--r--glances/plugins/plugin/model.py2
-rw-r--r--requirements.txt1
-rwxr-xr-xunitest.py4
9 files changed, 16 insertions, 422 deletions
diff --git a/README.rst b/README.rst
index d83d4ff5..1346ad0a 100644
--- a/README.rst
+++ b/README.rst
@@ -79,9 +79,12 @@ Requirements
============
- ``python>=3.8`` (use Glances 3.4.x for lower Python version)
-- ``psutil>=5.3.0`` (better with latest version)
+- ``psutil`` (better with latest version)
- ``defusedxml`` (in order to monkey patch xmlrpc)
+- ``packaging`` (for the version comparison)
- ``ujson`` (an optimized alternative to the standard json module)
+- ``pytz`` (for the timezone support)
+- ``pydantic`` (for the data validation support)
*Note for Python 2 users*
diff --git a/glances/events.py b/glances/events.py
deleted file mode 100644
index 6658c842..00000000
--- a/glances/events.py
+++ /dev/null
@@ -1,410 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of Glances.
-#
-# SPDX-FileCopyrightText: 2022 Nicolas Hennion <nicolas@nicolargo.com>
-#
-# SPDX-License-Identifier: LGPL-3.0-only
-#
-
-"""Manage Glances events (previously Glances logs in Glances < 3.1)."""
-
-import time
-from datetime import datetime
-
-from glances.logger import logger
-from glances.processes import glances_processes, sort_stats
-from glances.thresholds import glances_thresholds
-
-# Static decision tree for the global alert message
-# - msg: Message to be displayed (result of the decision tree)
-# - thresholds: a list of stats to take into account
-# - thresholds_min: minimal value of the thresholds sum
-# - 0: OK
-# - 1: CAREFUL
-# - 2: WARNING
-# - 3: CRITICAL
-tree = [
- {'msg': 'No warning or critical alert detected', 'thresholds': [], 'thresholds_min': 0},
- {'msg': 'High CPU user mode', 'thresholds': ['cpu_user'], 'thresholds_min': 2},
- {'msg': 'High CPU kernel usage', 'thresholds': ['cpu_system'], 'thresholds_min': 2},
- {'msg': 'High CPU I/O waiting', 'thresholds': ['cpu_iowait'], 'thresholds_min': 2},
- {
- 'msg': 'Large CPU stolen time. System running the hypervisor is too busy.',
- 'thresholds': ['cpu_steal'],
- 'thresholds_min': 2,
- },
- {'msg': 'High CPU niced value', 'thresholds': ['cpu_niced'], 'thresholds_min': 2},
- {'msg': 'System overloaded in the last 5 minutes', 'thresholds': ['load'], 'thresholds_min': 2},
- {'msg': 'High swap (paging) usage', 'thresholds': ['memswap'], 'thresholds_min': 2},
- {'msg': 'High memory consumption', 'thresholds': ['mem'], 'thresholds_min': 2},
-]
-
-# TODO: change the algo to use the following decision tree
-# Source: Inspire by https://scoutapm.com/blog/slow_server_flow_chart
-# _yes means threshold >= 2
-# _no means threshold < 2
-# With threshold:
-# - 0: OK
-# - 1: CAREFUL
-# - 2: WARNING
-# - 3: CRITICAL
-tree_new = {
- 'cpu_iowait': {
- '_yes': {
- 'memswap': {
- '_yes': {
- 'mem': {
- '_yes': {
- # Once you've identified the offenders, the resolution will again
- # depend on whether their memory usage seems business-as-usual or not.
- # For example, a memory leak can be satisfactorily addressed by a one-time
- # or periodic restart of the process.
- # - if memory usage seems anomalous: kill the offending processes.
- # - if memory usage seems business-as-usual: add RAM to the server,
- # or split high-memory using services to other servers.
- '_msg': "Memory issue"
- },
- '_no': {
- # ???
- '_msg': "Swap issue"
- },
- }
- },
- '_no': {
- # Low swap means you have a "real" IO wait problem. The next step is to see what's hogging your IO.
- # iotop is an awesome tool for identifying io offenders. Two things to note:
- # unless you've already installed iotop, it's probably not already on your system.
- # Recommendation: install it before you need it - - it's no fun trying to install a troubleshooting
- # tool on an overloaded machine (iotop requires a Linux of 2.62 or above)
- '_msg': "I/O issue"
- },
- }
- },
- '_no': {
- 'cpu_total': {
- '_yes': {
- 'cpu_user': {
- '_yes': {
- # We expect the user-time percentage to be high.
- # There's most likely a program or service you've configured on you server that's
- # hogging CPU.
- # Checking the % user time just confirms this. When you see that the % user-time is high,
- # it's time to see what executable is monopolizing the CPU
- # Once you've confirmed that the % usertime is high, check the process list(also provided
- # by top).
- # Be default, top sorts the process list by % CPU, so you can just look at the top process
- # or processes.
- # If there's a single process hogging the CPU in a way that seems abnormal, it's an
- # anomalous situation
- # that a service restart can fix. If there are are multiple processes taking up CPU
- # resources, or it
- # there's one process that takes lots of resources while otherwise functioning normally,
- # than your setup
- # may just be underpowered. You'll need to upgrade your server(add more cores),
- # or split services out onto
- # other boxes. In either case, you have a resolution:
- # - if situation seems anomalous: kill the offending processes.
- # - if situation seems typical given history: upgrade server or add more servers.
- '_msg': "CPU issue with user process(es)"
- },
- '_no': {
- 'cpu_steal': {
- '_yes': {
- '_msg': "CPU issue with stolen time. System running the hypervisor may be too busy."
- },
- '_no': {'_msg': "CPU issue with system process(es)"},
- }
- },
- }
- },
- '_no': {
- '_yes': {
- # ???
- '_msg': "Memory issue"
- },
- '_no': {
- # Your slowness isn't due to CPU or IO problems, so it's likely an application-specific issue.
- # It's also possible that the slowness is being caused by another server in your cluster, or
- # by an external service you rely on.
- # start by checking important applications for uncharacteristic slowness(the DB is a good place
- # to start), think through which parts of your infrastructure could be slowed down externally.
- # For example, do you use an externally hosted email service that could slow down critical
- # parts of your application ?
- # If you suspect another server in your cluster, strace and lsof can provide information on
- # what the process is doing or waiting on. Strace will show you which file descriptors are
- # being read or written to (or being attempted to be read from) and lsof can give you a
- # mapping of those file descriptors to network connections.
- '_msg': "External issue"
- },
- },
- }
- },
- }
-}
-
-
-def build_global_message():
- """Parse the decision tree and return the message.
-
- Note: message corresponding to the current thresholds values
- """
- # Compute the weight for each item in the tree
- current_thresholds = glances_thresholds.get()
- for i in tree:
- i['weight'] = sum([current_thresholds[t].value() for t in i['thresholds'] if t in current_thresholds])
- themax = max(tree, key=lambda d: d['weight'])
- if themax['weight'] >= themax['thresholds_min']:
- # Check if the weight is > to the minimal threshold value
- return themax['msg']
- else:
- return tree[0]['msg']
-
-
-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": "begin",
- "end": "end",
- "state": "WARNING|CRITICAL",
- "type": "CPU|LOAD|MEM",
- "max": MAX,
- "avg": AVG,
- "min": MIN,
- "sum": SUM,
- "count": COUNT,
- "top": [top 3 process name],
- "desc": "Processes description",
- "sort": "top sort key",
- "global": "global alert message"
- }
- """
-
- def __init__(self, max_events=10, min_duration=6, min_interval=6):
- """Init the events class.
-
- max_events: maximum size of the events list
- min_duration: events duration should be > min_duration to be taken into account (in seconds)
- min_interval: minimal interval between same kind of alert (in seconds)
- """
- # Maximum size of the events list
- self.set_max_events(max_events)
-
- # Minimal event duraton time (in seconds)
- self.set_min_duration(min_duration)
-
- # Minimal interval between same kind of alert (in seconds)
- self.set_min_interval(min_interval)
-
- # Init the logs list
- self.events_list = []
-
- def set_max_events(self, max_events):
- """Set the maximum size of the events list."""
- self.max_events = max_events
-
- def set_min_duration(self, min_duration):
- """Set the minimal event duration time (in seconds)."""
- self.min_duration = min_duration
-
- def set_min_interval(self, min_interval):
- """Set the minimum interval between same kind of alert (in seconds)."""
- self.min_interval = min_interval
-
- 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_time, event_type):
- """Return the event position in the events list if:
- type is matching
- and (end is < 0 or event_time - end < min_interval)
- Return -1 if the item is not found.
- """
- for i in range(self.len()):
- if ((self.events_list[i]['end'] < 0) or
- (event_time - self.events_list[i]['end'] < self.min_interval)) and \
- self.events_list[i]['type'] == event_type:
- return i
- return -1
-
- def get_event_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."""
- if glances_processes.auto_sort:
- glances_processes.set_sort_key(self.get_event_sort_key(event_type))
-
- def reset_process_sort(self):
- """Reset the process auto sort key."""
- if glances_processes.auto_sort:
- glances_processes.set_sort_key('auto')
-
- def add(self, event_state, event_type, event_value, proc_list=None, proc_desc="", min_duration=None):
- """Add a new item to the logs list.
-
- event_state = "OK|CAREFUL|WARNING|CRITICAL"
- event_type = "CPU|LOAD|MEM|..."
- event_value = value
- proc_list = list of processes
- proc_desc = processes description
- global_message = global alert message
-
- If 'event' is a 'new one', add it at the beginning of the list.
- If 'event' is not a 'new one', update the list .
- When finished if event duration < peak_time then the alert is not set.
- """
- event_time = time.mktime(datetime.now().timetuple())
- global_message = build_global_message()
- proc_list = proc_list or glances_processes.get_list()
-
- # Add or update the log
- event_index = self.__event_exist(event_time, event_type)
- if event_index < 0:
- # Event did not exist, add it
- self._create_event(event_time, event_state, event_type, event_value,
- proc_desc, global_message)
- else:
- # Event exist, update it
- self._update_event(event_time, event_index, event_state, event_type, event_value,
- proc_list, proc_desc, global_message)
-
- return self.len()
-
- def _create_event(self, event_time, event_state, event_type, event_value,
- proc_desc, global_message):
- """Add a new item in the log list.
-
- Item is added only if the criticality (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 = {
- "begin": event_time,
- "end": -1,
- "state": event_state,
- "type": event_type,
- "max": event_value,
- "avg": event_value,
- "min": event_value,
- "sum": event_value,
- "count": 1,
- "top": [],
- "desc": proc_desc,
- "sort": glances_processes.sort_key,
- "global": global_message,
- }
-
- # Add the item to the list
- self.events_list.insert(0, item)
-
- # Limit the list to 'max_events' items
- if self.len() > self.max_events:
- self.events_list.pop()
- return True
- else:
- return False
-
- def _update_event(self, event_time, event_index, event_state, event_type, event_value,
- proc_list, proc_desc, global_message):
- """Update an event in the list"""
- if event_state in ('OK', 'CAREFUL') and self.events_list[event_index]['end'] < 0:
- # Close the event
- self._close_event(event_time, event_index)
- elif event_state in ('OK', 'CAREFUL') and self.events_list[event_index]['end'] >= 0:
- # Event is already closed, do nothing
- pass
- else: # event_state == "WARNING" or event_state == "CRITICAL"
- # Set process sort key
- self.set_process_sort(event_type)
-
- # It's an ongoing event, set the end time to -1
- self.events_list[event_index]['end'] = -1
-
- # Min/Max/Sum/Count/Avergae value
- self.events_list[event_index]['min'] = min(self.events_list[event_index]['min'], event_value)
- self.events_list[event_index]['max'] = max(self.events_list[event_index]['max'], event_value)
- self.events_list[event_index]['sum'] += event_value
- self.events_list[event_index]['count'] += 1
- self.events_list[event_index]['avg'] = self.events_list[event_index]['sum'] / self.events_list[event_index]['count']
-
- if event_state == "CRITICAL":
- # Avoid to change from CRITICAL to WARNING
- # If an events have reached the CRITICAL state, it can't go back to WARNING
- self.events_list[event_index]['state'] = event_state
-
- # TOP PROCESS LIST (only for CRITICAL ALERT)
- events_sort_key = self.get_event_sort_key(event_type)
-
- # Sort the current process list to retrieve the TOP 3 processes
- self.events_list[event_index]['top'] = [p['name'] for p in sort_stats(proc_list, events_sort_key)[0:3]]
- self.events_list[event_index]['sort'] = events_sort_key
-
- # MONITORED PROCESSES DESC
- self.events_list[event_index]['desc'] = proc_desc
-
- # Global message:
- self.events_list[event_index]['global'] = global_message
-
- return True
-
- def _close_event(self, event_time, event_index):
- """Close an event in the list"""
- # Reset the automatic process sort key
- self.reset_process_sort()
-
- # Set the end of the events
- if event_time - self.events_list[event_index]['begin'] >= self.min_duration:
- # If event is >= min_duration seconds
- self.events_list[event_index]['end'] = event_time
- else:
- # If event < min_duration seconds, ignore
- self.events_list.remove(self.events_list[event_index])
-
- 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['end'] < 0 or (not critical and item['state'].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()
diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py
index 484b3b73..468d6d0b 100644
--- a/glances/outputs/glances_curses.py
+++ b/glances/outputs/glances_curses.py
@@ -14,7 +14,7 @@ import sys
from glances.globals import MACOS, WINDOWS, nativestr, u, itervalues, enable, disable
from glances.logger import logger
-from glances.events import glances_events
+from glances.events_list import glances_events
from glances.processes import glances_processes, sort_processes_key_list
from glances.outputs.glances_unicode import unicode_message
from glances.timer import Timer
diff --git a/glances/outputs/static/js/components/plugin-alert.vue b/glances/outputs/static/js/components/plugin-alert.vue
index 48a0478f..5eb7cabf 100644
--- a/glances/outputs/static/js/components/plugin-alert.vue
+++ b/glances/outputs/static/js/components/plugin-alert.vue
@@ -53,7 +53,6 @@ export default {
alert.avg = alertalertStats.avg;
alert.max = alertalertStats.max;
alert.top = alertalertStats.top.join(', ');
- alert.global = alertalertStats.global;
if (!alert.ongoing) {
const duration = alert.end - alert.begin;
diff --git a/glances/outputs/static/public/glances.js b/glances/outputs/static/public/glances.js
index 5ecc180a..220bf9ca 100644
--- a/glances/outputs/static/public/glances.js
+++ b/glances/outputs/static/public/glances.js
@@ -28,4 +28,4 @@ function n(e){return"[object Object]"===Object.prototype.toString.call(e)}Object
* https://jaywcjlove.github.io/hotkeys-js
* Licensed under the MIT license
*/
-var mo="undefined"!=typeof navigator&&navigator.userAgent.toLowerCase().indexOf("firefox")>0;function bo(e,t,n,r){e.addEventListener?e.addEventListener(t,n,r):e.attachEvent&&e.attachEvent("on".concat(t),(function(){n(window.event)}))}function vo(e,t){for(var n=t.slice(0,t.length-1),r=0;r<n.length;r++)n[r]=e[n[r].toLowerCase()];return n}function yo(e){"string"!=typeof e&&(e="");for(var t=(e=e.replace(/\s/g,"")).split(","),n=t.lastIndexOf("");n>=0;)t[n-1]+=",",t.splice(n,1),n=t.lastIndexOf("");return t}for(var wo={backspace:8,"⌫":8,tab:9,clear:12,enter:13,"↩":13,return:13,esc:27,escape:27,space:32,left:37,up:38,right:39,down:40,del:46,delete:46,ins:45,insert:45,home:36,end:35,pageup:33,pagedown:34,capslock:20,num_0:96,num_1:97,num_2:98,num_3:99,num_4:100,num_5:101,num_6:102,num_7:103,num_8:104,num_9:105,num_multiply:106,num_add:107,num_enter:108,num_subtract:109,num_decimal:110,num_divide:111,"⇪":20,",":188,".":190,"/":191,"`":192,"-":mo?173:189,"=":mo?61:187,";":mo?59:186,"'":222,"[":219,"]":221,"\\":220},xo={"⇧":16,shift:16,"⌥":18,alt:18,option:18,"⌃":17,ctrl:17,control:17,"⌘":91,cmd:91,command:91},_o={16:"shiftKey",18:"altKey",17:"ctrlKey",91:"metaKey",shiftKey:16,ctrlKey:17,altKey:18,metaKey:91},ko={16:!1,18:!1,17:!1,91:!1},So={},Co=1;Co<20;Co++)wo["f".concat(Co)]=111+Co;var To=[],Ao=!1,Eo="all",Oo=[],Io=function(e){return wo[e.toLowerCase()]||xo[e.toLowerCase()]||e.toUpperCase().charCodeAt(0)};function Po(e){Eo=e||"all"}function No(){return Eo||"all"}var Lo=function(e){var t=e.key,n=e.scope,r=e.method,i=e.splitKey,s=void 0===i?"+":i;yo(t).forEach((function(e){var t=e.split(s),i=t.length,o=t[i-1],a="*"===o?"*":Io(o);if(So[a]){n||(n=No());var l=i>1?vo(xo,t):[];So[a]=So[a].filter((function(e){return!((!r||e.method===r)&&e.scope===n&&function(e,t){for(var n=e.length>=t.length?e:t,r=e.length>=t.length?t:e,i=!0,s=0;s<n.length;s++)-1===r.indexOf(n[s])&&(i=!1);return i}(e.mods,l))}))}}))};function Do(e,t,n,r){var i;if(t.element===r&&(t.scope===n||"all"===t.scope)){for(var s in i=t.mods.length>0,ko)Object.prototype.hasOwnProperty.call(ko,s)&&(!ko[s]&&t.mods.indexOf(+s)>-1||ko[s]&&-1===t.mods.indexOf(+s))&&(i=!1);(0!==t.mods.length||ko[16]||ko[18]||ko[17]||ko[91])&&!i&&"*"!==t.shortcut||(t.keys=[],t.keys=t.keys.concat(To),!1===t.method(e,t)&&(e.preventDefault?e.preventDefault():e.returnValue=!1,e.stopPropagation&&e.stopPropagation(),e.cancelBubble&&(e.cancelBubble=!0)))}}function Mo(e,t){var n=So["*"],r=e.keyCode||e.which||e.charCode;if(jo.filter.call(this,e)){if(93!==r&&224!==r||(r=91),-1===To.indexOf(r)&&229!==r&&To.push(r),["ctrlKey","altKey","shiftKey","metaKey"].forEach((function(t){var n=_o[t];e[t]&&-1===To.indexOf(n)?To.push(n):!e[t]&&To.indexOf(n)>-1?To.splice(To.indexOf(n),1):"metaKey"===t&&e[t]&&3===To.length&&(e.ctrlKey||e.shiftKey||e.altKey||(To=To.slice(To.indexOf(n))))})),r in ko){for(var i in ko[r]=!0,xo)xo[i]===r&&(jo[i]=!0);if(!n)return}for(var s in ko)Object.prototype.hasOwnProperty.call(ko,s)&&(ko[s]=e[_o[s]]);e.getModifierState&&(!e.altKey||e.ctrlKey)&&e.getModifierState("AltGraph")&&(-1===To.indexOf(17)&&To.push(17),-1===To.indexOf(18)&&To.push(18),ko[17]=!0,ko[18]=!0);var o=No();if(n)for(var a=0;a<n.length;a++)n[a].scope===o&&("keydown"===e.type&&n[a].keydown||"keyup"===e.type&&n[a].keyup)&&Do(e,n[a],o,t);if(r in So)for(var l=0;l<So[r].length;l++)if(("keydown"===e.type&&So[r][l].keydown||"keyup"===e.type&&So[r][l].keyup)&&So[r][l].key){for(var c=So[r][l],u=c.splitKey,d=c.key.split(u),f=[],p=0;p<d.length;p++)f.push(Io(d[p]));f.sort().join("")===To.sort().join("")&&Do(e,c,o,t)}}}function jo(e,t,n){To=[];var r=yo(e),i=[],s="all",o=document,a=0,l=!1,c=!0,u="+",d=!1;for(void 0===n&&"function"==typeof t&&(n=t),"[object Object]"===Object.prototype.toString.call(t)&&(t.scope&&(s=t.scope),t.element&&(o=t.element),t.keyup&&(l=t.keyup),void 0!==t.keydown&&(c=t.keydown),void 0!==t.capture&&(d=t.capture),"string"==typeof t.splitKey&&(u=t.splitKey)),"string"==typeof t&&(s=t);a<r.length;a++)i=[],(e=r[a].split(u)).length>1&&(i=vo(xo,e)),(e="*"===(e=e[e.length-1])?"*":Io(e))in So||(So[e]=[]),So[e].push({keyup:l,keydown:c,scope:s,mods:i,shortcut:r[a],method:n,key:r[a],splitKey:u,element:o});void 0!==o&&!function(e){return Oo.indexOf(e)>-1}(o)&&window&&(Oo.push(o),bo(o,"keydown",(function(e){Mo(e,o)}),d),Ao||(Ao=!0,bo(window,"focus",(function(){To=[]}),d)),bo(o,"keyup",(function(e){Mo(e,o),function(e){var t=e.keyCode||e.which||e.charCode,n=To.indexOf(t);if(n>=0&&To.splice(n,1),e.key&&"meta"===e.key.toLowerCase()&&To.splice(0,To.length),93!==t&&224!==t||(t=91),t in ko)for(var r in ko[t]=!1,xo)xo[r]===t&&(jo[r]=!1)}(e)}),d))}var Ro={getPressedKeyString:function(){return To.map((function(e){return t=e,Object.keys(wo).find((function(e){return wo[e]===t}))||function(e){return Object.keys(xo).find((function(t){return xo[t]===e}))}(e)||String.fromCharCode(e);var t}))},setScope:Po,getScope:No,deleteScope:function(e,t){var n,r;for(var i in e||(e=No()),So)if(Object.prototype.hasOwnProperty.call(So,i))for(n=So[i],r=0;r<n.length;)n[r].scope===e?n.splice(r,1):r++;No()===e&&Po(t||"all")},getPressedKeyCodes:function(){return To.slice(0)},getAllKeyCodes:function(){var e=[];return Object.keys(So).forEach((function(t){So[t].forEach((function(t){var n=t.key,r=t.scope,i=t.mods,s=t.shortcut;e.push({scope:r,shortcut:s,mods:i,keys:n.split("+").map((function(e){return Io(e)}))})}))})),e},isPressed:function(e){return"string"==typeof e&&(e=Io(e)),-1!==To.indexOf(e)},filter:function(e){var t=e.target||e.srcElement,n=t.tagName,r=!0;return!t.isContentEditable&&("INPUT"!==n&&"TEXTAREA"!==n&&"SELECT"!==n||t.readOnly)||(r=!1),r},trigger:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"all";Object.keys(So).forEach((function(n){So[n].filter((function(n){return n.scope===t&&n.shortcut===e})).forEach((function(e){e&&e.method&&e.method()}))}))},unbind:function(e){if(void 0===e)Object.keys(So).forEach((function(e){return delete So[e]}));else if(Array.isArray(e))e.forEach((function(e){e.key&&Lo(e)}));else if("object"==typeof e)e.key&&Lo(e);else if("string"==typeof e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];var i=n[0],s=n[1];"function"==typeof i&&(s=i,i=""),Lo({key:e,scope:i,method:s,splitKey:"+"})}},keyMap:wo,modifier:xo,modifierMap:_o};for(var qo in Ro)Object.prototype.hasOwnProperty.call(Ro,qo)&&(jo[qo]=Ro[qo]);if("undefined"!=typeof window){var Bo=window.hotkeys;jo.noConflict=function(e){return e&&window.hotkeys===jo&&(window.hotkeys=Bo),jo},window.hotkeys=jo}const Uo=kt({args:void 0,config:void 0,data:void 0,status:"IDLE"});var Fo=n(9049),zo=n.n(Fo);const $o=new class{limits={};limitSuffix=["critical","careful","warning"];setLimits(e){this.limits=e}getAlert(e,t,n,r,i){var s=(i=i||!1)?"_log":"",o=100*(n=n||0)/(r=r||100);if(null!=this.limits[e])for(var a=0;a<this.limitSuffix.length;a++){var l=t+this.limitSuffix[a];if(o>=this.limits[e][l]){var c=l.lastIndexOf("_");return l.substring(c+1)+s}}return"ok"+s}getAlertLog(e,t,n,r){return this.getAlert(e,t,n,r,!0)}};const Ho=new class{data=void 0;init(e=60){let t;const n=()=>(Uo.status="PENDING",Promise.all([fetch("api/4/all",{method:"GET"}).then((e=>e.json())),fetch("api/4/all/views",{method:"GET"}).then((e=>e.json()))]).then((e=>{const t={stats:e[0],views:e[1],isBsd:"FreeBSD"===e[0].system.os_name,isLinux:"Linux"===e[0].system.os_name,isSunOS:"SunOS"===e[0].system.os_name,isMac:"Darwin"===e[0].system.os_name,isWindows:"Windows"===e[0].system.os_name};this.data=t,Uo.data=t,Uo.status="SUCCESS"})).catch((e=>{console.log(e),Uo.status="FAILURE"})).then((()=>{t&&clearTimeout(t),t=setTimeout(n,1e3*e)})));n(),fetch("api/4/all/limits",{method:"GET"}).then((e=>e.json())).then((e=>{$o.setLimits(e)})),fetch("api/4/args",{method:"GET"}).then((e=>e.json())).then(((e={})=>{Uo.args={...Uo.args,...e}})),fetch("api/4/config",{method:"GET"}).then((e=>e.json())).then(((e={})=>{Uo.config={...Uo.config,...e}}))}getData(){return this.data}};const Vo=new class{constructor(){this.favico=new(zo())({animation:"none"})}badge(e){this.favico.badge(e)}reset(){this.favico.reset()}},Go={key:0},Wo={class:"container-fluid"},Zo={class:"row"},Ko={class:"col-sm-12 col-lg-24"},Qo=wi("div",{class:"row"}," ",-1),Xo={class:"row"},Jo={class:"col-sm-12 col-lg-24"},Yo=wi("div",{class:"row"}," ",-1),ea={class:"divTable",style:{width:"100%"}},ta={class:"divTableBody"},na={class:"divTableRow"},ra={class:"divTableHead"},ia={class:"divTableHead"},sa={class:"divTableHead"},oa={class:"divTableHead"},aa={class:"divTableRow"},la={class:"divTableCell"},ca={class:"divTableCell"},ua={class:"divTableCell"},da={class:"divTableCell"},fa={class:"divTableRow"},pa={class:"divTableCell"},ha={class:"divTableCell"},ga={class:"divTableCell"},ma={class:"divTableCell"},ba={class:"divTableRow"},va={class:"divTableCell"},ya={class:"divTableCell"},wa={class:"divTableCell"},xa={class:"divTableCell"},_a={class:"divTableRow"},ka={class:"divTableCell"},Sa={class:"divTableCell"},Ca={class:"divTableCell"},Ta={class:"divTableCell"},Aa={class:"divTableRow"},Ea={class:"divTableCell"},Oa={class:"divTableCell"},Ia={class:"divTableCell"},Pa={class:"divTableCell"},Na={class:"divTableRow"},La={class:"divTableCell"},Da={class:"divTableCell"},Ma={class:"divTableCell"},ja={class:"divTableCell"},Ra={class:"divTableRow"},qa={class:"divTableCell"},Ba={class:"divTableCell"},Ua={class:"divTableCell"},Fa={class:"divTableCell"},za={class:"divTableRow"},$a=wi("div",{class:"divTableCell"}," ",-1),Ha={class:"divTableCell"},Va={class:"divTableCell"},Ga={class:"divTableCell"},Wa={class:"divTableRow"},Za=wi("div",{class:"divTableCell"}," ",-1),Ka={class:"divTableCell"},Qa={class:"divTableCell"},Xa={class:"divTableCell"},Ja={class:"divTableRow"},Ya=wi("div",{class:"divTableCell"}," ",-1),el={class:"divTableCell"},tl={class:"divTableCell"},nl={class:"divTableCell"},rl={class:"divTableRow"},il=wi("div",{class:"divTableCell"}," ",-1),sl={class:"divTableCell"},ol=wi("div",{class:"divTableCell"}," ",-1),al={class:"divTableCell"},ll={class:"divTableRow"},cl=wi("div",{class:"divTableCell"}," ",-1),ul={class:"divTableCell"},dl=wi("div",{class:"divTableCell"}," ",-1),fl=wi("div",{class:"divTableCell"}," ",-1),pl={class:"divTableRow"},hl=wi("div",{class:"divTableCell"}," ",-1),gl={class:"divTableCell"},ml=wi("div",{class:"divTableCell"}," ",-1),bl=wi("div",{class:"divTableCell"}," ",-1),vl={class:"divTableRow"},yl=wi("div",{class:"divTableCell"}," ",-1),wl={class:"divTableCell"},xl=wi("div",{class:"divTableCell"}," ",-1),_l=wi("div",{class:"divTableCell"}," ",-1),kl={class:"divTableRow"},Sl=wi("div",{class:"divTableCell"}," ",-1),Cl={class:"divTableCell"},Tl=wi("div",{class:"divTableCell"}," ",-1),Al=wi("div",{class:"divTableCell"}," ",-1),El={class:"divTableRow"},Ol=wi("div",{class:"divTableCell"}," ",-1),Il={class:"divTableCell"},Pl=wi("div",{class:"divTableCell"}," ",-1),Nl=wi("div",{class:"divTableCell"}," ",-1),Ll={class:"divTableRow"},Dl=wi("div",{class:"divTableCell"}," ",-1),Ml={class:"divTableCell"},jl=wi("div",{class:"divTableCell"}," ",-1),Rl=wi("div",{class:"divTableCell"}," ",-1),ql={class:"divTableRow"},Bl=wi("div",{class:"divTableCell"}," ",-1),Ul={class:"divTableCell"},Fl=wi("div",{class:"divTableCell"}," ",-1),zl=wi("div",{class:"divTableCell"}," ",-1),$l={class:"divTableRow"},Hl=wi("div",{class:"divTableCell"}," ",-1),Vl={class:"divTableCell"},Gl=wi("div",{class:"divTableCell"}," ",-1),Wl=wi("div",{class:"divTableCell"}," ",-1),Zl={class:"divTableRow"},Kl=wi("div",{class:"divTableCell"}," ",-1),Ql={class:"divTableCell"},Xl=wi("div",{class:"divTableCell"}," ",-1),Jl=wi("div",{class:"divTableCell"}," ",-1),Yl=wi("div",null,[wi("p",null,[Si(" For an exhaustive list of key bindings, "),wi("a",{href:"https://glances.readthedocs.io/en/latest/cmds.html#interactive-commands"},"click here"),Si(". ")])],-1),ec=wi("div",null,[wi("p",null,[Si("Press "),wi("b",null,"h"),Si(" to came back to Glances.")])],-1);const tc={data:()=>({help:void 0}),mounted(){fetch("api/4/help",{method:"GET"}).then((e=>e.json())).then((e=>this.help=e))}};var nc=n(3744);const rc=(0,nc.Z)(tc,[["render",function(e,t,n,r,i,s){return i.help?(li(),pi("div",Go,[wi("div",Wo,[wi("div",Zo,[wi("div",Ko,pe(i.help.version)+" "+pe(i.help.psutil_version),1)]),Qo,wi("div",Xo,[wi("div",Jo,pe(i.help.configuration_file),1)]),Yo]),wi("div",ea,[wi("div",ta,[wi("div",na,[wi("div",ra,pe(i.help.header_sort.replace(":","")),1),wi("div",ia,pe(i.help.header_show_hide.replace(":","")),1),wi("div",sa,pe(i.help.header_toggle.replace(":","")),1),wi("div",oa,pe(i.help.header_miscellaneous.replace(":","")),1)]),wi("div",aa,[wi("div",la,pe(i.help.sort_auto),1),wi("div",ca,pe(i.help.show_hide_application_monitoring),1),wi("div",ua,pe(i.help.toggle_bits_bytes),1),wi("div",da,pe(i.help.misc_erase_process_filter),1)]),wi("div",fa,[wi("div",pa,pe(i.help.sort_cpu),1),wi("div",ha,pe(i.help.show_hide_diskio),1),wi("div",ga,pe(i.help.toggle_count_rate),1),wi("div",ma,pe(i.help.misc_generate_history_graphs),1)]),wi("div",ba,[wi("div",va,pe(i.help.sort_io_rate),1),wi("div",ya,pe(i.help.show_hide_containers),1),wi("div",wa,pe(i.help.toggle_used_free),1),wi("div",xa,pe(i.help.misc_help),1)]),wi("div",_a,[wi("div",ka,pe(i.help.sort_mem),1),wi("div",Sa,pe(i.help.show_hide_top_extended_stats),1),wi("div",Ca,pe(i.help.toggle_bar_sparkline),1),wi("div",Ta,pe(i.help.misc_accumulate_processes_by_program),1)]),wi("div",Aa,[wi("div",Ea,pe(i.help.sort_process_name),1),wi("div",Oa,pe(i.help.show_hide_filesystem),1),wi("div",Ia,pe(i.help.toggle_separate_combined),1),wi("div",Pa,pe(i.help.misc_kill_process)+" - N/A in WebUI ",1)]),wi("div",Na,[wi("div",La,pe(i.help.sort_cpu_times),1),wi("div",Da,pe(i.help.show_hide_gpu),1),wi("div",Ma,pe(i.help.toggle_live_cumulative),1),wi("div",ja,pe(i.help.misc_reset_processes_summary_min_max),1)]),wi("div",Ra,[wi("div",qa,pe(i.help.sort_user),1),wi("div",Ba,pe(i.help.show_hide_ip),1),wi("div",Ua,pe(i.help.toggle_linux_percentage),1),wi("div",Fa,pe(i.help.misc_quit),1)]),wi("div",za,[$a,wi("div",Ha,pe(i.help.show_hide_tcp_connection),1),wi("div",Va,pe(i.help.toggle_cpu_individual_combined),1),wi("div",Ga,pe(i.help.misc_reset_history),1)]),wi("div",Wa,[Za,wi("div",Ka,pe(i.help.show_hide_alert),1),wi("div",Qa,pe(i.help.toggle_gpu_individual_combined),1),wi("div",Xa,pe(i.help.misc_delete_warning_alerts),1)]),wi("div",Ja,[Ya,wi("div",el,pe(i.help.show_hide_network),1),wi("div",tl,pe(i.help.toggle_short_full),1),wi("div",nl,pe(i.help.misc_delete_warning_and_critical_alerts),1)]),wi("div",rl,[il,wi("div",sl,pe(i.help.sort_cpu_times),1),ol,wi("div",al,pe(i.help.misc_edit_process_filter_pattern)+" - N/A in WebUI ",1)]),wi("div",ll,[cl,wi("div",ul,pe(i.help.show_hide_irq),1),dl,fl]),wi("div",pl,[hl,wi("div",gl,pe(i.help.show_hide_raid_plugin),1),ml,bl]),wi("div",vl,[yl,wi("div",wl,pe(i.help.show_hide_sensors),1),xl,_l]),wi("div",kl,[Sl,wi("div",Cl,pe(i.help.show_hide_wifi_module),1),Tl,Al]),wi("div",El,[Ol,wi("div",Il,pe(i.help.show_hide_processes),1),Pl,Nl]),wi("div",Ll,[Dl,wi("div",Ml,pe(i.help.show_hide_left_sidebar),1),jl,Rl]),wi("div",ql,[Bl,wi("div",Ul,pe(i.help.show_hide_quick_look),1),Fl,zl]),wi("div",$l,[Hl,wi("div",Vl,pe(i.help.show_hide_cpu_mem_swap),1),Gl,Wl]),wi("div",Zl,[Kl,wi("div",Ql,pe(i.help.show_hide_all),1),Xl,Jl])])]),Yl,ec])):Ti("v-if",!0)}]]),ic={class:"plugin"},sc={id:"alerts"},oc={key:0,class:"title"},ac={key:1,class:"title"},lc={id:"alert"},cc={class:"table"},uc={class:"table-cell text-left"};var dc=n(6486);const fc={props:{data:{type:Object}},computed:{stats(){return this.data.stats.alert},alerts(){return(this.stats||[]).map((e=>{const t={};var n=(new Date).getTimezoneOffset();if(t.state=e.state,t.type=e.type,t.begin=1e3*e.begin-60*n*1e3,t.end=1e3*e.end-60*n*1e3,t.ongoing=-1==e.end,t.min=e.min,t.avg=e.avg,t.max=e.max,t.top=e.top.join(", "),t.global=e.global,!t.ongoing){const e=t.end-t.begin,n=parseInt(e/1e3%60),r=parseInt(e/6e4%60),i=parseInt(e/36e5%24);t.duration=(0,dc.padStart)(i,2,"0")+":"+(0,dc.padStart)(r,2,"0")+":"+(0,dc.padStart)(n,2,"0")}return t}))},hasAlerts(){return this.countAlerts>0},countAlerts(){return this.alerts.length},hasOngoingAlerts(){return this.countOngoingAlerts>0},countOngoingAlerts(){return this.alerts.filter((({ongoing:e})=>e)).length}},watch:{countOngoingAlerts(){this.countOngoingAlerts?Vo.badge(this.countOngoingAlerts):Vo.reset()}},methods:{formatDate:e=>new Date(e).toISOString().slice(0,19).replace(/[^\d-:]/," ")}},pc=(0,nc.Z)(fc,[["render",function(e,t,n,r,i,s){return li(),pi("div",ic,[wi("section",sc,[s.hasAlerts?(li(),pi("span",oc," Warning or critical alerts (last "+pe(s.countAlerts)+" entries) ",1)):(li(),pi("span",ac,"No warning or critical alert detected"))]),wi("section",lc,[wi("div",cc,[(li(!0),pi(ni,null,pr(s.alerts,((t,n)=>(li(),pi("div",{class:"table-row",key:n},[wi("div",uc,[Si(pe(s.formatDate(t.begin))+" "+pe(t.tz)+" ("+pe(t.ongoing?"ongoing":t.duration)+") - ",1),On(wi("span",null,pe(t.state)+" on ",513),[[Ds,!t.ongoing]]),wi("span",{class:ce(t.state.toLowerCase())},pe(t.type),3),Si(" ("+pe(e.$filters.number(t.max,1))+") "+pe(t.top),1)])])))),128))])])])}]]),hc={key:0,id:"cloud",class:"plugin"},gc={class:"title"};const mc={props:{data:{type:Object}},computed:{stats(){return this.data.stats.cloud},provider(){return void 0!==this.stats.id?`${stats.platform}`:null},instance(){const{stats:e}=this;return void 0!==this.stats.id?`${e.type} instance ${e.name} (${e.region})`:null}}},bc=(0,nc.Z)(mc,[["render",function(e,t,n,r,i,s){return s.instance||s.provider?(li(),pi("section",hc,[wi("span",gc,pe(s.provider),1),Si(" "+pe(s.instance),1)])):Ti("v-if",!0)}]]),vc={class:"plugin",id:"connections"},yc=wi("div",{class:"table-row"},[wi("div",{class:"table-cell text-left title"},"TCP CONNECTIONS"),wi("div",{class:"table-cell"})],-1),wc={class:"table-row"},xc=wi("div",{class:"table-cell text-left"},"Listen",-1),_c=wi("div",{class:"table-cell"},null,-1),kc={class:"table-cell"},Sc={class:"table-row"},Cc=wi("div",{class:"table-cell text-left"},"Initiated",-1),Tc=wi("div",{class:"table-cell"},null,-1),Ac={class:"table-cell"},Ec={class:"table-row"},Oc=wi("div",{class:"table-cell text-left"},"Established",-1),Ic=wi("div",{class:"table-cell"},null,-1),Pc={class:"table-cell"},Nc={class:"table-row"},Lc=wi("div",{class:"table-cell text-left"},"Terminated",-1),Dc=wi("div",{class:"table-cell"},null,-1),Mc={class:"table-cell"},jc={class:"table-row"},Rc=wi("div",{class:"table-cell text-left"},"Tracked",-1),qc=wi("div",{class:"table-cell"},null,-1);const Bc={props:{data:{type:Object}},computed:{stats(){return this.data.stats.connections},view(){return this.data.views.connections},listen(){return this.stats.LISTEN},initiated(){return this.stats.initiated},established(){return this.stats.ESTABLISHED},terminated(){return this.stats.terminated},tracked(){return{count:this.stats.nf_conntrack_count,max:this.stats.nf_conntrack_max}}},methods:{getDecoration(e){if(void 0!==this.view[e])return this.view[e].decoration.toLowerCase()}}},Uc=(0,nc.Z)(Bc,[["render",function(e,t,n,r,i,s){return li(),pi("section",vc,[yc,wi("div",wc,[xc,_c,wi("div",kc,pe(s.listen),1)]),wi("div",Sc,[Cc,Tc,wi("div",Ac,pe(s.initiated),1)]),wi("div",Ec,[Oc,Ic,wi("div",Pc,pe(s.established),1)]),wi("div",Nc,[Lc,Dc,wi("div",Mc,pe(s.terminated),1)]),wi("div",jc,[Rc,qc,wi("div",{class:ce(["table-cell",s.ge