Merge branch 'issue2662' into develop

This commit is contained in:
nicolargo 2024-01-28 10:42:58 +01:00
commit 787f98d5ef
11 changed files with 400 additions and 341 deletions

View File

@ -45,8 +45,11 @@ max_processes_display=25
# Set to true to disable a plugin
# Note: you can also disable it from the command line (see --disable-plugin <plugin_name>)
disable=False
# Graphical percentage char used in the terminal user interface (default is |)
percentage_char=|
# Stats list (default is cpu,mem,load)
# Available stats are: cpu,mem,load,swap
list=cpu,mem,load
# Graphical bar char used in the terminal user interface (default is |)
bar_char=|
# Define CPU, MEM and SWAP thresholds in %
cpu_careful=50
cpu_warning=70
@ -57,6 +60,11 @@ mem_critical=90
swap_careful=50
swap_warning=70
swap_critical=90
# Source: http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages
# With 1 CPU core, the load should be lower than 1.00 ~ 100%
load_careful=70
load_warning=100
load_critical=500
[system]
# This plugin display the first line in the Glances UI with:

View File

@ -4,7 +4,7 @@ Quick Look
==========
The ``quicklook`` plugin is only displayed on wide screen and proposes a
bar view for CPU and memory (virtual and swap).
bar view for cpu, memory, swap and load (this list is configurable).
In the terminal interface, click on ``3`` to enable/disable it.
@ -27,10 +27,14 @@ client/server mode (see issue ).
Limit values can be overwritten in the configuration file under
the ``[quicklook]`` section.
You can also configure the percentage char used in the terminal user interface.
You can also configure the stats list and the bat character used in the
user interface.
.. code-block:: ini
[quicklook]
# Stats list (default is cpu,mem,load)
# Available stats are: cpu,mem,load,swap
list=cpu,mem,load
# Graphical percentage char used in the terminal user interface (default is |)
percentage_char=@
bar_char=|

View File

@ -109,16 +109,16 @@ GET alert
Get plugin stats::
# curl http://localhost:61208/api/4/alert
[{"avg": 75.58190732727591,
"begin": 1705242982.0,
[{"avg": 81.2863503930515,
"begin": 1706434886.0,
"count": 1,
"desc": "",
"end": -1,
"max": 75.58190732727591,
"min": 75.58190732727591,
"max": 81.2863503930515,
"min": 81.2863503930515,
"sort": "memory_percent",
"state": "WARNING",
"sum": 75.58190732727591,
"sum": 81.2863503930515,
"top": [],
"type": "MEM"}]
@ -140,21 +140,21 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/alert/begin
{"begin": [1705242982.0]}
{"begin": [1706434886.0]}
Get a specific item when field matches the given value::
# curl http://localhost:61208/api/4/alert/begin/1705242982.0
{"1705242982.0": [{"avg": 75.58190732727591,
"begin": 1705242982.0,
# curl http://localhost:61208/api/4/alert/begin/1706434886.0
{"1706434886.0": [{"avg": 81.2863503930515,
"begin": 1706434886.0,
"count": 1,
"desc": "",
"end": -1,
"max": 75.58190732727591,
"min": 75.58190732727591,
"max": 81.2863503930515,
"min": 81.2863503930515,
"sort": "memory_percent",
"state": "WARNING",
"sum": 75.58190732727591,
"sum": 81.2863503930515,
"top": [],
"type": "MEM"}]}
@ -172,7 +172,7 @@ Get plugin stats::
"refresh": 3.0,
"regex": True,
"result": None,
"timer": 0.19934892654418945},
"timer": 0.36128687858581543},
{"count": 0,
"countmax": 20.0,
"countmin": None,
@ -181,7 +181,7 @@ Get plugin stats::
"refresh": 3.0,
"regex": True,
"result": None,
"timer": 0.19925165176391602}]
"timer": 0.36110568046569824}]
Fields descriptions:
@ -209,7 +209,7 @@ Get a specific item when field matches the given value::
"refresh": 3.0,
"regex": True,
"result": None,
"timer": 0.19934892654418945}]}
"timer": 0.36128687858581543}]}
GET connections
---------------
@ -243,8 +243,8 @@ Get plugin stats::
# curl http://localhost:61208/api/4/containers
[{"command": "top",
"cpu": {"total": 1.8635523677666806e-06},
"cpu_percent": 1.8635523677666806e-06,
"cpu": {"total": 2.4258436881746593e-06},
"cpu_percent": 2.4258436881746593e-06,
"created": "2023-12-09T10:45:34.339489876+01:00",
"engine": "podman",
"id": "481d6ffb7eef284d062628cf350bdd9ce0a803db8a2a505d75565ed24322b714",
@ -253,8 +253,8 @@ Get plugin stats::
"io_rx": 0.0,
"io_wx": 0.0,
"key": "name",
"memory": {"limit": 7823585280.0, "usage": 1306624.0},
"memory_usage": 1306624.0,
"memory": {"limit": 7823585280.0, "usage": 1212416.0},
"memory_usage": 1212416.0,
"name": "sad_darwin",
"network": {"rx": 0.0, "time_since_update": 1, "tx": 0.0},
"network_rx": 0.0,
@ -264,8 +264,8 @@ Get plugin stats::
"status": "running",
"uptime": "1 months"},
{"command": "",
"cpu": {"total": 3.4505346487574547e-10},
"cpu_percent": 3.4505346487574547e-10,
"cpu": {"total": 3.5348550629383954e-10},
"cpu_percent": 3.5348550629383954e-10,
"created": "2022-10-22T14:23:03.120912374+02:00",
"engine": "podman",
"id": "9491515251edcd5bb5dc17205d7ee573c0be96fe0b08b0a12a7e2cea874565ea",
@ -274,8 +274,8 @@ Get plugin stats::
"io_rx": 0.0,
"io_wx": 0.0,
"key": "name",
"memory": {"limit": 7823585280.0, "usage": 290816.0},
"memory_usage": 290816.0,
"memory": {"limit": 7823585280.0, "usage": 237568.0},
"memory_usage": 237568.0,
"name": "8d0f1c783def-infra",
"network": {"rx": 0.0, "time_since_update": 1, "tx": 0.0},
"network_rx": 0.0,
@ -313,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.8635523677666806e-06},
"cpu_percent": 1.8635523677666806e-06,
"cpu": {"total": 2.4258436881746593e-06},
"cpu_percent": 2.4258436881746593e-06,
"created": "2023-12-09T10:45:34.339489876+01:00",
"engine": "podman",
"id": "481d6ffb7eef284d062628cf350bdd9ce0a803db8a2a505d75565ed24322b714",
@ -323,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": 1306624.0},
"memory_usage": 1306624.0,
"memory": {"limit": 7823585280.0, "usage": 1212416.0},
"memory_usage": 1212416.0,
"name": "sad_darwin",
"network": {"rx": 0.0, "time_since_update": 1, "tx": 0.0},
"network_rx": 0.0,
@ -362,7 +362,7 @@ Get plugin stats::
"ctx_switches": 0,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 74.6,
"idle": 43.4,
"interrupts": 0,
"iowait": 0.0,
"irq": 0.0,
@ -371,10 +371,10 @@ Get plugin stats::
"softirq": 0.0,
"steal": 0.0,
"syscalls": 0,
"system": 3.3,
"system": 7.8,
"time_since_update": 1,
"total": 25.4,
"user": 22.1}
"total": 56.6,
"user": 48.8}
Fields descriptions:
@ -397,7 +397,7 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/cpu/total
{"total": 25.4}
{"total": 56.6}
GET diskio
----------
@ -454,13 +454,13 @@ Get plugin stats::
# curl http://localhost:61208/api/4/fs
[{"alias": "Root",
"device_name": "/dev/mapper/ubuntu--gnome--vg-root",
"free": 19083309056,
"free": 17195761664,
"fs_type": "ext4",
"key": "mnt_point",
"mnt_point": "/",
"percent": 91.7,
"percent": 92.6,
"size": 243334156288,
"used": 211863392256},
"used": 213750939648},
{"device_name": "zsfpool",
"free": 31195136,
"fs_type": "zfs",
@ -490,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": 19083309056,
"free": 17195761664,
"fs_type": "ext4",
"key": "mnt_point",
"mnt_point": "/",
"percent": 91.7,
"percent": 92.6,
"size": 243334156288,
"used": 211863392256}]}
"used": 213750939648}]}
GET ip
------
@ -504,11 +504,11 @@ GET ip
Get plugin stats::
# curl http://localhost:61208/api/4/ip
{"address": "192.168.0.32",
"gateway": "192.168.0.254",
{"address": "192.168.1.14",
"gateway": "192.168.1.1",
"mask": "255.255.255.0",
"mask_cidr": 24,
"public_address": "91.166.228.228",
"public_address": "92.151.148.66",
"public_info_human": ""}
Fields descriptions:
@ -523,7 +523,7 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/ip/gateway
{"gateway": "192.168.0.254"}
{"gateway": "192.168.1.1"}
GET load
--------
@ -531,10 +531,7 @@ GET load
Get plugin stats::
# curl http://localhost:61208/api/4/load
{"cpucore": 4,
"min1": 1.00927734375,
"min15": 0.66259765625,
"min5": 0.7548828125}
{"cpucore": 4, "min1": 2.142578125, "min15": 2.2412109375, "min5": 2.296875}
Fields descriptions:
@ -546,7 +543,7 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/load/min1
{"min1": 1.00927734375}
{"min1": 2.142578125}
GET mem
-------
@ -554,16 +551,16 @@ GET mem
Get plugin stats::
# curl http://localhost:61208/api/4/mem
{"active": 2827825152,
"available": 1910370304,
"buffers": 442753024,
"cached": 1887649792,
"free": 1910370304,
"inactive": 3567714304,
"percent": 75.6,
"shared": 457003008,
{"active": 2943950848,
"available": 1464078336,
"buffers": 63561728,
"cached": 1855676416,
"free": 1464078336,
"inactive": 3364462592,
"percent": 81.3,
"shared": 513527808,
"total": 7823585280,
"used": 5913214976}
"used": 6359506944}
Fields descriptions:
@ -590,13 +587,13 @@ GET memswap
Get plugin stats::
# curl http://localhost:61208/api/4/memswap
{"free": 3856048128,
"percent": 52.3,
"sin": 14772441088,
"sout": 22269526016,
{"free": 3434184704,
"percent": 57.5,
"sin": 21763555328,
"sout": 30277906432,
"time_since_update": 1,
"total": 8082419712,
"used": 4226371584}
"used": 4648235008}
Fields descriptions:
@ -620,26 +617,26 @@ Get plugin stats::
# curl http://localhost:61208/api/4/network
[{"alias": None,
"cumulative_cx": 2537577204,
"cumulative_rx": 1268788602,
"cumulative_tx": 1268788602,
"cx": 0,
"cumulative_cx": 2734623262,
"cumulative_rx": 1367311631,
"cumulative_tx": 1367311631,
"cx": 576,
"interface_name": "lo",
"is_up": True,
"key": "interface_name",
"rx": 0,
"rx": 288,
"speed": 0,
"time_since_update": 1,
"tx": 0},
"tx": 288},
{"alias": "WIFI",
"cumulative_cx": 14514673497,
"cumulative_rx": 11339647204,
"cumulative_tx": 3175026293,
"cx": 224,
"cumulative_cx": 16571979029,
"cumulative_rx": 13260033314,
"cumulative_tx": 3311945715,
"cx": 186,
"interface_name": "wlp2s0",
"is_up": True,
"key": "interface_name",
"rx": 98,
"rx": 60,
"speed": 0,
"time_since_update": 1,
"tx": 126}]
@ -666,24 +663,24 @@ Get a specific field::
"br-40875d2e2716",
"docker0",
"br_grafana",
"veth55598fc",
"mpqemubr0"]}
"mpqemubr0",
"vethbeef843"]}
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": 2537577204,
"cumulative_rx": 1268788602,
"cumulative_tx": 1268788602,
"cx": 0,
"cumulative_cx": 2734623262,
"cumulative_rx": 1367311631,
"cumulative_tx": 1367311631,
"cx": 576,
"interface_name": "lo",
"is_up": True,
"key": "interface_name",
"rx": 0,
"rx": 288,
"speed": 0,
"time_since_update": 1,
"tx": 0}]}
"tx": 288}]}
GET now
-------
@ -691,7 +688,7 @@ GET now
Get plugin stats::
# curl http://localhost:61208/api/4/now
"2024-01-14 15:36:22 CET"
"2024-01-28 10:41:26 CET"
GET percpu
----------
@ -700,19 +697,6 @@ Get plugin stats::
# curl http://localhost:61208/api/4/percpu
[{"cpu_number": 0,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 20.0,
"iowait": 0.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 2.0,
"total": 80.0,
"user": 9.0},
{"cpu_number": 1,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 23.0,
@ -722,9 +706,22 @@ Get plugin stats::
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 2.0,
"system": 5.0,
"total": 77.0,
"user": 7.0}]
"user": 22.0},
{"cpu_number": 1,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 16.0,
"iowait": 0.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 4.0,
"total": 84.0,
"user": 31.0}]
Fields descriptions:
@ -753,12 +750,12 @@ Get plugin stats::
# curl http://localhost:61208/api/4/ports
[{"description": "DefaultGateway",
"host": "192.168.0.254",
"host": "192.168.1.1",
"indice": "port_0",
"port": 0,
"refresh": 30,
"rtt_warning": None,
"status": 0.005277,
"status": 0.007028,
"timeout": 3}]
Fields descriptions:
@ -775,19 +772,19 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/ports/host
{"host": ["192.168.0.254"]}
{"host": ["192.168.1.1"]}
Get a specific item when field matches the given value::
# curl http://localhost:61208/api/4/ports/host/192.168.0.254
{"192.168.0.254": [{"description": "DefaultGateway",
"host": "192.168.0.254",
"indice": "port_0",
"port": 0,
"refresh": 30,
"rtt_warning": None,
"status": 0.005277,
"timeout": 3}]}
# curl http://localhost:61208/api/4/ports/host/192.168.1.1
{"192.168.1.1": [{"description": "DefaultGateway",
"host": "192.168.1.1",
"indice": "port_0",
"port": 0,
"refresh": 30,
"rtt_warning": None,
"status": 0.007028,
"timeout": 3}]}
GET processcount
----------------
@ -795,7 +792,7 @@ GET processcount
Get plugin stats::
# curl http://localhost:61208/api/4/processcount
{"pid_max": 0, "running": 1, "sleeping": 326, "thread": 1611, "total": 392}
{"pid_max": 0, "running": 1, "sleeping": 336, "thread": 1717, "total": 412}
Fields descriptions:
@ -808,7 +805,7 @@ Fields descriptions:
Get a specific field::
# curl http://localhost:61208/api/4/processcount/total
{"total": 392}
{"total": 412}
GET psutilversion
-----------------
@ -824,25 +821,14 @@ GET quicklook
Get plugin stats::
# curl http://localhost:61208/api/4/quicklook
{"cpu": 25.4,
"cpu_hz": 3000000000.0,
"cpu_hz_current": 2723398750.0000005,
{"cpu": 56.6,
"cpu_hz": 2025000000.0,
"cpu_hz_current": 1723932000.0,
"cpu_name": "Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz",
"mem": 75.6,
"cpucore": 4,
"load": 56.0,
"mem": 81.3,
"percpu": [{"cpu_number": 0,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 20.0,
"iowait": 0.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 2.0,
"total": 80.0,
"user": 9.0},
{"cpu_number": 1,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 23.0,
@ -852,50 +838,64 @@ Get plugin stats::
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 2.0,
"system": 5.0,
"total": 77.0,
"user": 7.0},
"user": 22.0},
{"cpu_number": 1,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 16.0,
"iowait": 0.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 4.0,
"total": 84.0,
"user": 31.0},
{"cpu_number": 2,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 21.0,
"idle": 27.0,
"iowait": 0.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 1.0,
"total": 79.0,
"user": 9.0},
"system": 4.0,
"total": 73.0,
"user": 21.0},
{"cpu_number": 3,
"guest": 0.0,
"guest_nice": 0.0,
"idle": 28.0,
"idle": 24.0,
"iowait": 0.0,
"irq": 0.0,
"key": "cpu_number",
"nice": 0.0,
"softirq": 0.0,
"steal": 0.0,
"system": 1.0,
"total": 72.0,
"user": 3.0}],
"swap": 52.3}
"system": 3.0,
"total": 76.0,
"user": 25.0}],
"swap": 57.5}
Fields descriptions:
* **cpu**: CPU percent usage (unit is *percent*)
* **mem**: MEM percent usage (unit is *percent*)
* **swap**: SWAP percent usage (unit is *percent*)
* **load**: LOAD percent usage (unit is *percent*)
* **cpu_name**: CPU name (unit is *None*)
* **cpu_hz_current**: CPU current frequency (unit is *hertz*)
* **cpu_hz**: CPU max frequency (unit is *hertz*)
Get a specific field::
# curl http://localhost:61208/api/4/quicklook/cpu
{"cpu": 25.4}
# curl http://localhost:61208/api/4/quicklook/cpu_name
{"cpu_name": "Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz"}
GET sensors
-----------
@ -984,7 +984,7 @@ GET uptime
Get plugin stats::
# curl http://localhost:61208/api/4/uptime
"50 days, 6:38:24"
"64 days, 1:43:26"
GET version
-----------
@ -1009,85 +1009,63 @@ Get top 2 processes of the processlist plugin::
# curl http://localhost:61208/api/4/processlist/top/2
[{"cmdline": ["/usr/share/code/code",
"--ms-enable-electron-run-as-node",
"/home/nicolargo/.vscode/extensions/vue.volar-1.8.25/server.js",
"--node-ipc",
"--clientProcessId=391253"],
"cpu_percent": 0.0,
"cpu_times": {"children_system": 0.0,
"children_user": 0.0,
"iowait": 0.0,
"system": 182.3,
"user": 3586.33},
"gids": {"effective": 1000, "real": 1000, "saved": 1000},
"io_counters": [1702031360, 0, 0, 0, 0],
"key": "pid",
"memory_info": {"data": 792121344,
"dirty": 0,
"lib": 0,
"rss": 578248704,
"shared": 17330176,
"text": 120565760,
"vms": 1205534920704},
"memory_percent": 7.391096067914275,
"name": "code",
"nice": 0,
"num_threads": 8,
"pid": 391764,
"status": "S",
"time_since_update": 1,
"username": "nicolargo"},
{"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": 0.78,
"children_user": 6.15,
"cpu_times": {"children_system": 0.85,
"children_user": 6.34,
"iowait": 0.0,
"system": 360.08,
"user": 6010.89},
"system": 466.27,
"user": 7859.93},
"gids": {"effective": 1000, "real": 1000, "saved": 1000},
"io_counters": [1231159296, 2641920, 0, 0, 0],
"io_counters": [2126852096, 2703360, 0, 0, 0],
"key": "pid",
"memory_info": {"data": 899014656,
"memory_info": {"data": 944828416,
"dirty": 0,
"lib": 0,
"rss": 511119360,
"shared": 26382336,
"rss": 531513344,
"shared": 17362944,
"text": 120565760,
"vms": 1207768694784},
"memory_percent": 6.533057948593103,
"memory_percent": 6.793731070571267,
"name": "code",
"nice": 0,
"num_threads": 13,
"pid": 391817,
"status": "S",
"time_since_update": 1,
"username": "nicolargo"},
{"cmdline": ["/usr/share/code/code",
"--type=renderer",
"--crashpad-handler-pid=391157",
"--enable-crash-reporter=721e05a9-6035-4dcb-bd58-68097aa48dd0,no_channel",
"--user-data-dir=/home/nicolargo/.config/Code",
"--standard-schemes=vscode-webview,vscode-file",
"--enable-sandbox",
"--secure-schemes=vscode-webview,vscode-file",
"--bypasscsp-schemes",
"--cors-schemes=vscode-webview,vscode-file",
"--fetch-schemes=vscode-webview,vscode-file",
"--service-worker-schemes=vscode-webview",
"--streaming-schemes",
"--app-path=/usr/share/code/resources/app",
"--enable-sandbox",
"--enable-blink-features=HighlightAPI",
"--first-renderer-process",
"--lang=en-US",
"--num-raster-threads=2",
"--enable-main-frame-before-activation",
"--renderer-client-id=4",
"--time-ticks-at-unix-epoch=-1702561657662203",
"--launch-time-ticks=95866298101",
"--shared-files=v8_context_snapshot_data:100",
"--field-trial-handle=0,i,2865222574050452096,10380804405300286374,262144",
"--disable-features=CalculateNativeWinOcclusion,SpareRendererForSitePerProcess",
"--vscode-window-config=vscode:a08b576a-4b00-4480-bfc3-390d8aea727c"],
"cpu_percent": 0.0,
"cpu_times": {"children_system": 0.0,
"children_user": 0.0,
"iowait": 0.0,
"system": 872.37,
"user": 12288.82},
"gids": {"effective": 1000, "real": 1000, "saved": 1000},
"io_counters": [1207435264, 3117056, 0, 0, 0],
"key": "pid",
"memory_info": {"data": 1501626368,
"dirty": 0,
"lib": 0,
"rss": 484990976,
"shared": 76034048,
"text": 120565760,
"vms": 1220702756864},
"memory_percent": 6.199088507922547,
"name": "code",
"nice": 0,
"num_threads": 15,
"pid": 391192,
"status": "S",
"time_since_update": 1,
"username": "nicolargo"}]
Note: Only work for plugin with a list of items
@ -1116,34 +1094,34 @@ GET stats history
History of a plugin::
# curl http://localhost:61208/api/4/cpu/history
{"system": [["2024-01-14T15:36:24.814316", 3.3],
["2024-01-14T15:36:25.828843", 1.8],
["2024-01-14T15:36:26.982020", 1.8]],
"user": [["2024-01-14T15:36:24.814299", 22.1],
["2024-01-14T15:36:25.828836", 9.7],
["2024-01-14T15:36:26.982006", 9.7]]}
{"system": [["2024-01-28T10:41:28.116797", 7.8],
["2024-01-28T10:41:29.140407", 3.1],
["2024-01-28T10:41:30.368579", 3.1]],
"user": [["2024-01-28T10:41:28.116785", 48.8],
["2024-01-28T10:41:29.140398", 17.3],
["2024-01-28T10:41:30.368565", 17.3]]}
Limit history to last 2 values::
# curl http://localhost:61208/api/4/cpu/history/2
{"system": [["2024-01-14T15:36:25.828843", 1.8],
["2024-01-14T15:36:26.982020", 1.8]],
"user": [["2024-01-14T15:36:25.828836", 9.7],
["2024-01-14T15:36:26.982006", 9.7]]}
{"system": [["2024-01-28T10:41:29.140407", 3.1],
["2024-01-28T10:41:30.368579", 3.1]],
"user": [["2024-01-28T10:41:29.140398", 17.3],
["2024-01-28T10:41:30.368565", 17.3]]}
History for a specific field::
# curl http://localhost:61208/api/4/cpu/system/history
{"system": [["2024-01-14T15:36:22.968267", 3.3],
["2024-01-14T15:36:24.814316", 3.3],
["2024-01-14T15:36:25.828843", 1.8],
["2024-01-14T15:36:26.982020", 1.8]]}
{"system": [["2024-01-28T10:41:26.512718", 7.8],
["2024-01-28T10:41:28.116797", 7.8],
["2024-01-28T10:41:29.140407", 3.1],
["2024-01-28T10:41:30.368579", 3.1]]}
Limit history for a specific field to last 2 values::
# curl http://localhost:61208/api/4/cpu/system/history
{"system": [["2024-01-14T15:36:25.828843", 1.8],
["2024-01-14T15:36:26.982020", 1.8]]}
{"system": [["2024-01-28T10:41:29.140407", 3.1],
["2024-01-28T10:41:30.368579", 3.1]]}
GET limits (used for thresholds)
--------------------------------
@ -1301,14 +1279,18 @@ All limits/thresholds::
"19"]},
"psutilversion": {"history_size": 1200.0},
"quicklook": {"history_size": 1200.0,
"quicklook_bar_char": ["|"],
"quicklook_cpu_careful": 50.0,
"quicklook_cpu_critical": 90.0,
"quicklook_cpu_warning": 70.0,
"quicklook_disable": ["False"],
"quicklook_list": ["cpu", "mem", "load"],
"quicklook_load_careful": 70.0,
"quicklook_load_critical": 500.0,
"quicklook_load_warning": 100.0,
"quicklook_mem_careful": 50.0,
"quicklook_mem_critical": 90.0,
"quicklook_mem_warning": 70.0,
"quicklook_percentage_char": ["|"],
"quicklook_swap_careful": 50.0,
"quicklook_swap_critical": 90.0,
"quicklook_swap_warning": 70.0},

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" "Jan 14, 2024" "4.0.0_beta01" "Glances"
.TH "GLANCES" "1" "Jan 28, 2024" "4.0.0_beta01" "Glances"
.SH NAME
glances \- An eye on your system
.SH SYNOPSIS

View File

@ -15,7 +15,6 @@ from math import modf
class Bar(object):
"""Manage bar (progression or status).
import sys
@ -28,28 +27,36 @@ class Bar(object):
sys.stdout.flush()
"""
def __init__(self, size, percentage_char='|', empty_char=' ', pre_char='[', post_char=']', with_text=True):
def __init__(self, size,
bar_char='|',
empty_char=' ',
pre_char='[', post_char=']',
unit_char='%',
display_value=True,
min_value=0, max_value=100):
# Build curses_bars
self.__curses_bars = [empty_char] * 5 + [percentage_char] * 5
self.__curses_bars = [empty_char] * 5 + [bar_char] * 5
# Bar size
self.__size = size
# Bar current percent
self.__percent = 0
# Min and max value
self.min_value = 0
self.max_value = 100
self.min_value = min_value
self.max_value = max_value
# Char used for the decoration
self.__pre_char = pre_char
self.__post_char = post_char
self.__empty_char = empty_char
self.__with_text = with_text
self.__unit_char = unit_char
# Value should be displayed ?
self.__display_value = display_value
@property
def size(self, with_decoration=False):
# Return the bar size, with or without decoration
if with_decoration:
return self.__size
if self.__with_text:
if self.__display_value:
return self.__size - 6
@property
@ -58,10 +65,8 @@ class Bar(object):
@percent.setter
def percent(self, value):
if value <= self.min_value:
if value < self.min_value:
value = self.min_value
if value >= self.max_value:
value = self.max_value
self.__percent = value
@property
@ -72,16 +77,26 @@ class Bar(object):
def post_char(self):
return self.__post_char
def get(self):
def get(self, overwrite=''):
"""Return the bars."""
frac, whole = modf(self.size * self.percent / 100.0)
value = self.max_value if self.percent > self.max_value else self.percent
frac, whole = modf(self.size * value / 100.0)
ret = self.__curses_bars[8] * int(whole)
if frac > 0:
ret += self.__curses_bars[int(frac * 8)]
whole += 1
ret += self.__empty_char * int(self.size - whole)
if self.__with_text:
ret = '{}{:5.1f}%'.format(ret, self.percent)
if self.__display_value:
if self.percent > self.max_value:
ret = '{}>{:4.0f}{}'.format(ret,
self.max_value,
self.__unit_char)
else:
ret = '{}{:5.1f}{}'.format(ret,
self.percent,
self.__unit_char)
if overwrite and len(overwrite) < len(ret) - 6:
ret = overwrite + ret[len(overwrite):]
return ret
def __str__(self):

View File

@ -34,7 +34,10 @@ class Sparkline(object):
"""Manage sparklines (see https://pypi.org/project/sparklines/)."""
def __init__(self, size, pre_char='[', post_char=']', empty_char=' ', with_text=True):
def __init__(self, size,
pre_char='[', post_char=']',
unit_char='%',
display_value=True):
# If the sparklines python module available ?
self.__available = sparklines_module
# Sparkline size
@ -44,8 +47,9 @@ class Sparkline(object):
# Char used for the decoration
self.__pre_char = pre_char
self.__post_char = post_char
self.__empty_char = empty_char
self.__with_text = with_text
self.__unit_char = unit_char
# Value should be displayed ?
self.__display_value = display_value
@property
def available(self):
@ -56,7 +60,7 @@ class Sparkline(object):
# Return the sparkline size, with or without decoration
if with_decoration:
return self.__size
if self.__with_text:
if self.__display_value:
return self.__size - 6
@property
@ -75,14 +79,19 @@ class Sparkline(object):
def post_char(self):
return self.__post_char
def get(self):
def get(self, overwrite=''):
"""Return the sparkline."""
ret = sparklines(self.percents, minimum=0, maximum=100)[0]
if self.__with_text:
if self.__display_value:
percents_without_none = [x for x in self.percents if x is not None]
if len(percents_without_none) > 0:
ret = '{}{:5.1f}%'.format(ret, percents_without_none[-1])
return nativestr(ret)
ret = '{}{:5.1f}{}'.format(ret,
percents_without_none[-1],
self.__unit_char)
ret = nativestr(ret)
if overwrite and len(overwrite) < len(ret) - 6:
ret = overwrite + ret[len(overwrite):]
return ret
def __str__(self):
"""Return the sparkline."""

View File

@ -42,41 +42,23 @@
<div class="table-cell">{{ percpu.total }}%</div>
</div>
</template>
<div class="table-row">
<div class="table-cell text-left">MEM</div>
<div class="table-row" v-for="(key) in stats_list_after_cpu">
<div class="table-cell text-left">{{ key.toUpperCase() }}</div>
<div class="table-cell">
<div class="progress">
<div
:class="`progress-bar progress-bar-${getDecoration('mem')}`"
:class="`progress-bar progress-bar-${getDecoration(key)}`"
role="progressbar"
:aria-valuenow="mem"
:aria-valuenow="stats[key]"
aria-valuemin="0"
aria-valuemax="100"
:style="`width: ${mem}%;`"
:style="`width: ${stats[key]}%;`"
>
&nbsp;
</div>
</div>
</div>
<div class="table-cell">{{ mem }}%</div>
</div>
<div class="table-row">
<div class="table-cell text-left">SWAP</div>
<div class="table-cell">
<div class="progress">
<div
:class="`progress-bar progress-bar-${getDecoration('swap')}`"
role="progressbar"
:aria-valuenow="swap"
aria-valuemin="0"
aria-valuemax="100"
:style="`width: ${swap}%;`"
>
&nbsp;
</div>
</div>
</div>
<div class="table-cell">{{ swap }}%</div>
<div class="table-cell">{{ stats[key] }}%</div>
</div>
</div>
</section>
@ -106,9 +88,6 @@ export default {
view() {
return this.data.views['quicklook'];
},
mem() {
return this.stats.mem;
},
cpu() {
return this.stats.cpu;
},
@ -121,15 +100,15 @@ export default {
cpu_hz() {
return this.stats.cpu_hz;
},
swap() {
return this.stats.swap;
},
percpus() {
return this.stats.percpu.map(({ cpu_number: number, total }) => ({
number,
total
}));
}
},
stats_list_after_cpu() {
return this.view.list.filter((key) => !key.includes('cpu'));
},
},
methods: {
getDecoration(value) {

View File

@ -2336,9 +2336,9 @@
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"dev": true,
"funding": [
{
@ -7584,9 +7584,9 @@
"dev": true
},
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"dev": true
},
"forwarded": {

File diff suppressed because one or more lines are too long

View File

@ -58,6 +58,14 @@ items_history_list = [
{'name': 'min15', 'description': '15 minutes load'},
]
# Get the number of logical CPU core only once
# the variable is also shared with the QuickLook plugin
try:
nb_log_core = CorePluginModel().update()["log"]
except Exception as e:
logger.warning('Error: Can not retrieve the CPU core number (set it to 1) ({})'.format(e))
nb_log_core = 1
class PluginModel(GlancesPluginModel):
"""Glances load plugin.
@ -74,24 +82,6 @@ class PluginModel(GlancesPluginModel):
# We want to display the stat in the curse interface
self.display_curse = True
# Call CorePluginModel in order to display the core number
try:
self.nb_log_core = CorePluginModel(args=self.args).update()["log"]
except Exception as e:
logger.warning('Error: Can not retrieve the CPU core number (set it to 1) ({})'.format(e))
self.nb_log_core = 1
def _getloadavg(self):
"""Get load average. On both Linux and Windows thanks to PsUtil"""
try:
return psutil.getloadavg()
except (AttributeError, OSError):
pass
try:
return os.getloadavg()
except (AttributeError, OSError):
return None
@GlancesPluginModel._check_decorator
@GlancesPluginModel._log_result_decorator
def update(self):
@ -103,11 +93,16 @@ class PluginModel(GlancesPluginModel):
# Update stats using the standard system lib
# Get the load using the os standard lib
load = self._getloadavg()
load = get_load_average()
if load is None:
stats = self.get_init_value()
else:
stats = {'min1': load[0], 'min5': load[1], 'min15': load[2], 'cpucore': self.nb_log_core}
stats = {
'min1': load[0],
'min5': load[1],
'min15': load[2],
'cpucore': get_nb_log_core()
}
elif self.input_method == 'snmp':
# Update stats using SNMP
@ -122,7 +117,7 @@ class PluginModel(GlancesPluginModel):
for k, v in iteritems(stats):
stats[k] = float(v)
stats['cpucore'] = self.nb_log_core
stats['cpucore'] = get_nb_log_core()
# Update the stats
self.stats = stats
@ -170,9 +165,9 @@ class PluginModel(GlancesPluginModel):
ret.append(self.curse_new_line())
msg = '{:7}'.format('{} min'.format(load_time))
ret.append(self.curse_add_line(msg))
if args.disable_irix and self.nb_log_core != 0:
if args.disable_irix and get_nb_log_core() != 0:
# Enable Irix mode for load (see issue #1554)
load_stat = self.stats['min{}'.format(load_time)] / self.nb_log_core * 100
load_stat = self.stats['min{}'.format(load_time)] / get_nb_log_core() * 100
msg = '{:>5.1f}%'.format(load_stat)
else:
# Default mode for load
@ -181,3 +176,28 @@ class PluginModel(GlancesPluginModel):
ret.append(self.curse_add_line(msg, self.get_views(key='min{}'.format(load_time), option='decoration')))
return ret
def get_nb_log_core():
"""Get the number of logical CPU core."""
return nb_log_core
def get_load_average(percent: bool = False):
"""Get load average. On both Linux and Windows thanks to PsUtil
if percent is True, return the load average in percent
Ex: if you only have one CPU core and the load average is 1.0, then return 100%"""
load_average = None
try:
load_average = psutil.getloadavg()
except (AttributeError, OSError):
try:
load_average = os.getloadavg()
except (AttributeError, OSError):
pass
if load_average and percent:
return tuple([round(i / get_nb_log_core() * 100, 1) for i in load_average])
else:
return load_average

View File

@ -2,7 +2,7 @@
#
# This file is part of Glances.
#
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <nicolas@nicolargo.com>
# SPDX-FileCopyrightText: 2024 Nicolas Hennion <nicolas@nicolargo.com>
#
# SPDX-License-Identifier: LGPL-3.0-only
#
@ -11,6 +11,7 @@
from glances.logger import logger
from glances.cpu_percent import cpu_percent
from glances.plugins.load import get_load_average, get_nb_log_core
from glances.outputs.glances_bars import Bar
from glances.outputs.glances_sparklines import Sparkline
from glances.plugins.plugin.model import GlancesPluginModel
@ -36,6 +37,10 @@ fields_description = {
'description': 'SWAP percent usage',
'unit': 'percent',
},
'load': {
'description': 'LOAD percent usage',
'unit': 'percent',
},
'cpu_name': {
'description': 'CPU name',
},
@ -56,6 +61,7 @@ items_history_list = [
{'name': 'percpu', 'description': 'PERCPU percent usage', 'y_unit': '%'},
{'name': 'mem', 'description': 'MEM percent usage', 'y_unit': '%'},
{'name': 'swap', 'description': 'SWAP percent usage', 'y_unit': '%'},
{'name': 'load', 'description': 'LOAD percent usage', 'y_unit': '%'},
]
@ -65,6 +71,9 @@ class PluginModel(GlancesPluginModel):
'stats' is a dictionary.
"""
AVAILABLE_STATS_LIST = ['cpu', 'mem', 'swap', 'load']
DEFAULT_STATS_LIST = ['cpu', 'mem', 'load']
def __init__(self, args=None, config=None):
"""Init the quicklook plugin."""
super(PluginModel, self).__init__(
@ -75,6 +84,12 @@ class PluginModel(GlancesPluginModel):
# We want to display the stat in the curse interface
self.display_curse = True
# Define the stats list
self.stats_list = self.get_conf_value('list', default=self.DEFAULT_STATS_LIST)
if not set(self.stats_list).issubset(self.AVAILABLE_STATS_LIST):
logger.warning('Quicklook plugin: Invalid stats list: {}'.format(self.stats_list))
self.stats_list = self.AVAILABLE_STATS_LIST
@GlancesPluginModel._check_decorator
@GlancesPluginModel._log_result_decorator
def update(self):
@ -84,11 +99,20 @@ class PluginModel(GlancesPluginModel):
# Grab quicklook stats: CPU, MEM and SWAP
if self.input_method == 'local':
# Get the latest CPU percent value
# Get system information
cpu_info = cpu_percent.get_info()
stats['cpu_name'] = cpu_info['cpu_name']
stats['cpu_hz_current'] = (
self._mhz_to_hz(cpu_info['cpu_hz_current']) if cpu_info['cpu_hz_current'] is not None else None
)
stats['cpu_hz'] = self._mhz_to_hz(cpu_info['cpu_hz']) if cpu_info['cpu_hz'] is not None else None
# Get the CPU percent value (global and per core)
# Stats is shared across all plugins
stats['cpu'] = cpu_percent.get()
stats['percpu'] = cpu_percent.get(percpu=True)
# Use the psutil lib for the memory (virtual and swap)
# Get the virtual and swap memory
stats['mem'] = psutil.virtual_memory().percent
try:
stats['swap'] = psutil.swap_memory().percent
@ -96,13 +120,14 @@ class PluginModel(GlancesPluginModel):
# Correct issue in Illumos OS (see #1767)
stats['swap'] = None
# Get additional information
cpu_info = cpu_percent.get_info()
stats['cpu_name'] = cpu_info['cpu_name']
stats['cpu_hz_current'] = (
self._mhz_to_hz(cpu_info['cpu_hz_current']) if cpu_info['cpu_hz_current'] is not None else None
)
stats['cpu_hz'] = self._mhz_to_hz(cpu_info['cpu_hz']) if cpu_info['cpu_hz'] is not None else None
# Get load
stats['cpucore'] = get_nb_log_core()
try:
# Load average is a tuple (1 min, 5 min, 15 min)
# Process only the 15 min value (index 2)
stats['load'] = get_load_average(percent=True)[2]
except (TypeError, IndexError):
stats['load'] = None
elif self.input_method == 'snmp':
# Not available
@ -118,12 +143,19 @@ class PluginModel(GlancesPluginModel):
# Call the father's method
super(PluginModel, self).update_views()
# Add specifics information
# Alert only
for key in ['cpu', 'mem', 'swap']:
# Alert for CPU, MEM and SWAP
for key in self.stats_list:
if key in self.stats:
self.views[key]['decoration'] = self.get_alert(self.stats[key], header=key)
# Alert for LOAD
self.views['load']['decoration'] = self.get_alert(
self.stats['load'], header='load'
)
# Define the list of stats to display
self.views['list'] = self.stats_list
def msg_curse(self, args=None, max_width=10):
"""Return the list to display in the UI."""
# Init the return message
@ -139,15 +171,19 @@ class PluginModel(GlancesPluginModel):
return ret
# Define the data: Bar (default behavior) or Sparkline
sparkline_tag = False
if self.args.sparkline and self.history_enable() and not self.args.client:
data = Sparkline(max_width)
sparkline_tag = data.available
if not sparkline_tag:
# Fallback to bar if Sparkline module is not installed
data = Bar(max_width, percentage_char=self.get_conf_value('percentage_char', default=['|'])[0])
data = dict()
for key in self.stats_list:
if self.args.sparkline and self.history_enable() and not self.args.client:
data[key] = Sparkline(max_width)
else:
# Fallback to bar if Sparkline module is not installed
data[key] = Bar(max_width,
bar_char=self.get_conf_value('bar_char', default=['|'])[0])
# Build the string message
##########################
# System information
if 'cpu_name' in self.stats and 'cpu_hz_current' in self.stats and 'cpu_hz' in self.stats:
msg_name = self.stats['cpu_name']
if self.stats['cpu_hz_current'] and self.stats['cpu_hz']:
@ -160,36 +196,38 @@ class PluginModel(GlancesPluginModel):
ret.append(self.curse_add_line(msg_name))
ret.append(self.curse_add_line(msg_freq))
ret.append(self.curse_new_line())
for key in ['cpu', 'mem', 'swap']:
# Loop over CPU, MEM and LOAD
for key in self.stats_list:
if key == 'cpu' and args.percpu:
if sparkline_tag:
raw_cpu = self.get_raw_history(item='percpu', nb=data.size)
if type(data[key]).__name__ == 'Sparkline':
raw_cpu = self.get_raw_history(item='percpu', nb=data[key].size)
for cpu_index, cpu in enumerate(self.stats['percpu']):
if sparkline_tag:
if type(data[key]).__name__ == 'Sparkline':
# Sparkline display an history
data.percents = [i[1][cpu_index]['total'] for i in raw_cpu]
data[key].percents = [i[1][cpu_index]['total'] for i in raw_cpu]
# A simple padding in order to align metrics to the right
data.percents += [None] * (data.size - len(data.percents))
data[key].percents += [None] * (data[key].size - len(data[key].percents))
else:
# Bar only the last value
data.percent = cpu['total']
data[key].percent = cpu['total']
if cpu[cpu['key']] < 10:
msg = '{:3}{} '.format(key.upper(), cpu['cpu_number'])
else:
msg = '{:4} '.format(cpu['cpu_number'])
ret.extend(self._msg_create_line(msg, data, key))
ret.extend(self._msg_create_line(msg, data[key], key))
ret.append(self.curse_new_line())
else:
if sparkline_tag:
if type(data[key]).__name__ == 'Sparkline':
# Sparkline display an history
data.percents = [i[1] for i in self.get_raw_history(item=key, nb=data.size)]
data[key].percents = [i[1] for i in self.get_raw_history(item=key, nb=data[key].size)]
# A simple padding in order to align metrics to the right
data.percents += [None] * (data.size - len(data.percents))
data[key].percents += [None] * (data[key].size - len(data[key].percents))
else:
# Bar only the last value
data.percent = self.stats[key]
data[key].percent = self.stats[key]
msg = '{:4} '.format(key.upper())
ret.extend(self._msg_create_line(msg, data, key))
ret.extend(self._msg_create_line(msg, data[key], key))
ret.append(self.curse_new_line())
# Remove the last new line
@ -200,10 +238,14 @@ class PluginModel(GlancesPluginModel):
def _msg_create_line(self, msg, data, key):
"""Create a new line to the Quick view."""
# if key == 'mem' and self.get_alert(self.stats['swap'], header='swap') != 'DEFAULT':
# overwrite = 'SWAP'
# else:
overwrite = ''
return [
self.curse_add_line(msg),
self.curse_add_line(data.pre_char, decoration='BOLD'),
self.curse_add_line(data.get(), self.get_views(key=key, option='decoration')),
self.curse_add_line(data.get(overwrite), self.get_views(key=key, option='decoration')),
self.curse_add_line(data.post_char, decoration='BOLD'),
self.curse_add_line(' '),
]