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 * 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 * Alias definition change in the configuration file #1735
Glances version 3.x and lower: Glances version 3.x and lower:
sda1_alias=InternalDisk sda1_alias=InternalDisk
sdb1_alias=ExternalDisk sdb1_alias=ExternalDisk
Glances version 4.x and higher: Glances version 4.x and higher:
alias=sda1:InternalDisk,sdb1:ExternalDisk 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 Version 3.4.0.3

View File

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

View File

@ -25,14 +25,20 @@ class GlancesEvents(object):
event_value = value event_value = value
Item (or event) is defined by: Item (or event) is defined by:
["begin", {
"end", "begin": "begin",
"WARNING|CRITICAL", "end": "end",
"CPU|LOAD|MEM", "state": "WARNING|CRITICAL",
MAX, AVG, MIN, SUM, COUNT, "type": "CPU|LOAD|MEM",
[top3 process list], "max": MAX,
"Processes description", "avg": AVG,
"top sort key"] "min": MIN,
"sum": SUM,
"count": COUNT,
"top": [top 3 process name],
"desc": "Processes description",
"sort": "top sort key"
}
""" """
def __init__(self, max_events=10): def __init__(self, max_events=10):
@ -60,11 +66,11 @@ class GlancesEvents(object):
An event exist if: An event exist if:
* end is < 0 * end is < 0
* event_type is matching * type is matching
Return -1 if the item is not found. Return -1 if the item is not found.
""" """
for i in range(self.len()): 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 i
return -1 return -1
@ -124,20 +130,20 @@ class GlancesEvents(object):
# Create the new log item # Create the new log item
# Time is stored in Epoch format # Time is stored in Epoch format
# Epoch -> DMYHMS = datetime.fromtimestamp(epoch) # Epoch -> DMYHMS = datetime.fromtimestamp(epoch)
item = [ item = {
time.mktime(datetime.now().timetuple()), # START DATE "begin": time.mktime(datetime.now().timetuple()),
-1, # END DATE "end": -1,
event_state, # STATE: WARNING|CRITICAL "state": event_state,
event_type, # TYPE: CPU, LOAD, MEM... "type": event_type,
event_value, # MAX "max": event_value,
event_value, # AVG "avg": event_value,
event_value, # MIN "min": event_value,
event_value, # SUM "sum": event_value,
1, # COUNT "count": 1,
[], # TOP 3 PROCESS LIST "top": [],
proc_desc, # MONITORED PROCESSES DESC "desc": proc_desc,
glances_processes.sort_key, "sort": glances_processes.sort_key,
] # TOP PROCESS SORT KEY }
# Add the item to the list # Add the item to the list
self.events_list.insert(0, item) self.events_list.insert(0, item)
@ -145,7 +151,6 @@ class GlancesEvents(object):
# Limit the list to 'max_events' items # Limit the list to 'max_events' items
if self.len() > self.max_events: if self.len() > self.max_events:
self.events_list.pop() self.events_list.pop()
return True return True
else: else:
return False return False
@ -158,9 +163,9 @@ class GlancesEvents(object):
# Set the end of the events # Set the end of the events
end_time = time.mktime(datetime.now().timetuple()) 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 # If event is > peak_time seconds
self.events_list[event_index][1] = end_time self.events_list[event_index]['end'] = end_time
else: else:
# If event <= peak_time seconds, ignore # If event <= peak_time seconds, ignore
self.events_list.remove(self.events_list[event_index]) self.events_list.remove(self.events_list[event_index])
@ -170,25 +175,25 @@ class GlancesEvents(object):
# State # State
if event_state == "CRITICAL": if event_state == "CRITICAL":
self.events_list[event_index][2] = event_state self.events_list[event_index]['state'] = event_state
# Min value # 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 # 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 # Average value
self.events_list[event_index][7] += event_value self.events_list[event_index]['sum'] += event_value
self.events_list[event_index][8] += 1 self.events_list[event_index]['count'] += 1
self.events_list[event_index][5] = self.events_list[event_index][7] / self.events_list[event_index][8] 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) # TOP PROCESS LIST (only for CRITICAL ALERT)
if event_state == "CRITICAL": if event_state == "CRITICAL":
events_sort_key = self.get_event_sort_key(event_type) events_sort_key = self.get_event_sort_key(event_type)
# Sort the current process list to retrieve the TOP 3 processes # 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]['top'] = [p['name'] for p in sort_stats(proc_list, events_sort_key)[0:3]]
self.events_list[event_index][11] = events_sort_key self.events_list[event_index]['sort'] = events_sort_key
# MONITORED PROCESSES DESC # MONITORED PROCESSES DESC
self.events_list[event_index][10] = proc_desc self.events_list[event_index]['desc'] = proc_desc
return True return True
@ -202,7 +207,7 @@ class GlancesEvents(object):
clean_events_list = [] clean_events_list = []
while self.len() > 0: while self.len() > 0:
item = self.events_list.pop() 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) clean_events_list.insert(0, item)
# The list is now the clean one # The list is now the clean one
self.events_list = clean_events_list self.events_list = clean_events_list

View File

@ -13,11 +13,12 @@
{{ formatDate(alert.begin) }} {{ formatDate(alert.begin) }}
{{ alert.tz }} {{ alert.tz }}
({{ alert.ongoing ? 'ongoing' : alert.duration }}) - ({{ alert.ongoing ? 'ongoing' : alert.duration }}) -
<span v-show="!alert.ongoing"> {{ alert.level }} on </span> <span v-show="!alert.ongoing"> {{ alert.state }} on </span>
<span :class="alert.level.toLowerCase()"> <span :class="alert.state.toLowerCase()">
{{ alert.name }} {{ alert.type }}
</span> </span>
({{ $filters.number(alert.max, 1) }}) ({{ $filters.number(alert.max, 1) }})
{{ alert.top }}
</div> </div>
</div> </div>
</div> </div>
@ -43,14 +44,15 @@ export default {
return (this.stats || []).map((alertalertStats) => { return (this.stats || []).map((alertalertStats) => {
const alert = {}; const alert = {};
var tzoffset = new Date().getTimezoneOffset(); var tzoffset = new Date().getTimezoneOffset();
alert.name = alertalertStats[3]; alert.state = alertalertStats.state;
alert.level = alertalertStats[2]; alert.type = alertalertStats.type;
alert.begin = alertalertStats[0] * 1000 - tzoffset * 60 * 1000; alert.begin = alertalertStats.begin * 1000 - tzoffset * 60 * 1000;
alert.end = alertalertStats[1] * 1000 - tzoffset * 60 * 1000; alert.end = alertalertStats.end * 1000 - tzoffset * 60 * 1000;
alert.ongoing = alertalertStats[1] == -1; alert.ongoing = alertalertStats.end == -1;
alert.min = alertalertStats[6]; alert.min = alertalertStats.min;
alert.mean = alertalertStats[5]; alert.avg = alertalertStats.avg;
alert.max = alertalertStats[4]; alert.max = alertalertStats.max;
alert.top = alertalertStats.top.join(', ');
if (!alert.ongoing) { if (!alert.ongoing) {
const duration = alert.end - alert.begin; 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.logger import logger
from glances.plugins.plugin.model import GlancesPluginModel 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 # Static decision tree for the global alert message
# - msg: Message to be displayed (result of the decision tree) # - msg: Message to be displayed (result of the decision tree)
# - thresholds: a list of stats to take into account # - thresholds: a list of stats to take into account
@ -172,7 +243,11 @@ class PluginModel(GlancesPluginModel):
def __init__(self, args=None, config=None): def __init__(self, args=None, config=None):
"""Init the plugin.""" """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 # We want to display the stat in the curse interface
self.display_curse = True self.display_curse = True
@ -210,32 +285,35 @@ class PluginModel(GlancesPluginModel):
# New line # New line
ret.append(self.curse_new_line()) ret.append(self.curse_new_line())
# Start # 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)) ret.append(self.curse_add_line(msg))
# Duration # Duration
if alert[1] > 0: if alert['end'] > 0:
# If finished display duration # 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: else:
msg = ' (ongoing)' msg = ' (ongoing)'
ret.append(self.curse_add_line(msg)) ret.append(self.curse_add_line(msg))
ret.append(self.curse_add_line(" - ")) ret.append(self.curse_add_line(" - "))
# Infos # Infos
if alert[1] > 0: if alert['end'] > 0:
# If finished do not display status # 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)) ret.append(self.curse_add_line(msg))
else: else:
msg = str(alert[3]) msg = str(alert['type'])
ret.append(self.curse_add_line(msg, decoration=alert[2])) ret.append(self.curse_add_line(msg, decoration=alert['state']))
# Min / Mean / Max # Min / Mean / Max
if self.approx_equal(alert[6], alert[4], tolerance=0.1): if self.approx_equal(alert['min'], alert['max'], tolerance=0.1):
msg = ' ({:.1f})'.format(alert[5]) msg = ' ({:.1f})'.format(alert['avg'])
else: 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)) ret.append(self.curse_add_line(msg))
# Top processes # Top processes
top_process = ', '.join([p['name'] for p in alert[9]]) top_process = ', '.join(alert['top'])
if top_process != '': if top_process != '':
msg = ': {}'.format(top_process) msg = ': {}'.format(top_process)
ret.append(self.curse_add_line(msg)) ret.append(self.curse_add_line(msg))

View File

@ -415,12 +415,13 @@ class GlancesPluginModel(object):
def get_raw_stats_value(self, item, value): def get_raw_stats_value(self, item, value):
"""Return the stats object for a specific 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): if not isinstance(self.stats, list):
return None return None
else: 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) value = int(value)
try: try:
return {value: [i for i in self.stats if i[item] == value]} 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) self.assertIsInstance(req.json(), text_type)
elif p in ('fs', 'percpu', 'sensors', 'alert', 'processlist', 'diskio', elif p in ('fs', 'percpu', 'sensors', 'alert', 'processlist', 'diskio',
'hddtemp', 'batpercent', 'network', 'folders', 'amps', 'ports', 'hddtemp', 'batpercent', 'network', 'folders', 'amps', 'ports',
'irq', 'wifi', 'gpu'): 'irq', 'wifi', 'gpu', 'containers'):
self.assertIsInstance(req.json(), list) self.assertIsInstance(req.json(), list)
if len(req.json()) > 0:
self.assertIsInstance(req.json()[0], dict)
else: else:
self.assertIsInstance(req.json(), dict) self.assertIsInstance(req.json(), dict)