Refactor Alert data model from list of list to list of dict #2633

This commit is contained in:
nicolargo 2023-12-23 11:01:41 +01:00
parent 947e24c8cb
commit 6edd6fd1ff
9 changed files with 341 additions and 210 deletions

View File

@ -12,12 +12,17 @@ Under development: https://github.com/nicolargo/glances/issues?q=is%3Aopen+is%3A
* The Glances API version 3 is replaced by the version 4. So Restfull API URL is now /api/4/ #2610
* Alias definition change in the configuration file #1735
Glances version 3.x and lower:
sda1_alias=InternalDisk
sdb1_alias=ExternalDisk
Glances version 4.x and higher:
alias=sda1:InternalDisk,sdb1:ExternalDisk
* Alias can now be used to redefine FS name #1735
* Alert data model change from a list of list to a list of dict #2633
===============
Version 3.4.0.3

View File

@ -109,18 +109,54 @@ GET alert
Get plugin stats::
# curl http://localhost:61208/api/4/alert
[[1703267698.0,
-1,
"WARNING",
"MEM",
77.65786849069791,
77.65786849069791,
77.65786849069791,
77.65786849069791,
1,
[],
"",
"memory_percent"]]
[{"avg": 71.7690328288976,
"begin": 1703324631.0,
"count": 1,
"desc": "",
"end": -1,
"max": 71.7690328288976,
"min": 71.7690328288976,
"sort": "memory_percent",
"state": "WARNING",
"sum": 71.7690328288976,
"top": [],
"type": "MEM"}]
Fields descriptions:
* **begin**: Begin timestamp of the event (unit is *timestamp*)
* **end**: End timestamp of the event (or -1 if ongoing) (unit is *timestamp*)
* **state**: State of the event (WARNING|CRITICAL) (unit is *string*)
* **type**: Type of the event (CPU|LOAD|MEM) (unit is *string*)
* **max**: Maximum value during the event period (unit is *float*)
* **avg**: Average value during the event period (unit is *float*)
* **min**: Minimum value during the event period (unit is *float*)
* **sum**: Sum of the values during the event period (unit is *float*)
* **count**: Number of values during the event period (unit is *int*)
* **top**: Top 3 processes name during the event period (unit is *list*)
* **desc**: Description of the event (unit is *string*)
* **sort**: Sort key of the top processes (unit is *string*)
Get a specific field::
# curl http://localhost:61208/api/4/alert/begin
{"begin": [1703324631.0]}
Get a specific item when field matches the given value::
# curl http://localhost:61208/api/4/alert/begin/1703324631.0
{"1703324631.0": [{"avg": 71.7690328288976,
"begin": 1703324631.0,
"count": 1,
"desc": "",
"end": -1,
"max": 71.7690328288976,
"min": 71.7690328288976,
"sort": "memory_percent",
"state": "WARNING",
"sum": 71.7690328288976,
"top": [],
"type": "MEM"}]}
GET amps
--------
@ -136,7 +172,7 @@ Get plugin stats::
"refresh": 3.0,
"regex": True,
"result": None,
"timer": 0.3074169158935547},
"timer": 0.3228726387023926},
{"count": 0,
"countmax": 20.0,
"countmin": None,
@ -145,7 +181,7 @@ Get plugin stats::
"refresh": 3.0,
"regex": True,
"result": None,
"timer": 0.30725765228271484}]
"timer": 0.3227043151855469}]
Fields descriptions:
@ -173,7 +209,7 @@ Get a specific item when field matches the given value::
"refresh": 3.0,
"regex": True,
"result": None,
"timer": 0.3074169158935547}]}
"timer": 0.3228726387023926}]}
GET connections
---------------
@ -207,8 +243,8 @@ Get plugin stats::
# curl http://localhost:61208/api/4/containers
[{"command": "top",
"cpu": {"total": 1.2265872243101236e-06},
"cpu_percent": 1.2265872243101236e-06,
"cpu": {"total": 1.2822740648554537e-06},
"cpu_percent": 1.2822740648554537e-06,
"created": "2023-12-09T10:45:34.339489876+01:00",
"engine": "podman",
"id": "481d6ffb7eef284d062628cf350bdd9ce0a803db8a2a505d75565ed24322b714",
@ -217,8 +253,8 @@ Get plugin stats::
"io_rx": 0.0,
"io_wx": 0.0,
"key": "name",
"memory": {"limit": 7823585280.0, "usage": 1388544.0},
"memory_usage": 1388544.0,
"memory": {"limit": 7823585280.0, "usage": 1376256.0},
"memory_usage": 1376256.0,
"name": "sad_darwin",
"network": {"rx": 0.0, "time_since_update": 1, "tx": 0.0},
"network_rx": 0.0,
@ -228,8 +264,8 @@ Get plugin stats::
"status": "running",
"uptime": "1 weeks"},
{"command": "",
"cpu": {"total": 3.3083466569066167e-10},
"cpu_percent": 3.3083466569066167e-10,
"cpu": {"total": 3.319390733197021e-10},
"cpu_percent": 3.319390733197021e-10,
"created": "2022-10-22T14:23:03.120912374+02:00",
"engine": "podman",
"id": "9491515251edcd5bb5dc17205d7ee573c0be96fe0b08b0a12a7e2cea874565ea",
@ -238,8 +274,8 @@ Get plugin stats::
"io_rx": 0.0,
"io_wx": 0.0,
"key": "name",
"memory": {"limit": 7823585280.0, "usage": 327680.0},
"memory_usage": 327680.0,
"memory": {"limit": 7823585280.0, "usage": 319488.0},
"memory_usage": 319488.0,
"name": "8d0f1c783def-infra",
"network": {"rx": 0.0, "time_since_update": 1, "tx": 0.0},
"network_rx": 0.0,
@ -277,8 +313,8 @@ Get a specific item when field matches the given value::
# curl http://localhost:61208/api/4/containers/name/sad_darwin
{"sad_darwin": [{"command": "top",
"cpu": {"total": 1.2265872243101236e-06},
"cpu_percent": 1.2265872243101236e-06,
"cpu": {"total": 1.2822740648554537e-06},
"cpu_percent": 1.2822740648554537e-06,
"created": "2023-12-09T10:45:34.339489876+01:00",
"engine": "podman",
"id": "481d6ffb7eef284d062628cf350bdd9ce0a803db8a2a505d75565ed24322b714",
@ -287,8 +323,8 @@ Get a specific item when field matches the given value::
"io_rx": 0.0,
"io_wx": 0.0,
"key": "name",
"memory": {"limit": 7823585280.0, "usage": 1388544.0},
"memory_usage": 1388544.0,
"memory": {"limit": 7823585280.0, "usage": 1376256.0},
"memory_usage": 1376256.0,
"name": "sad_darwin",
"network": {"rx": 0.0, "time_since_update": 1, "tx": 0.0},
"network_rx": 0.0,
@ -326,19 +362,19 @@ Get plugin stats::
"ctx_switches": 0,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 73.0,
"idle": 64.1,
"interrupts": 0,
"iowait": 0.0,
"iowait": 0.5,
"irq": 0.0,
"nice": 0.0,
"soft_interrupts": 0,
"softirq": 0.0,
"steal": 0.0,
"syscalls": 0,
"system": 2.2,
"system": 12.6,
"time_since_update": 1,
"total": 27.0,
"user": 24.9}
"total": 35.4,
"user": 22.7}
Fields descriptions:
@ -361,7 +397,7 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/cpu/total
{"total": 27.0}
{"total": 35.4}
GET diskio
----------
@ -418,13 +454,13 @@ Get plugin stats::
# curl http://localhost:61208/api/4/fs
[{"alias": "Root",
"device_name": "/dev/mapper/ubuntu--gnome--vg-root",
"free": 25931997184,
"free": 25977536512,
"fs_type": "ext4",
"key": "mnt_point",
"mnt_point": "/",
"percent": 88.8,
"size": 243334156288,
"used": 205014704128},
"used": 204969164800},
{"device_name": "zsfpool",
"free": 31195136,
"fs_type": "zfs",
@ -454,13 +490,13 @@ Get a specific item when field matches the given value::
# curl http://localhost:61208/api/4/fs/mnt_point//
{"/": [{"alias": "Root",
"device_name": "/dev/mapper/ubuntu--gnome--vg-root",
"free": 25931997184,
"free": 25977536512,
"fs_type": "ext4",
"key": "mnt_point",
"mnt_point": "/",
"percent": 88.8,
"size": 243334156288,
"used": 205014704128}]}
"used": 204969164800}]}
GET ip
------
@ -495,10 +531,7 @@ GET load
Get plugin stats::
# curl http://localhost:61208/api/4/load
{"cpucore": 4,
"min1": 1.02978515625,
"min15": 1.37255859375,
"min5": 1.27783203125}
{"cpucore": 4, "min1": 1.8193359375, "min15": 1.66552734375, "min5": 1.58203125}
Fields descriptions:
@ -510,7 +543,7 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/load/min1
{"min1": 1.02978515625}
{"min1": 1.8193359375}
GET mem
-------
@ -518,16 +551,16 @@ GET mem
Get plugin stats::
# curl http://localhost:61208/api/4/mem
{"active": 3293724672,
"available": 1747955712,
"buffers": 105394176,
"cached": 1907453952,
"free": 1747955712,
"inactive": 2607702016,
"percent": 77.7,
"shared": 546648064,
{"active": 3406278656,
"available": 2208673792,
"buffers": 109953024,
"cached": 1813655552,
"free": 2208673792,
"inactive": 2144509952,
"percent": 71.8,
"shared": 509751296,
"total": 7823585280,
"used": 6075629568}
"used": 5614911488}
Fields descriptions:
@ -554,13 +587,13 @@ GET memswap
Get plugin stats::
# curl http://localhost:61208/api/4/memswap
{"free": 4666490880,
"percent": 42.3,
"sin": 8551440384,
"sout": 14097289216,
{"free": 4540248064,
"percent": 43.8,
"sin": 8918196224,
"sout": 14552772608,
"time_since_update": 1,
"total": 8082419712,
"used": 3415928832}
"used": 3542171648}
Fields descriptions:
@ -584,9 +617,9 @@ Get plugin stats::
# curl http://localhost:61208/api/4/network
[{"alias": None,
"cumulative_cx": 1917091264,
"cumulative_rx": 958545632,
"cumulative_tx": 958545632,
"cumulative_cx": 1949107280,
"cumulative_rx": 974553640,
"cumulative_tx": 974553640,
"cx": 0,
"interface_name": "lo",
"is_up": True,
@ -596,14 +629,14 @@ Get plugin stats::
"time_since_update": 1,
"tx": 0},
{"alias": "WIFI",
"cumulative_cx": 6804843378,
"cumulative_rx": 6353991859,
"cumulative_tx": 450851519,
"cx": 1056,
"cumulative_cx": 6848799089,
"cumulative_rx": 6385848903,
"cumulative_tx": 462950186,
"cx": 224,
"interface_name": "wlp2s0",
"is_up": True,
"key": "interface_name",
"rx": 930,
"rx": 98,
"speed": 0,
"time_since_update": 1,
"tx": 126}]
@ -637,9 +670,9 @@ Get a specific item when field matches the given value::
# curl http://localhost:61208/api/4/network/interface_name/lo
{"lo": [{"alias": None,
"cumulative_cx": 1917091264,
"cumulative_rx": 958545632,
"cumulative_tx": 958545632,
"cumulative_cx": 1949107280,
"cumulative_rx": 974553640,
"cumulative_tx": 974553640,
"cx": 0,
"interface_name": "lo",
"is_up": True,
@ -655,7 +688,7 @@ GET now
Get plugin stats::
# curl http://localhost:61208/api/4/now
"2023-12-22 18:54:58 CET"
"2023-12-23 10:43:51 CET"
GET percpu
----------
@ -666,29 +699,29 @@ Get plugin stats::
[{"cpu_number": 0,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 31.0,
"iowait": 0.0,
"idle": 25.0,
"iowait": 1.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 2.0,
"total": 69.0,
"user": 15.0},
"system": 3.0,
"total": 75.0,
"user": 21.0},
{"cpu_number": 1,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 35.0,
"iowait": 0.0,
"idle": 33.0,
"iowait": 1.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 1.0,
"total": 65.0,
"user": 9.0}]
"system": 3.0,
"total": 67.0,
"user": 11.0}]
Fields descriptions:
@ -722,7 +755,7 @@ Get plugin stats::
"port": 0,
"refresh": 30,
"rtt_warning": None,
"status": 0.007214,
"status": 0.007002,
"timeout": 3}]
Fields descriptions:
@ -750,7 +783,7 @@ Get a specific item when field matches the given value::
"port": 0,
"refresh": 30,
"rtt_warning": None,
"status": 0.007214,
"status": 0.007002,
"timeout": 3}]}
GET processcount
@ -759,7 +792,7 @@ GET processcount
Get plugin stats::
# curl http://localhost:61208/api/4/processcount
{"pid_max": 0, "running": 2, "sleeping": 312, "thread": 1495, "total": 379}
{"pid_max": 0, "running": 1, "sleeping": 313, "thread": 1486, "total": 390}
Fields descriptions:
@ -772,7 +805,7 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/processcount/total
{"total": 379}
{"total": 390}
GET psutilversion
-----------------
@ -788,54 +821,54 @@ GET quicklook
Get plugin stats::
# curl http://localhost:61208/api/4/quicklook
{"cpu": 27.0,
{"cpu": 35.4,
"cpu_hz": 2025000000.0,
"cpu_hz_current": 2047157750.0,
"cpu_hz_current": 1785102250.0,
"cpu_name": "Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz",
"mem": 77.7,
"mem": 71.8,
"percpu": [{"cpu_number": 0,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 31.0,
"iowait": 0.0,
"idle": 25.0,
"iowait": 1.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 2.0,
"total": 69.0,
"user": 15.0},
"system": 3.0,
"total": 75.0,
"user": 21.0},
{"cpu_number": 1,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 35.0,
"iowait": 0.0,
"idle": 33.0,
"iowait": 1.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 1.0,
"total": 65.0,
"user": 9.0},
"system": 3.0,
"total": 67.0,
"user": 11.0},
{"cpu_number": 2,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 43.0,
"idle": 21.0,
"iowait": 0.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 0.0,
"total": 57.0,
"user": 2.0},
"system": 18.0,
"total": 79.0,
"user": 10.0},
{"cpu_number": 3,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 27.0,
"idle": 47.0,
"iowait": 0.0,
"irq": 0.0,
"key": "cpu_number",
@ -843,9 +876,9 @@ Get plugin stats::
"softirq": 0.0,
"steal": 0.0,
"system": 1.0,
"total": 73.0,
"user": 19.0}],
"swap": 42.3}
"total": 53.0,
"user": 2.0}],
"swap": 43.8}
Fields descriptions:
@ -859,7 +892,7 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/quicklook/cpu
{"cpu": 27.0}
{"cpu": 35.4}
GET sensors
-----------
@ -948,7 +981,7 @@ GET uptime
Get plugin stats::
# curl http://localhost:61208/api/4/uptime
"27 days, 9:57:04"
"28 days, 1:45:56"
GET version
-----------
@ -972,28 +1005,33 @@ GET top n items of a specific plugin
Get top 2 processes of the processlist plugin::
# curl http://localhost:61208/api/4/processlist/top/2
[{"cmdline": ["/snap/firefox/3206/usr/lib/firefox/firefox"],
[{"cmdline": ["/usr/share/code/code",
"--ms-enable-electron-run-as-node",
"/home/nicolargo/.vscode/extensions/ms-python.vscode-pylance-2023.12.1/dist/server.bundle.js",
"--cancellationReceive=file:810abd06604ca203178b3fa9390087012fbf550dba",
"--node-ipc",
"--clientProcessId=391253"],
"cpu_percent": 0.0,
"cpu_times": {"children_system": 1408.84,
"children_user": 10148.43,
"cpu_times": {"children_system": 0.41,
"children_user": 4.19,
"iowait": 0.0,
"system": 3365.72,
"user": 11764.01},
"system": 256.43,
"user": 4368.89},
"gids": {"effective": 1000, "real": 1000, "saved": 1000},
"io_counters": [9456750592, 13008068608, 0, 0, 0],
"io_counters": [355196928, 1896448, 0, 0, 0],
"key": "pid",
"memory_info": {"data": 1410756608,
"memory_info": {"data": 886296576,
"dirty": 0,
"lib": 0,
"rss": 517181440,
"shared": 109961216,
"text": 643072,
"vms": 13905248256},
"memory_percent": 6.610542628353635,
"name": "firefox",
"rss": 500559872,
"shared": 20254720,
"text": 120565760,
"vms": 1207768694784},
"memory_percent": 6.398088013172395,
"name": "code",
"nice": 0,
"num_threads": 138,
"pid": 7195,
"num_threads": 13,
"pid": 391817,
"status": "S",
"time_since_update": 1,
"username": "nicolargo"},
@ -1024,19 +1062,19 @@ Get top 2 processes of the processlist plugin::
"cpu_times": {"children_system": 0.0,
"children_user": 0.0,
"iowait": 0.0,
"system": 390.29,
"user": 4351.56},
"system": 399.65,
"user": 4442.83},
"gids": {"effective": 1000, "real": 1000, "saved": 1000},
"io_counters": [517786624, 0, 0, 0, 0],
"io_counters": [580611072, 0, 0, 0, 0],
"key": "pid",
"memory_info": {"data": 1422823424,
"memory_info": {"data": 1419350016,
"dirty": 0,
"lib": 0,
"rss": 497307648,
"shared": 54018048,
"rss": 482299904,
"shared": 50790400,
"text": 643072,
"vms": 4070424576},
"memory_percent": 6.356518529571138,
"vms": 4056260608},
"memory_percent": 6.164691592650474,
"name": "WebExtensions",
"nice": 0,
"num_threads": 20,
@ -1071,34 +1109,34 @@ GET stats history
History of a plugin::
# curl http://localhost:61208/api/4/cpu/history
{"system": [["2023-12-22T18:55:00.816728", 3.5],
["2023-12-22T18:55:01.837000", 3.5],
["2023-12-22T18:55:03.276090", 6.7]],
"user": [["2023-12-22T18:55:00.816716", 39.2],
["2023-12-22T18:55:01.836985", 39.2],
["2023-12-22T18:55:03.276079", 30.4]]}
{"system": [["2023-12-23T10:43:53.365630", 12.6],
["2023-12-23T10:43:54.388206", 2.3],
["2023-12-23T10:43:55.606404", 2.3]],
"user": [["2023-12-23T10:43:53.365616", 22.7],
["2023-12-23T10:43:54.388189", 12.7],
["2023-12-23T10:43:55.606390", 12.7]]}
Limit history to last 2 values::
# curl http://localhost:61208/api/4/cpu/history/2
{"system": [["2023-12-22T18:55:01.837000", 3.5],
["2023-12-22T18:55:03.276090", 6.7]],
"user": [["2023-12-22T18:55:01.836985", 39.2],
["2023-12-22T18:55:03.276079", 30.4]]}
{"system": [["2023-12-23T10:43:54.388206", 2.3],
["2023-12-23T10:43:55.606404", 2.3]],
"user": [["2023-12-23T10:43:54.388189", 12.7],
["2023-12-23T10:43:55.606390", 12.7]]}
History for a specific field::
# curl http://localhost:61208/api/4/cpu/system/history
{"system": [["2023-12-22T18:54:58.788338", 2.2],
["2023-12-22T18:55:00.816728", 3.5],
["2023-12-22T18:55:01.837000", 3.5],
["2023-12-22T18:55:03.276090", 6.7]]}
{"system": [["2023-12-23T10:43:51.624123", 12.6],
["2023-12-23T10:43:53.365630", 12.6],
["2023-12-23T10:43:54.388206", 2.3],
["2023-12-23T10:43:55.606404", 2.3]]}
Limit history for a specific field to last 2 values::
# curl http://localhost:61208/api/4/cpu/system/history
{"system": [["2023-12-22T18:55:01.837000", 3.5],
["2023-12-22T18:55:03.276090", 6.7]]}
{"system": [["2023-12-23T10:43:54.388206", 2.3],
["2023-12-23T10:43:55.606404", 2.3]]}
GET limits (used for thresholds)
--------------------------------

View File

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "GLANCES" "1" "Dec 22, 2023" "4.0.0_beta01" "Glances"
.TH "GLANCES" "1" "Dec 23, 2023" "4.0.0_beta01" "Glances"
.SH NAME
glances \- An eye on your system
.SH SYNOPSIS

View File

@ -25,14 +25,20 @@ class GlancesEvents(object):
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"]
{
"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"
}
"""
def __init__(self, max_events=10):
@ -60,11 +66,11 @@ class GlancesEvents(object):
An event exist if:
* end is < 0
* event_type is matching
* 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:
if self.events_list[i]['end'] < 0 and self.events_list[i]['type'] == event_type:
return i
return -1
@ -124,20 +130,20 @@ class GlancesEvents(object):
# 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 SORT KEY
item = {
"begin": time.mktime(datetime.now().timetuple()),
"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,
}
# Add the item to the list
self.events_list.insert(0, item)
@ -145,7 +151,6 @@ class GlancesEvents(object):
# Limit the list to 'max_events' items
if self.len() > self.max_events:
self.events_list.pop()
return True
else:
return False
@ -158,9 +163,9 @@ class GlancesEvents(object):
# Set the end of the events
end_time = time.mktime(datetime.now().timetuple())
if end_time - self.events_list[event_index][0] > peak_time:
if end_time - self.events_list[event_index]['begin'] > peak_time:
# If event is > peak_time seconds
self.events_list[event_index][1] = end_time
self.events_list[event_index]['end'] = end_time
else:
# If event <= peak_time seconds, ignore
self.events_list.remove(self.events_list[event_index])
@ -170,25 +175,25 @@ class GlancesEvents(object):
# State
if event_state == "CRITICAL":
self.events_list[event_index][2] = event_state
self.events_list[event_index]['state'] = event_state
# Min value
self.events_list[event_index][6] = min(self.events_list[event_index][6], event_value)
self.events_list[event_index]['min'] = min(self.events_list[event_index]['min'], event_value)
# Max value
self.events_list[event_index][4] = max(self.events_list[event_index][4], event_value)
self.events_list[event_index]['max'] = max(self.events_list[event_index]['max'], 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]
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']
# TOP PROCESS LIST (only for CRITICAL ALERT)
if event_state == "CRITICAL":
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][9] = sort_stats(proc_list, events_sort_key)[0:3]
self.events_list[event_index][11] = events_sort_key
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][10] = proc_desc
self.events_list[event_index]['desc'] = proc_desc
return True
@ -202,7 +207,7 @@ class GlancesEvents(object):
clean_events_list = []
while self.len() > 0:
item = self.events_list.pop()
if item[1] < 0 or (not critical and item[2].startswith("CRITICAL")):
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

View File

@ -13,11 +13,12 @@
{{ formatDate(alert.begin) }}
{{ alert.tz }}
({{ alert.ongoing ? 'ongoing' : alert.duration }}) -
<span v-show="!alert.ongoing"> {{ alert.level }} on </span>
<span :class="alert.level.toLowerCase()">
{{ alert.name }}
<span v-show="!alert.ongoing"> {{ alert.state }} on </span>
<span :class="alert.state.toLowerCase()">
{{ alert.type }}
</span>
({{ $filters.number(alert.max, 1) }})
{{ alert.top }}
</div>
</div>
</div>
@ -43,14 +44,15 @@ export default {
return (this.stats || []).map((alertalertStats) => {
const alert = {};
var tzoffset = new Date().getTimezoneOffset();
alert.name = alertalertStats[3];
alert.level = alertalertStats[2];
alert.begin = alertalertStats[0] * 1000 - tzoffset * 60 * 1000;
alert.end = alertalertStats[1] * 1000 - tzoffset * 60 * 1000;
alert.ongoing = alertalertStats[1] == -1;
alert.min = alertalertStats[6];
alert.mean = alertalertStats[5];
alert.max = alertalertStats[4];
alert.state = alertalertStats.state;
alert.type = alertalertStats.type;
alert.begin = alertalertStats.begin * 1000 - tzoffset * 60 * 1000;
alert.end = alertalertStats.end * 1000 - tzoffset * 60 * 1000;
alert.ongoing = alertalertStats.end == -1;
alert.min = alertalertStats.min;
alert.avg = alertalertStats.avg;
alert.max = alertalertStats.max;
alert.top = alertalertStats.top.join(', ');
if (!alert.ongoing) {
const duration = alert.end - alert.begin;

File diff suppressed because one or more lines are too long

View File

@ -19,6 +19,77 @@ from glances.thresholds import glances_thresholds
# from glances.logger import logger
from glances.plugins.plugin.model import GlancesPluginModel
# {
# "begin": "begin",
# "end": "end",
# "state": "WARNING|CRITICAL",
# "type": "CPU|LOAD|MEM",
# "max": MAX,
# "avg": AVG,
# "min": MIN,
# "sum": SUM,
# "count": COUNT,
# "top": [top3 process list],
# "desc": "Processes description",
# "sort": "top sort key"
# }
# Fields description
# description: human readable description
# short_name: shortname to use un UI
# unit: unit type
# rate: is it a rate ? If yes, // by time_since_update when displayed,
# min_symbol: Auto unit should be used if value > than 1 'X' (K, M, G)...
fields_description = {
'begin': {
'description': 'Begin timestamp of the event',
'unit': 'timestamp',
},
'end': {
'description': 'End timestamp of the event (or -1 if ongoing)',
'unit': 'timestamp',
},
'state': {
'description': 'State of the event (WARNING|CRITICAL)',
'unit': 'string',
},
'type': {
'description': 'Type of the event (CPU|LOAD|MEM)',
'unit': 'string',
},
'max': {
'description': 'Maximum value during the event period',
'unit': 'float',
},
'avg': {
'description': 'Average value during the event period',
'unit': 'float',
},
'min': {
'description': 'Minimum value during the event period',
'unit': 'float',
},
'sum': {
'description': 'Sum of the values during the event period',
'unit': 'float',
},
'count': {
'description': 'Number of values during the event period',
'unit': 'int',
},
'top': {
'description': 'Top 3 processes name during the event period',
'unit': 'list',
},
'desc': {
'description': 'Description of the event',
'unit': 'string',
},
'sort': {
'description': 'Sort key of the top processes',
'unit': 'string',
},
}
# 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
@ -172,7 +243,11 @@ class PluginModel(GlancesPluginModel):
def __init__(self, args=None, config=None):
"""Init the plugin."""
super(PluginModel, self).__init__(args=args, config=config, stats_init_value=[])
super(PluginModel, self).__init__(
args=args, config=config,
stats_init_value=[],
fields_description=fields_description
)
# We want to display the stat in the curse interface
self.display_curse = True
@ -210,32 +285,35 @@ class PluginModel(GlancesPluginModel):
# New line
ret.append(self.curse_new_line())
# Start
msg = str(datetime.fromtimestamp(alert[0], tz=pytz.timezone(tzname[0] if tzname[0] else 'UTC')))
msg = str(datetime.fromtimestamp(alert['begin'],
tz=pytz.timezone(tzname[0] if tzname[0] else 'UTC')))
ret.append(self.curse_add_line(msg))
# Duration
if alert[1] > 0:
if alert['end'] > 0:
# If finished display duration
msg = ' ({})'.format(datetime.fromtimestamp(alert[1]) - datetime.fromtimestamp(alert[0]))
msg = ' ({})'.format(datetime.fromtimestamp(alert['end']) - datetime.fromtimestamp(alert['begin']))
else:
msg = ' (ongoing)'
ret.append(self.curse_add_line(msg))
ret.append(self.curse_add_line(" - "))
# Infos
if alert[1] > 0:
if alert['end'] > 0:
# If finished do not display status
msg = '{} on {}'.format(alert[2], alert[3])
msg = '{} on {}'.format(alert['state'], alert['type'])
ret.append(self.curse_add_line(msg))
else:
msg = str(alert[3])
ret.append(self.curse_add_line(msg, decoration=alert[2]))
msg = str(alert['type'])
ret.append(self.curse_add_line(msg, decoration=alert['state']))
# Min / Mean / Max
if self.approx_equal(alert[6], alert[4], tolerance=0.1):
msg = ' ({:.1f})'.format(alert[5])
if self.approx_equal(alert['min'], alert['max'], tolerance=0.1):
msg = ' ({:.1f})'.format(alert['avg'])
else:
msg = ' (Min:{:.1f} Mean:{:.1f} Max:{:.1f})'.format(alert[6], alert[5], alert[4])
msg = ' (Min:{:.1f} Mean:{:.1f} Max:{:.1f})'.format(alert['min'],
alert['avg'],
alert['max'])
ret.append(self.curse_add_line(msg))
# Top processes
top_process = ', '.join([p['name'] for p in alert[9]])
top_process = ', '.join(alert['top'])
if top_process != '':
msg = ': {}'.format(top_process)
ret.append(self.curse_add_line(msg))

View File

@ -415,12 +415,13 @@ class GlancesPluginModel(object):
def get_raw_stats_value(self, item, value):
"""Return the stats object for a specific item=value.
Stats should be a list of dict (processlist, network...)
Return None if the item=value does not exist
Return None if the item is not a list of dict
"""
if not isinstance(self.stats, list):
return None
else:
if not isinstance(value, int) and value.isdigit():
if (not isinstance(value, int) and not isinstance(value, float)) and value.isdigit():
value = int(value)
try:
return {value: [i for i in self.stats if i[item] == value]}

View File

@ -104,8 +104,10 @@ class TestGlances(unittest.TestCase):
self.assertIsInstance(req.json(), text_type)
elif p in ('fs', 'percpu', 'sensors', 'alert', 'processlist', 'diskio',
'hddtemp', 'batpercent', 'network', 'folders', 'amps', 'ports',
'irq', 'wifi', 'gpu'):
'irq', 'wifi', 'gpu', 'containers'):
self.assertIsInstance(req.json(), list)
if len(req.json()) > 0:
self.assertIsInstance(req.json()[0], dict)
else:
self.assertIsInstance(req.json(), dict)