mirror of
https://github.com/nicolargo/glances.git
synced 2024-11-24 13:23:12 +03:00
Glances 4.0.8
This commit is contained in:
commit
bf3bb6a7e8
15
.github/workflows/build.yml
vendored
15
.github/workflows/build.yml
vendored
@ -123,19 +123,12 @@ jobs:
|
||||
|
||||
- name: Retrieve Repository Docker metadata
|
||||
id: docker_meta
|
||||
uses: crazy-max/ghaction-docker-meta@v5.0.0
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.DEFAULT_DOCKER_IMAGE }}
|
||||
labels: |
|
||||
org.opencontainers.image.url=https://nicolargo.github.io/glances/
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ env.NODE_ENV }}-${{ matrix.os }}-${{ matrix.tag.tag }}
|
||||
restore-keys: ${{ runner.os }}-buildx-${{ env.NODE_ENV }}-${{ matrix.os }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
@ -166,5 +159,7 @@ jobs:
|
||||
platforms: ${{ matrix.os != 'ubuntu' && env.DOCKER_PLATFORMS || env.DOCKER_PLATFORMS_UBUNTU }}
|
||||
target: ${{ matrix.tag.target }}
|
||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
|
||||
# GHA default behaviour overwrites last build cache. Causes alpine and ubuntu cache to overwrite each other.
|
||||
# Use `scope` with the os name to prevent that
|
||||
cache-from: 'type=gha,scope=${{ matrix.os }}'
|
||||
cache-to: 'type=gha,mode=max,scope=${{ matrix.os }}'
|
||||
|
56
NEWS.rst
56
NEWS.rst
@ -48,6 +48,62 @@ Version 4.0.2
|
||||
|
||||
Thanks to RazCrimson for the sensors patch !
|
||||
|
||||
===============
|
||||
Version 4.0.8
|
||||
===============
|
||||
|
||||
* Make CORS option configurable security webui #2812
|
||||
* When Glances is installed via venv, default configuration file is not used documentation packaging #2803
|
||||
* GET /1272f6e9e8f9d6bfd6de.png results in 404 bug webui #2781 by Emporea was closed May 25, 2024
|
||||
* Screen frequently flickers when outputting to local display bug needs test #2490
|
||||
* Retire ujson for being in maintenance mode dependencies enhancement #2791
|
||||
|
||||
===============
|
||||
Version 4.0.7
|
||||
===============
|
||||
|
||||
* cpu_hz_current not available on NetBSD #2792
|
||||
* SensorType change in REST API breaks compatibility in 4.0.4 #2788
|
||||
|
||||
===============
|
||||
Version 4.0.6
|
||||
===============
|
||||
|
||||
* No GPU info on Web View #2796
|
||||
|
||||
===============
|
||||
Version 4.0.5
|
||||
===============
|
||||
|
||||
* SensorType change in REST API breaks compatibility in 4.0.4 #2788
|
||||
* Please make pydantic optional dependency, not required one #2777
|
||||
* Update the Grafana dashboard #2780
|
||||
* 4.0.4 - On Glances startup "ERROR -- Can not init battery class #2776
|
||||
* In codeSpace (with Python 3.8), an error occurs in ./unittest-restful.py #2773
|
||||
|
||||
Use Ruff as default Linter.
|
||||
|
||||
===============
|
||||
Version 4.0.4
|
||||
===============
|
||||
|
||||
Hostfix release for support sensors plugin on python 3.8
|
||||
|
||||
===============
|
||||
Version 4.0.3
|
||||
===============
|
||||
|
||||
Additional fixes for Sensor plugin
|
||||
|
||||
===============
|
||||
Version 4.0.2
|
||||
===============
|
||||
|
||||
* hotfix: plugin(sensors) - race conditions btw fan_speed & temperature… #2766
|
||||
* fix: include requirements.txt and SECURITY.md for pypi dist #2761
|
||||
|
||||
Thanks to RazCrimson for the sensors patch !
|
||||
|
||||
===============
|
||||
Version 4.0.1
|
||||
===============
|
||||
|
@ -86,7 +86,7 @@ Requirements
|
||||
- ``psutil`` (better with latest version)
|
||||
- ``defusedxml`` (in order to monkey patch xmlrpc)
|
||||
- ``packaging`` (for the version comparison)
|
||||
- ``ujson`` (an optimized alternative to the standard json module)
|
||||
- ``orjson`` (an optimized alternative to the standard json module)
|
||||
|
||||
*Note for Python 2 users*
|
||||
|
||||
@ -115,7 +115,6 @@ Optional dependencies:
|
||||
- ``podman`` (for the Containers Podman monitoring support)
|
||||
- ``potsdb`` (for the OpenTSDB export module)
|
||||
- ``prometheus_client`` (for the Prometheus export module)
|
||||
- ``py-cpuinfo`` (for the Quicklook CPU info module)
|
||||
- ``pygal`` (for the graph export module)
|
||||
- ``pymdstat`` (for RAID support) [Linux-only]
|
||||
- ``pymongo`` (for the MongoDB export module)
|
||||
|
@ -23,12 +23,16 @@ history_size=1200
|
||||
##############################################################################
|
||||
|
||||
[outputs]
|
||||
# Options for all UIs
|
||||
#--------------------
|
||||
# Separator in the Curses and WebUI interface (between top and others plugins)
|
||||
separator=True
|
||||
# Set the the Curses and WebUI interface left menu plugin list (comma-separated)
|
||||
#left_menu=network,wifi,connections,ports,diskio,fs,irq,folders,raid,smart,sensors,now
|
||||
# Limit the number of processes to display (in the WebUI)
|
||||
max_processes_display=25
|
||||
# Options for WebUI
|
||||
#------------------
|
||||
# Set URL prefix for the WebUI and the API
|
||||
# Example: url_prefix=/glances/ => http://localhost/glances/
|
||||
# Note: The final / is mandatory
|
||||
@ -41,9 +45,22 @@ max_processes_display=25
|
||||
# then configure this folder with the webui_root_path key
|
||||
# Default is folder where glances_restfull_api.py is hosted
|
||||
#webui_root_path=
|
||||
# CORS options
|
||||
# Comma separated list of origins that should be permitted to make cross-origin requests.
|
||||
# Default is *
|
||||
#cors_origins=*
|
||||
# Indicate that cookies should be supported for cross-origin requests.
|
||||
# Default is True
|
||||
#cors_credentials=True
|
||||
# Comma separated list of HTTP methods that should be allowed for cross-origin requests.
|
||||
# Default is *
|
||||
#cors_methods=*
|
||||
# Comma separated list of HTTP request headers that should be supported for cross-origin requests.
|
||||
# Default is *
|
||||
#cors_headers=*
|
||||
|
||||
##############################################################################
|
||||
# plugins
|
||||
# Plugins
|
||||
##############################################################################
|
||||
|
||||
[quicklook]
|
||||
@ -199,6 +216,10 @@ tx_critical=90
|
||||
hide=docker.*,lo
|
||||
# Define the list of wireless network interfaces to be show (comma-separated)
|
||||
#show=docker.*
|
||||
# Automatically hide interface not up (default is False)
|
||||
#hide_no_up=True
|
||||
# Automatically hide interface with no IP address (default is False)
|
||||
#hide_no_ip=True
|
||||
# It is possible to overwrite the bitrate thresholds per interface
|
||||
# WLAN 0 Default limits (in bits per second aka bps) for interface bitrate
|
||||
#wlan0_rx_careful=4000000
|
||||
@ -765,13 +786,13 @@ refresh=3
|
||||
countmax=20
|
||||
|
||||
[amp_conntrack]
|
||||
# Use comma separated for multiple commands (no space around the comma)
|
||||
# Use && separator for multiple commands
|
||||
# If the regex key is not defined, the AMP will be executed every refresh second
|
||||
# and the process count will not be displayed (countmin and countmax will be ignore)
|
||||
enable=false
|
||||
refresh=30
|
||||
one_line=false
|
||||
command=sysctl net.netfilter.nf_conntrack_count;sysctl net.netfilter.nf_conntrack_max
|
||||
command=sysctl net.netfilter.nf_conntrack_count && sysctl net.netfilter.nf_conntrack_max
|
||||
|
||||
[amp_nginx]
|
||||
# Use the NGinx AMP
|
||||
|
@ -1,5 +1,5 @@
|
||||
orjson
|
||||
reuse
|
||||
setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
|
||||
sphinx
|
||||
sphinx_rtd_theme
|
||||
ujson
|
||||
|
@ -23,12 +23,16 @@ history_size=1200
|
||||
##############################################################################
|
||||
|
||||
[outputs]
|
||||
# Options for all UIs
|
||||
#--------------------
|
||||
# Separator in the Curses and WebUI interface (between top and others plugins)
|
||||
separator=True
|
||||
# Set the the Curses and WebUI interface left menu plugin list (comma-separated)
|
||||
#left_menu=network,wifi,connections,ports,diskio,fs,irq,folders,raid,smart,sensors,now
|
||||
# Limit the number of processes to display (in the WebUI)
|
||||
max_processes_display=25
|
||||
# Options for WebUI
|
||||
#------------------
|
||||
# Set URL prefix for the WebUI and the API
|
||||
# Example: url_prefix=/glances/ => http://localhost/glances/
|
||||
# Note: The final / is mandatory
|
||||
@ -41,6 +45,19 @@ max_processes_display=25
|
||||
# then configure this folder with the webui_root_path key
|
||||
# Default is folder where glances_restfull_api.py is hosted
|
||||
#webui_root_path=
|
||||
# CORS options
|
||||
# Comma separated list of origins that should be permitted to make cross-origin requests.
|
||||
# Default is *
|
||||
#cors_origins=*
|
||||
# Indicate that cookies should be supported for cross-origin requests.
|
||||
# Default is True
|
||||
#cors_credentials=True
|
||||
# Comma separated list of HTTP methods that should be allowed for cross-origin requests.
|
||||
# Default is *
|
||||
#cors_methods=*
|
||||
# Comma separated list of HTTP request headers that should be supported for cross-origin requests.
|
||||
# Default is *
|
||||
#cors_headers=*
|
||||
|
||||
##############################################################################
|
||||
# plugins
|
||||
@ -199,6 +216,10 @@ tx_critical=90
|
||||
#hide=docker.*,lo
|
||||
# Define the list of wireless network interfaces to be show (comma-separated)
|
||||
#show=docker.*
|
||||
# Automatically hide interface not up (default is False)
|
||||
hide_no_up=True
|
||||
# Automatically hide interface with no IP address (default is False)
|
||||
hide_no_ip=True
|
||||
# It is possible to overwrite the bitrate thresholds per interface
|
||||
# WLAN 0 Default limits (in bits per second aka bps) for interface bitrate
|
||||
#wlan0_rx_careful=4000000
|
||||
@ -765,13 +786,13 @@ refresh=3
|
||||
countmax=20
|
||||
|
||||
[amp_conntrack]
|
||||
# Use comma separated for multiple commands (no space around the comma)
|
||||
# Use && separator for multiple commands
|
||||
# If the regex key is not defined, the AMP will be executed every refresh second
|
||||
# and the process count will not be displayed (countmin and countmax will be ignore)
|
||||
enable=false
|
||||
refresh=30
|
||||
one_line=false
|
||||
command=sysctl net.netfilter.nf_conntrack_count;sysctl net.netfilter.nf_conntrack_max
|
||||
command=sysctl net.netfilter.nf_conntrack_count && sysctl net.netfilter.nf_conntrack_max
|
||||
|
||||
[amp_nginx]
|
||||
# Use the NGinx AMP
|
||||
|
@ -1,9 +1,8 @@
|
||||
# install with base requirements file
|
||||
-r requirements.txt
|
||||
|
||||
docker>=6.1.1; python_version >= "3.7"
|
||||
packaging; python_version >= "3.7"
|
||||
podman; python_version >= "3.6"
|
||||
docker>=6.1.1
|
||||
podman
|
||||
python-dateutil
|
||||
requests
|
||||
six
|
||||
|
@ -61,9 +61,11 @@ For example:
|
||||
enable=false
|
||||
refresh=30
|
||||
one_line=false
|
||||
command=sysctl net.netfilter.nf_conntrack_count;sysctl net.netfilter.nf_conntrack_max
|
||||
command=sysctl net.netfilter.nf_conntrack_count && sysctl net.netfilter.nf_conntrack_max
|
||||
|
||||
For security reason, pipe is not directly allowed in a AMP command but you create a sheel
|
||||
Note: for multiple command, please use the '&&'' separator.
|
||||
|
||||
For security reason, pipe is not directly allowed in a AMP command but you create a shell
|
||||
script with your command:
|
||||
|
||||
.. code-block:: ini
|
||||
|
@ -17,6 +17,8 @@ In this case thresholds values are define in bps.
|
||||
Additionally, you can define:
|
||||
|
||||
- a list of network interfaces to hide
|
||||
- automatically hide interfaces not up
|
||||
- automatically hide interfaces without IP address
|
||||
- per-interface limit values
|
||||
- aliases for interface name
|
||||
|
||||
@ -41,6 +43,10 @@ virtual docker interface (docker0, docker1, ...):
|
||||
hide=docker.*,lo
|
||||
# Define the list of network interfaces to show (comma-separated regexp)
|
||||
#show=eth0,eth1
|
||||
# Automatically hide interface not up (default is False)
|
||||
hide_no_up=True
|
||||
# Automatically hide interface with no IP address (default is False)
|
||||
hide_no_ip=True
|
||||
# WLAN 0 alias
|
||||
wlan0_alias=Wireless IF
|
||||
# It is possible to overwrite the bitrate thresholds per interface
|
||||
|
226
docs/api.rst
226
docs/api.rst
@ -141,7 +141,7 @@ Get plugin stats::
|
||||
"refresh": 3.0,
|
||||
"regex": True,
|
||||
"result": None,
|
||||
"timer": 0.17942380905151367},
|
||||
"timer": 0.24439311027526855},
|
||||
{"count": 0,
|
||||
"countmax": 20.0,
|
||||
"countmin": None,
|
||||
@ -150,7 +150,7 @@ Get plugin stats::
|
||||
"refresh": 3.0,
|
||||
"regex": True,
|
||||
"result": None,
|
||||
"timer": 0.17932724952697754}]
|
||||
"timer": 0.2443389892578125}]
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
@ -178,7 +178,7 @@ Get a specific item when field matches the given value::
|
||||
"refresh": 3.0,
|
||||
"regex": True,
|
||||
"result": None,
|
||||
"timer": 0.17942380905151367}]}
|
||||
"timer": 0.24439311027526855}]}
|
||||
|
||||
GET cloud
|
||||
---------
|
||||
@ -219,7 +219,21 @@ GET containers
|
||||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/containers
|
||||
[]
|
||||
[{"command": "/bin/sh -c /venv/bin/python3 -m glances $GLANCES_OPT",
|
||||
"cpu": {"total": 0.0},
|
||||
"cpu_percent": 0.0,
|
||||
"created": "2024-05-25T13:52:22.535373707Z",
|
||||
"engine": "docker",
|
||||
"id": "bb99d31288db8904ed4cd43db8255a926830936189bc180d77c3459cbaa7f490",
|
||||
"image": ["nicolargo/glances:latest"],
|
||||
"io": {},
|
||||
"key": "name",
|
||||
"memory": {},
|
||||
"memory_usage": None,
|
||||
"name": "wizardly_nightingale",
|
||||
"network": {},
|
||||
"status": "running",
|
||||
"uptime": "14 mins"}]
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
@ -240,6 +254,31 @@ Fields descriptions:
|
||||
* **pod_name**: Pod name (only with Podman) (unit is *None*)
|
||||
* **pod_id**: Pod ID (only with Podman) (unit is *None*)
|
||||
|
||||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/4/containers/name
|
||||
{"name": ["wizardly_nightingale"]}
|
||||
|
||||
Get a specific item when field matches the given value::
|
||||
|
||||
# curl http://localhost:61208/api/4/containers/name/wizardly_nightingale
|
||||
{"wizardly_nightingale": [{"command": "/bin/sh -c /venv/bin/python3 -m glances "
|
||||
"$GLANCES_OPT",
|
||||
"cpu": {"total": 0.0},
|
||||
"cpu_percent": 0.0,
|
||||
"created": "2024-05-25T13:52:22.535373707Z",
|
||||
"engine": "docker",
|
||||
"id": "bb99d31288db8904ed4cd43db8255a926830936189bc180d77c3459cbaa7f490",
|
||||
"image": ["nicolargo/glances:latest"],
|
||||
"io": {},
|
||||
"key": "name",
|
||||
"memory": {},
|
||||
"memory_usage": None,
|
||||
"name": "wizardly_nightingale",
|
||||
"network": {},
|
||||
"status": "running",
|
||||
"uptime": "14 mins"}]}
|
||||
|
||||
GET core
|
||||
--------
|
||||
|
||||
@ -265,18 +304,18 @@ Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/cpu
|
||||
{"cpucore": 16,
|
||||
"ctx_switches": 247960513,
|
||||
"ctx_switches": 7772781,
|
||||
"guest": 0.0,
|
||||
"idle": 0.0,
|
||||
"interrupts": 235154276,
|
||||
"idle": 3.0,
|
||||
"interrupts": 6643340,
|
||||
"iowait": 0.0,
|
||||
"irq": 0.0,
|
||||
"nice": 0.0,
|
||||
"soft_interrupts": 79848589,
|
||||
"soft_interrupts": 1761276,
|
||||
"steal": 0.0,
|
||||
"syscalls": 0,
|
||||
"system": 0.0,
|
||||
"total": 0.0,
|
||||
"total": 16.7,
|
||||
"user": 1.0}
|
||||
|
||||
Fields descriptions:
|
||||
@ -310,7 +349,7 @@ Fields descriptions:
|
||||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/4/cpu/total
|
||||
{"total": 0.0}
|
||||
{"total": 16.7}
|
||||
|
||||
GET diskio
|
||||
----------
|
||||
@ -320,14 +359,14 @@ Get plugin stats::
|
||||
# curl http://localhost:61208/api/4/diskio
|
||||
[{"disk_name": "nvme0n1",
|
||||
"key": "disk_name",
|
||||
"read_bytes": 4854106624,
|
||||
"read_count": 207109,
|
||||
"write_bytes": 15446680576,
|
||||
"write_count": 891078},
|
||||
"read_bytes": 3983976960,
|
||||
"read_count": 115648,
|
||||
"write_bytes": 3073111040,
|
||||
"write_count": 91409},
|
||||
{"disk_name": "nvme0n1p1",
|
||||
"key": "disk_name",
|
||||
"read_bytes": 7484416,
|
||||
"read_count": 592,
|
||||
"read_bytes": 7476224,
|
||||
"read_count": 576,
|
||||
"write_bytes": 1024,
|
||||
"write_count": 2}]
|
||||
|
||||
@ -363,10 +402,10 @@ Get a specific item when field matches the given value::
|
||||
# curl http://localhost:61208/api/4/diskio/disk_name/nvme0n1
|
||||
{"nvme0n1": [{"disk_name": "nvme0n1",
|
||||
"key": "disk_name",
|
||||
"read_bytes": 4854106624,
|
||||
"read_count": 207109,
|
||||
"write_bytes": 15446680576,
|
||||
"write_count": 891078}]}
|
||||
"read_bytes": 3983976960,
|
||||
"read_count": 115648,
|
||||
"write_bytes": 3073111040,
|
||||
"write_count": 91409}]}
|
||||
|
||||
GET folders
|
||||
-----------
|
||||
@ -393,13 +432,13 @@ Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/fs
|
||||
[{"device_name": "/dev/mapper/ubuntu--vg-ubuntu--lv",
|
||||
"free": 904231424000,
|
||||
"free": 902284546048,
|
||||
"fs_type": "ext4",
|
||||
"key": "mnt_point",
|
||||
"mnt_point": "/",
|
||||
"percent": 5.1,
|
||||
"percent": 5.3,
|
||||
"size": 1003736440832,
|
||||
"used": 48442511360}]
|
||||
"used": 50389389312}]
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
@ -420,13 +459,13 @@ Get a specific item when field matches the given value::
|
||||
|
||||
# curl http://localhost:61208/api/4/fs/mnt_point//
|
||||
{"/": [{"device_name": "/dev/mapper/ubuntu--vg-ubuntu--lv",
|
||||
"free": 904231424000,
|
||||
"free": 902284546048,
|
||||
"fs_type": "ext4",
|
||||
"key": "mnt_point",
|
||||
"mnt_point": "/",
|
||||
"percent": 5.1,
|
||||
"percent": 5.3,
|
||||
"size": 1003736440832,
|
||||
"used": 48442511360}]}
|
||||
"used": 50389389312}]}
|
||||
|
||||
GET gpu
|
||||
-------
|
||||
@ -500,9 +539,9 @@ Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/load
|
||||
{"cpucore": 16,
|
||||
"min1": 0.2802734375,
|
||||
"min15": 0.6240234375,
|
||||
"min5": 0.61376953125}
|
||||
"min1": 0.560546875,
|
||||
"min15": 0.54833984375,
|
||||
"min5": 0.70166015625}
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
@ -514,7 +553,7 @@ Fields descriptions:
|
||||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/4/load/min1
|
||||
{"min1": 0.2802734375}
|
||||
{"min1": 0.560546875}
|
||||
|
||||
GET mem
|
||||
-------
|
||||
@ -522,16 +561,16 @@ GET mem
|
||||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/mem
|
||||
{"active": 8875126784,
|
||||
"available": 7975804928,
|
||||
"buffers": 463708160,
|
||||
"cached": 7862255616,
|
||||
"free": 7975804928,
|
||||
"inactive": 4694634496,
|
||||
"percent": 51.4,
|
||||
"shared": 849006592,
|
||||
{"active": 5540470784,
|
||||
"available": 11137699840,
|
||||
"buffers": 226918400,
|
||||
"cached": 6333566976,
|
||||
"free": 11137699840,
|
||||
"inactive": 3872489472,
|
||||
"percent": 32.2,
|
||||
"shared": 656637952,
|
||||
"total": 16422486016,
|
||||
"used": 8446681088}
|
||||
"used": 5284786176}
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
@ -558,13 +597,13 @@ GET memswap
|
||||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/memswap
|
||||
{"free": 4293914624,
|
||||
{"free": 4294963200,
|
||||
"percent": 0.0,
|
||||
"sin": 0,
|
||||
"sout": 114688,
|
||||
"sout": 0,
|
||||
"time_since_update": 1,
|
||||
"total": 4294963200,
|
||||
"used": 1048576}
|
||||
"used": 0}
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
@ -589,15 +628,26 @@ Get plugin stats::
|
||||
# curl http://localhost:61208/api/4/network
|
||||
[{"alias": None,
|
||||
"bytes_all": 0,
|
||||
"bytes_all_gauge": 1608088786,
|
||||
"bytes_all_gauge": 422462144,
|
||||
"bytes_recv": 0,
|
||||
"bytes_recv_gauge": 1294928139,
|
||||
"bytes_recv_gauge": 413272561,
|
||||
"bytes_sent": 0,
|
||||
"bytes_sent_gauge": 313160647,
|
||||
"bytes_sent_gauge": 9189583,
|
||||
"interface_name": "wlp0s20f3",
|
||||
"key": "interface_name",
|
||||
"speed": 0,
|
||||
"time_since_update": 0.18457698822021484}]
|
||||
"time_since_update": 0.24814295768737793},
|
||||
{"alias": None,
|
||||
"bytes_all": 0,
|
||||
"bytes_all_gauge": 18987,
|
||||
"bytes_recv": 0,
|
||||
"bytes_recv_gauge": 528,
|
||||
"bytes_sent": 0,
|
||||
"bytes_sent_gauge": 18459,
|
||||
"interface_name": "vethfc47299",
|
||||
"key": "interface_name",
|
||||
"speed": 10485760000,
|
||||
"time_since_update": 0.24814295768737793}]
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
@ -619,22 +669,22 @@ Fields descriptions:
|
||||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/4/network/interface_name
|
||||
{"interface_name": ["wlp0s20f3"]}
|
||||
{"interface_name": ["wlp0s20f3", "vethfc47299"]}
|
||||
|
||||
Get a specific item when field matches the given value::
|
||||
|
||||
# curl http://localhost:61208/api/4/network/interface_name/wlp0s20f3
|
||||
{"wlp0s20f3": [{"alias": None,
|
||||
"bytes_all": 0,
|
||||
"bytes_all_gauge": 1608088786,
|
||||
"bytes_all_gauge": 422462144,
|
||||
"bytes_recv": 0,
|
||||
"bytes_recv_gauge": 1294928139,
|
||||
"bytes_recv_gauge": 413272561,
|
||||
"bytes_sent": 0,
|
||||
"bytes_sent_gauge": 313160647,
|
||||
"bytes_sent_gauge": 9189583,
|
||||
"interface_name": "wlp0s20f3",
|
||||
"key": "interface_name",
|
||||
"speed": 0,
|
||||
"time_since_update": 0.18457698822021484}]}
|
||||
"time_since_update": 0.24814295768737793}]}
|
||||
|
||||
GET now
|
||||
-------
|
||||
@ -642,7 +692,7 @@ GET now
|
||||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/now
|
||||
{"custom": "2024-05-25 16:10:02 CEST", "iso": "2024-05-25T16:10:02+02:00"}
|
||||
{"custom": "2024-06-08 10:22:29 CEST", "iso": "2024-06-08T10:22:29+02:00"}
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
@ -652,7 +702,7 @@ Fields descriptions:
|
||||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/4/now/iso
|
||||
{"iso": "2024-05-25T16:10:02+02:00"}
|
||||
{"iso": "2024-06-08T10:22:29+02:00"}
|
||||
|
||||
GET percpu
|
||||
----------
|
||||
@ -719,7 +769,7 @@ Get plugin stats::
|
||||
"port": 0,
|
||||
"refresh": 30,
|
||||
"rtt_warning": None,
|
||||
"status": 0.005044,
|
||||
"status": 0.005593,
|
||||
"timeout": 3}]
|
||||
|
||||
Fields descriptions:
|
||||
@ -747,7 +797,7 @@ Get a specific item when field matches the given value::
|
||||
"port": 0,
|
||||
"refresh": 30,
|
||||
"rtt_warning": None,
|
||||
"status": 0.005044,
|
||||
"status": 0.005593,
|
||||
"timeout": 3}]}
|
||||
|
||||
GET processcount
|
||||
@ -756,7 +806,7 @@ GET processcount
|
||||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/processcount
|
||||
{"pid_max": 0, "running": 0, "sleeping": 292, "thread": 1710, "total": 432}
|
||||
{"pid_max": 0, "running": 0, "sleeping": 279, "thread": 1568, "total": 410}
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
@ -769,7 +819,7 @@ Fields descriptions:
|
||||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/4/processcount/total
|
||||
{"total": 432}
|
||||
{"total": 410}
|
||||
|
||||
GET processlist
|
||||
---------------
|
||||
@ -809,14 +859,14 @@ GET quicklook
|
||||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/quicklook
|
||||
{"cpu": 0.0,
|
||||
{"cpu": 16.7,
|
||||
"cpu_hz": 4475000000.0,
|
||||
"cpu_hz_current": 1610092062.5,
|
||||
"cpu_hz_current": 1230624312.5,
|
||||
"cpu_log_core": 16,
|
||||
"cpu_name": "13th Gen Intel(R) Core(TM) i7-13620H",
|
||||
"cpu_phys_core": 10,
|
||||
"load": 3.9,
|
||||
"mem": 51.5,
|
||||
"load": 3.4,
|
||||
"mem": 32.1,
|
||||
"percpu": [{"cpu_number": 0,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
@ -924,7 +974,7 @@ Get plugin stats::
|
||||
{"cpu_number": 8,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 0.0,
|
||||
"idle": 1.0,
|
||||
"iowait": 0.0,
|
||||
"irq": 0.0,
|
||||
"key": "cpu_number",
|
||||
@ -932,7 +982,7 @@ Get plugin stats::
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"system": 0.0,
|
||||
"total": 100.0,
|
||||
"total": 99.0,
|
||||
"user": 0.0},
|
||||
{"cpu_number": 9,
|
||||
"guest": 0.0,
|
||||
@ -1063,14 +1113,14 @@ Get plugin stats::
|
||||
"label": "Ambient",
|
||||
"type": "temperature_core",
|
||||
"unit": "C",
|
||||
"value": 38,
|
||||
"value": 36,
|
||||
"warning": 0},
|
||||
{"critical": None,
|
||||
"key": "label",
|
||||
"label": "Ambient 3",
|
||||
"type": "temperature_core",
|
||||
"unit": "C",
|
||||
"value": 35,
|
||||
"value": 29,
|
||||
"warning": 0}]
|
||||
|
||||
Fields descriptions:
|
||||
@ -1131,7 +1181,7 @@ Get a specific item when field matches the given value::
|
||||
"label": "Ambient",
|
||||
"type": "temperature_core",
|
||||
"unit": "C",
|
||||
"value": 38,
|
||||
"value": 36,
|
||||
"warning": 0}]}
|
||||
|
||||
GET smart
|
||||
@ -1175,7 +1225,7 @@ GET uptime
|
||||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/uptime
|
||||
"11 days, 17:02:42"
|
||||
"0:14:44"
|
||||
|
||||
GET version
|
||||
-----------
|
||||
@ -1183,7 +1233,7 @@ GET version
|
||||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/version
|
||||
"4.0.7"
|
||||
"4.0.8"
|
||||
|
||||
GET wifi
|
||||
--------
|
||||
@ -1192,8 +1242,8 @@ Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/4/wifi
|
||||
[{"key": "ssid",
|
||||
"quality_level": -62.0,
|
||||
"quality_link": 48.0,
|
||||
"quality_level": -66.0,
|
||||
"quality_link": 44.0,
|
||||
"ssid": "wlp0s20f3"}]
|
||||
|
||||
Get a specific field::
|
||||
@ -1205,8 +1255,8 @@ Get a specific item when field matches the given value::
|
||||
|
||||
# curl http://localhost:61208/api/4/wifi/ssid/wlp0s20f3
|
||||
{"wlp0s20f3": [{"key": "ssid",
|
||||
"quality_level": -62.0,
|
||||
"quality_link": 48.0,
|
||||
"quality_level": -66.0,
|
||||
"quality_link": 44.0,
|
||||
"ssid": "wlp0s20f3"}]}
|
||||
|
||||
GET all stats
|
||||
@ -1251,34 +1301,34 @@ GET stats history
|
||||
History of a plugin::
|
||||
|
||||
# curl http://localhost:61208/api/4/cpu/history
|
||||
{"system": [["2024-05-25T16:10:03.933630", 0.0],
|
||||
["2024-05-25T16:10:04.963537", 0.0],
|
||||
["2024-05-25T16:10:06.018120", 0.0]],
|
||||
"user": [["2024-05-25T16:10:03.933619", 1.0],
|
||||
["2024-05-25T16:10:04.963532", 1.0],
|
||||
["2024-05-25T16:10:06.018110", 1.0]]}
|
||||
{"system": [["2024-06-08T10:22:30.631056", 0.0],
|
||||
["2024-06-08T10:22:31.667772", 1.0],
|
||||
["2024-06-08T10:22:32.723737", 1.0]],
|
||||
"user": [["2024-06-08T10:22:30.631046", 1.0],
|
||||
["2024-06-08T10:22:31.667765", 1.0],
|
||||
["2024-06-08T10:22:32.723728", 1.0]]}
|
||||
|
||||
Limit history to last 2 values::
|
||||
|
||||
# curl http://localhost:61208/api/4/cpu/history/2
|
||||
{"system": [["2024-05-25T16:10:04.963537", 0.0],
|
||||
["2024-05-25T16:10:06.018120", 0.0]],
|
||||
"user": [["2024-05-25T16:10:04.963532", 1.0],
|
||||
["2024-05-25T16:10:06.018110", 1.0]]}
|
||||
{"system": [["2024-06-08T10:22:31.667772", 1.0],
|
||||
["2024-06-08T10:22:32.723737", 1.0]],
|
||||
"user": [["2024-06-08T10:22:31.667765", 1.0],
|
||||
["2024-06-08T10:22:32.723728", 1.0]]}
|
||||
|
||||
History for a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/4/cpu/system/history
|
||||
{"system": [["2024-05-25T16:10:02.825532", 0.0],
|
||||
["2024-05-25T16:10:03.933630", 0.0],
|
||||
["2024-05-25T16:10:04.963537", 0.0],
|
||||
["2024-05-25T16:10:06.018120", 0.0]]}
|
||||
{"system": [["2024-06-08T10:22:29.515717", 0.0],
|
||||
["2024-06-08T10:22:30.631056", 0.0],
|
||||
["2024-06-08T10:22:31.667772", 1.0],
|
||||
["2024-06-08T10:22:32.723737", 1.0]]}
|
||||
|
||||
Limit history for a specific field to last 2 values::
|
||||
|
||||
# curl http://localhost:61208/api/4/cpu/system/history
|
||||
{"system": [["2024-05-25T16:10:04.963537", 0.0],
|
||||
["2024-05-25T16:10:06.018120", 0.0]]}
|
||||
{"system": [["2024-06-08T10:22:31.667772", 1.0],
|
||||
["2024-06-08T10:22:32.723737", 1.0]]}
|
||||
|
||||
GET limits (used for thresholds)
|
||||
--------------------------------
|
||||
|
@ -21,6 +21,7 @@ You can place your ``glances.conf`` file in the following locations:
|
||||
``*BSD`` ~/.config/glances/, /usr/local/etc/glances/, /usr/share/docs/glances/
|
||||
``macOS`` ~/.config/glances/, ~/Library/Application Support/glances/, /usr/local/etc/glances/, /usr/share/docs/glances/
|
||||
``Windows`` %APPDATA%\\glances\\glances.conf
|
||||
``All`` + <venv_root_folder>/share/doc/glances/
|
||||
==================== =============================================================
|
||||
|
||||
- On Windows XP, ``%APPDATA%`` is: ``C:\Documents and Settings\<USERNAME>\Application Data``.
|
||||
@ -59,17 +60,41 @@ than a second one concerning the user interface:
|
||||
.. code-block:: ini
|
||||
|
||||
[outputs]
|
||||
# Options for all UIs
|
||||
#--------------------
|
||||
# Separator in the Curses and WebUI interface (between top and others plugins)
|
||||
separator=True
|
||||
# Set the the Curses and WebUI interface left menu plugin list (comma-separated)
|
||||
#left_menu=network,wifi,connections,ports,diskio,fs,irq,folders,raid,smart,sensors,now
|
||||
# Limit the number of processes to display (for the WebUI)
|
||||
# Limit the number of processes to display (in the WebUI)
|
||||
max_processes_display=25
|
||||
# Set the URL prefix (for the WebUI and the API)
|
||||
# Options for WebUI
|
||||
#------------------
|
||||
# Set URL prefix for the WebUI and the API
|
||||
# Example: url_prefix=/glances/ => http://localhost/glances/
|
||||
# The final / is mandatory
|
||||
# Note: The final / is mandatory
|
||||
# Default is no prefix (/)
|
||||
#url_prefix=/glances/
|
||||
# Set root path for WebUI statics files
|
||||
# Why ? On Debian system, WebUI statics files are not provided.
|
||||
# You can download it in a specific folder
|
||||
# thanks to https://github.com/nicolargo/glances/issues/2021
|
||||
# then configure this folder with the webui_root_path key
|
||||
# Default is folder where glances_restfull_api.py is hosted
|
||||
#webui_root_path=
|
||||
# CORS options
|
||||
# Comma separated list of origins that should be permitted to make cross-origin requests.
|
||||
# Default is *
|
||||
#cors_origins=*
|
||||
# Indicate that cookies should be supported for cross-origin requests.
|
||||
# Default is True
|
||||
#cors_credentials=True
|
||||
# Comma separated list of HTTP methods that should be allowed for cross-origin requests.
|
||||
# Default is *
|
||||
#cors_methods=*
|
||||
# Comma separated list of HTTP request headers that should be supported for cross-origin requests.
|
||||
# Default is *
|
||||
#cors_headers=*
|
||||
|
||||
Each plugin, export module, and application monitoring process (AMP) can
|
||||
have a section. Below is an example for the CPU plugin:
|
||||
|
@ -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" "May 25, 2024" "4.0.7" "Glances"
|
||||
.TH "GLANCES" "1" "Jun 08, 2024" "4.0.8" "Glances"
|
||||
.SH NAME
|
||||
glances \- An eye on your system
|
||||
.SH SYNOPSIS
|
||||
@ -585,6 +585,15 @@ T} T{
|
||||
%APPDATA%\eglances\eglances.conf
|
||||
T}
|
||||
_
|
||||
T{
|
||||
\fBAll\fP
|
||||
T} T{
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
<venv_root_folder>/share/doc/glances/
|
||||
.UNINDENT
|
||||
T}
|
||||
_
|
||||
.TE
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
@ -632,17 +641,41 @@ than a second one concerning the user interface:
|
||||
.nf
|
||||
.ft C
|
||||
[outputs]
|
||||
# Options for all UIs
|
||||
#\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
|
||||
# Separator in the Curses and WebUI interface (between top and others plugins)
|
||||
separator=True
|
||||
# Set the the Curses and WebUI interface left menu plugin list (comma\-separated)
|
||||
#left_menu=network,wifi,connections,ports,diskio,fs,irq,folders,raid,smart,sensors,now
|
||||
# Limit the number of processes to display (for the WebUI)
|
||||
# Limit the number of processes to display (in the WebUI)
|
||||
max_processes_display=25
|
||||
# Set the URL prefix (for the WebUI and the API)
|
||||
# Options for WebUI
|
||||
#\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
|
||||
# Set URL prefix for the WebUI and the API
|
||||
# Example: url_prefix=/glances/ => http://localhost/glances/
|
||||
# The final / is mandatory
|
||||
# Note: The final / is mandatory
|
||||
# Default is no prefix (/)
|
||||
#url_prefix=/glances/
|
||||
# Set root path for WebUI statics files
|
||||
# Why ? On Debian system, WebUI statics files are not provided.
|
||||
# You can download it in a specific folder
|
||||
# thanks to https://github.com/nicolargo/glances/issues/2021
|
||||
# then configure this folder with the webui_root_path key
|
||||
# Default is folder where glances_restfull_api.py is hosted
|
||||
#webui_root_path=
|
||||
# CORS options
|
||||
# Comma separated list of origins that should be permitted to make cross\-origin requests.
|
||||
# Default is *
|
||||
#cors_origins=*
|
||||
# Indicate that cookies should be supported for cross\-origin requests.
|
||||
# Default is True
|
||||
#cors_credentials=True
|
||||
# Comma separated list of HTTP methods that should be allowed for cross\-origin requests.
|
||||
# Default is *
|
||||
#cors_methods=*
|
||||
# Comma separated list of HTTP request headers that should be supported for cross\-origin requests.
|
||||
# Default is *
|
||||
#cors_headers=*
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
|
@ -19,7 +19,7 @@ import tracemalloc
|
||||
# Global name
|
||||
# Version should start and end with a numerical char
|
||||
# See https://packaging.python.org/specifications/core-metadata/#version
|
||||
__version__ = '4.0.7'
|
||||
__version__ = '4.0.8'
|
||||
__apiversion__ = '4'
|
||||
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
|
||||
__license__ = 'LGPLv3'
|
||||
|
@ -24,11 +24,9 @@ one_line=false
|
||||
command=foo status
|
||||
"""
|
||||
|
||||
from subprocess import STDOUT, CalledProcessError, check_output
|
||||
|
||||
from glances.amps.amp import GlancesAmp
|
||||
from glances.globals import to_ascii, u
|
||||
from glances.logger import logger
|
||||
from glances.secure import secure_popen
|
||||
|
||||
|
||||
class Amp(GlancesAmp):
|
||||
@ -68,10 +66,7 @@ class Amp(GlancesAmp):
|
||||
# Run command(s)
|
||||
# Comma separated commands can be executed
|
||||
try:
|
||||
msg = ''
|
||||
for cmd in res.split(';'):
|
||||
msg += u(check_output(cmd.split(), stderr=STDOUT))
|
||||
self.set_result(to_ascii(msg.rstrip()))
|
||||
except CalledProcessError as e:
|
||||
self.set_result(secure_popen(res).rstrip())
|
||||
except Exception as e:
|
||||
self.set_result(e.output)
|
||||
return self.result()
|
||||
|
@ -33,11 +33,10 @@ one_line=true
|
||||
service_cmd=/usr/bin/service --status-all
|
||||
"""
|
||||
|
||||
from subprocess import STDOUT, check_output
|
||||
|
||||
from glances.amps.amp import GlancesAmp
|
||||
from glances.globals import iteritems
|
||||
from glances.logger import logger
|
||||
from glances.secure import secure_popen
|
||||
|
||||
|
||||
class Amp(GlancesAmp):
|
||||
@ -58,8 +57,9 @@ class Amp(GlancesAmp):
|
||||
# Get the systemctl status
|
||||
logger.debug('{}: Update stats using service {}'.format(self.NAME, self.get('service_cmd')))
|
||||
try:
|
||||
res = check_output(self.get('service_cmd').split(), stderr=STDOUT).decode('utf-8')
|
||||
except OSError as e:
|
||||
# res = check_output(self.get('service_cmd').split(), stderr=STDOUT).decode('utf-8')
|
||||
res = secure_popen(self.get('service_cmd'))
|
||||
except Exception as e:
|
||||
logger.debug(f'{self.NAME}: Error while executing service ({e})')
|
||||
else:
|
||||
status = {'running': 0, 'stopped': 0, 'upstart': 0}
|
||||
|
@ -11,7 +11,7 @@
|
||||
import sys
|
||||
import time
|
||||
|
||||
import ujson
|
||||
import orjson
|
||||
|
||||
from glances import __version__
|
||||
from glances.globals import Fault, ProtocolError, ServerProxy, Transport
|
||||
@ -118,7 +118,7 @@ class GlancesClient:
|
||||
if __version__.split('.')[0] == client_version.split('.')[0]:
|
||||
# Init stats
|
||||
self.stats = GlancesStatsClient(config=self.config, args=self.args)
|
||||
self.stats.set_plugins(ujson.loads(self.client.getAllPlugins()))
|
||||
self.stats.set_plugins(orjson.loads(self.client.getAllPlugins()))
|
||||
logger.debug(f"Client version: {__version__} / Server version: {client_version}")
|
||||
else:
|
||||
self.log_and_exit(
|
||||
@ -195,7 +195,7 @@ class GlancesClient:
|
||||
"""
|
||||
# Update the stats
|
||||
try:
|
||||
server_stats = ujson.loads(self.client.getAll())
|
||||
server_stats = orjson.loads(self.client.getAll())
|
||||
except OSError:
|
||||
# Client cannot get server stats
|
||||
return "Disconnected"
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
import threading
|
||||
|
||||
import ujson
|
||||
import orjson
|
||||
|
||||
from glances.autodiscover import GlancesAutoDiscoverServer
|
||||
from glances.client import GlancesClient, GlancesClientTransport
|
||||
@ -95,12 +95,12 @@ class GlancesClientBrowser:
|
||||
# Mandatory stats
|
||||
try:
|
||||
# CPU%
|
||||
cpu_percent = 100 - ujson.loads(s.getCpu())['idle']
|
||||
cpu_percent = 100 - orjson.loads(s.getPlugin('cpu'))['idle']
|
||||
server['cpu_percent'] = f'{cpu_percent:.1f}'
|
||||
# MEM%
|
||||
server['mem_percent'] = ujson.loads(s.getMem())['percent']
|
||||
server['mem_percent'] = orjson.loads(s.getPlugin('mem'))['percent']
|
||||
# OS (Human Readable name)
|
||||
server['hr_name'] = ujson.loads(s.getSystem())['hr_name']
|
||||
server['hr_name'] = orjson.loads(s.getPlugin('system'))['hr_name']
|
||||
except (OSError, Fault, KeyError) as e:
|
||||
logger.debug(f"Error while grabbing stats form server ({e})")
|
||||
server['status'] = 'OFFLINE'
|
||||
@ -120,7 +120,7 @@ class GlancesClientBrowser:
|
||||
# Optional stats (load is not available on Windows OS)
|
||||
try:
|
||||
# LOAD
|
||||
load_min5 = ujson.loads(s.getLoad())['min5']
|
||||
load_min5 = orjson.loads(s.getPlugin('load'))['min5']
|
||||
server['load_min5'] = f'{load_min5:.2f}'
|
||||
except Exception as e:
|
||||
logger.warning(f"Error while grabbing stats form server ({e})")
|
||||
|
@ -81,16 +81,29 @@ def default_config_dir():
|
||||
- Linux, SunOS, *BSD, macOS: /usr/share/doc (as defined in the setup.py files)
|
||||
- Windows: %APPDATA%\glances
|
||||
"""
|
||||
if LINUX or SUNOS or BSD or MACOS:
|
||||
path = '/usr/share/doc'
|
||||
else:
|
||||
path = os.environ.get('APPDATA')
|
||||
if path is None:
|
||||
path = ''
|
||||
else:
|
||||
path = os.path.join(path, 'glances')
|
||||
path = []
|
||||
# Add venv path (solve issue #2803)
|
||||
if in_virtualenv():
|
||||
path.append(os.path.join(sys.prefix, 'share', 'doc', 'glances'))
|
||||
|
||||
return [path]
|
||||
# Add others system path
|
||||
if LINUX or SUNOS or BSD or MACOS:
|
||||
path.append('/usr/share/doc')
|
||||
else:
|
||||
path.append(os.environ.get('APPDATA'))
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def in_virtualenv():
|
||||
# Source: https://stackoverflow.com/questions/1871549/how-to-determine-if-python-is-running-inside-a-virtualenv/1883251#1883251
|
||||
return sys.prefix != get_base_prefix_compat()
|
||||
|
||||
|
||||
def get_base_prefix_compat():
|
||||
"""Get base/real prefix, or sys.prefix if there is none."""
|
||||
# Source: https://stackoverflow.com/questions/1871549/how-to-determine-if-python-is-running-inside-a-virtualenv/1883251#1883251
|
||||
return getattr(sys, "base_prefix", None) or getattr(sys, "real_prefix", None) or sys.prefix
|
||||
|
||||
|
||||
class Config:
|
||||
@ -104,6 +117,7 @@ class Config:
|
||||
self.config_dir = config_dir
|
||||
self.config_filename = 'glances.conf'
|
||||
self._loaded_config_file = None
|
||||
self._config_file_paths = self.config_file_paths()
|
||||
|
||||
# Re pattern for optimize research of `foo`
|
||||
self.re_pattern = re.compile(r'(\`.+?\`)')
|
||||
@ -151,7 +165,7 @@ class Config:
|
||||
|
||||
def read(self):
|
||||
"""Read the config file, if it exists. Using defaults otherwise."""
|
||||
for config_file in self.config_file_paths():
|
||||
for config_file in self._config_file_paths:
|
||||
logger.debug(f'Search glances.conf file in {config_file}')
|
||||
if os.path.exists(config_file):
|
||||
try:
|
||||
|
@ -23,7 +23,7 @@ class CpuPercent:
|
||||
self.percpu_percent = []
|
||||
|
||||
# Get CPU name
|
||||
self.__get_cpu_name()
|
||||
self.cpu_info['cpu_name'] = self.__get_cpu_name()
|
||||
|
||||
# cached_timer_cpu is the minimum time interval between stats updates
|
||||
# since last update is passed (will retrieve old cached info instead)
|
||||
@ -71,12 +71,18 @@ class CpuPercent:
|
||||
|
||||
def __get_cpu_name(self):
|
||||
# Get the CPU name once from the /proc/cpuinfo file
|
||||
# TODO: Multisystem...
|
||||
# Read the first line with the "model name"
|
||||
ret = None
|
||||
try:
|
||||
self.cpu_info['cpu_name'] = open('/proc/cpuinfo').readlines()[4].split(':')[1].strip()
|
||||
except (FileNotFoundError, PermissionError, IndexError, KeyError, AttributeError):
|
||||
self.cpu_info['cpu_name'] = 'CPU'
|
||||
return self.cpu_info['cpu_name']
|
||||
cpuinfo_file = open('/proc/cpuinfo').readlines()
|
||||
except (FileNotFoundError, PermissionError):
|
||||
pass
|
||||
else:
|
||||
for line in cpuinfo_file:
|
||||
if line.startswith('model name'):
|
||||
ret = line.split(':')[1].strip()
|
||||
break
|
||||
return ret if ret else 'CPU'
|
||||
|
||||
def __get_cpu(self):
|
||||
"""Update and/or return the CPU using the psutil library."""
|
||||
|
@ -33,7 +33,7 @@ from urllib.request import Request, urlopen
|
||||
from xmlrpc.client import Fault, ProtocolError, Server, ServerProxy, Transport
|
||||
from xmlrpc.server import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
|
||||
|
||||
import ujson
|
||||
import orjson
|
||||
|
||||
# Correct issue #1025 by monkey path the xmlrpc lib
|
||||
from defusedxml.xmlrpc import monkey_patch
|
||||
@ -309,9 +309,9 @@ def json_dumps(data):
|
||||
Manage the issue #815 for Windows OS with UnicodeDecodeError catching.
|
||||
"""
|
||||
try:
|
||||
return ujson.dumps(data)
|
||||
return orjson.dumps(data)
|
||||
except UnicodeDecodeError:
|
||||
return ujson.dumps(data, ensure_ascii=False)
|
||||
return orjson.dumps(data, ensure_ascii=False)
|
||||
|
||||
|
||||
def dictlist(data, item):
|
||||
|
@ -249,15 +249,19 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
screen_x = self.screen.getmaxyx()[1]
|
||||
screen_y = self.screen.getmaxyx()[0]
|
||||
stats_max = screen_y - 3
|
||||
stats_len = len(stats)
|
||||
|
||||
self._page_max_lines = stats_max
|
||||
self._page_max = int(math.ceil(stats_len / stats_max))
|
||||
# Init position
|
||||
x = 0
|
||||
y = 0
|
||||
self._page_max = int(math.ceil(len(stats) / stats_max))
|
||||
|
||||
# Display top header
|
||||
# Display header
|
||||
x, y = self.__display_header(stats, 0, 0, screen_x, screen_y)
|
||||
|
||||
# Display Glances server list
|
||||
# ================================
|
||||
return self.__display_server_list(stats, x, y, screen_x, screen_y)
|
||||
|
||||
def __display_header(self, stats, x, y, screen_x, screen_y):
|
||||
stats_len = len(stats)
|
||||
stats_max = screen_y - 3
|
||||
if stats_len == 0:
|
||||
if self.first_scan and not self.args.disable_autodiscover:
|
||||
msg = 'Glances is scanning your network. Please wait...'
|
||||
@ -282,11 +286,14 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
msg = f'{page_lines} servers displayed.({self._current_page + 1}/{self._page_max}) {status_count}'
|
||||
self.term_window.addnstr(y + 1, x, msg, screen_x - x)
|
||||
|
||||
if stats_len == 0:
|
||||
return x, y
|
||||
|
||||
def __display_server_list(self, stats, x, y, screen_x, screen_y):
|
||||
if len(stats) == 0:
|
||||
# No server to display
|
||||
return False
|
||||
|
||||
# Display the Glances server list
|
||||
# ================================
|
||||
stats_max = screen_y - 3
|
||||
|
||||
# Table of table
|
||||
# Item description: [stats_id, column name, column size]
|
||||
|
@ -130,11 +130,11 @@ class GlancesRestfulApi:
|
||||
# https://fastapi.tiangolo.com/tutorial/cors/
|
||||
self._app.add_middleware(
|
||||
CORSMiddleware,
|
||||
# allow_origins=["*"],
|
||||
allow_origins=[self.bind_url],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
# Related to https://github.com/nicolargo/glances/issues/2812
|
||||
allow_origins=config.get_list_value('outputs', 'cors_origins', default=["*"]),
|
||||
allow_credentials=config.get_bool_value('outputs', 'cors_credentials', default=True),
|
||||
allow_methods=config.get_list_value('outputs', 'cors_methods', default=["*"]),
|
||||
allow_headers=config.get_list_value('outputs', 'cors_headers', default=["*"]),
|
||||
)
|
||||
|
||||
# FastAPI Enable GZIP compression
|
||||
|
@ -218,23 +218,23 @@ body {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
/* Loading page */
|
||||
// /* Loading page */
|
||||
|
||||
#loading-page .glances-logo {
|
||||
background: url('../images/glances.png') no-repeat center center;
|
||||
background-size: contain;
|
||||
}
|
||||
// #loading-page .glances-logo {
|
||||
// background: url('../images/glances.png') no-repeat center center;
|
||||
// background-size: contain;
|
||||
// }
|
||||
|
||||
@media (max-width: 750px) {
|
||||
#loading-page .glances-logo {
|
||||
height: 400px;
|
||||
}
|
||||
}
|
||||
@media (min-width: 750px) {
|
||||
#loading-page .glances-logo {
|
||||
height: 500px;
|
||||
}
|
||||
}
|
||||
// @media (max-width: 750px) {
|
||||
// #loading-page .glances-logo {
|
||||
// height: 400px;
|
||||
// }
|
||||
// }
|
||||
// @media (min-width: 750px) {
|
||||
// #loading-page .glances-logo {
|
||||
// height: 500px;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
/*
|
||||
|
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div v-if="!dataLoaded" class="container-fluid" id="loading-page">
|
||||
<div class="glances-logo"></div>
|
||||
<div class="loader">Loading...</div>
|
||||
<div class="loader">Glances is loading...</div>
|
||||
</div>
|
||||
<glances-help v-else-if="args.help_tag"></glances-help>
|
||||
<main v-else>
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 49 KiB |
6
glances/outputs/static/public/glances.js
vendored
6
glances/outputs/static/public/glances.js
vendored
File diff suppressed because one or more lines are too long
@ -10,7 +10,7 @@
|
||||
|
||||
import threading
|
||||
|
||||
from ujson import loads
|
||||
from orjson import loads
|
||||
|
||||
from glances.globals import queue, urlopen_auth
|
||||
from glances.logger import logger
|
||||
|
@ -88,6 +88,11 @@ class PluginModel(GlancesPluginModel):
|
||||
self.hide_zero = False
|
||||
self.hide_zero_fields = ['bytes_recv', 'bytes_sent']
|
||||
|
||||
# Add support for automatically hiding network interfaces that are down
|
||||
# or that don't have any IP addresses #2799
|
||||
self.hide_no_up = config.get_bool_value(self.plugin_name, 'hide_no_up', default=False)
|
||||
self.hide_no_ip = config.get_bool_value(self.plugin_name, 'hide_no_ip', default=False)
|
||||
|
||||
# Force a first update because we need two updates to have the first stat
|
||||
self.update()
|
||||
self.refresh_timer.set(0)
|
||||
@ -140,10 +145,21 @@ class PluginModel(GlancesPluginModel):
|
||||
net_status = {}
|
||||
try:
|
||||
net_status = psutil.net_if_stats()
|
||||
net_addrs = psutil.net_if_addrs()
|
||||
except OSError as e:
|
||||
# see psutil #797/glances #1106
|
||||
logger.debug(f'Can not get network interface status ({e})')
|
||||
|
||||
# Filter interfaces (related to #2799)
|
||||
if self.hide_no_up:
|
||||
net_status = {k: v for k, v in net_status.items() if v.isup}
|
||||
if self.hide_no_ip:
|
||||
net_status = {
|
||||
k: v
|
||||
for k, v in net_status.items()
|
||||
if k in net_addrs and any(a.family != psutil.AF_LINK for a in net_addrs[k])
|
||||
}
|
||||
|
||||
for interface_name, interface_stat in net_io_counters.items():
|
||||
# Do not take hidden interface into account
|
||||
# or KeyError: 'eth0' when interface is not connected #1348
|
||||
|
@ -95,7 +95,7 @@ class GlancesPluginModel:
|
||||
# Init the limits (configuration keys) dictionary
|
||||
self._limits = {}
|
||||
if config is not None:
|
||||
logger.debug(f'Load section {self.plugin_name} in {config.config_file_paths()}')
|
||||
logger.debug(f'Load section {self.plugin_name} in Glances configuration file')
|
||||
self.load_limits(config=config)
|
||||
|
||||
# Init the alias (dictionnary)
|
||||
|
@ -23,7 +23,7 @@ def secure_popen(cmd):
|
||||
"""
|
||||
ret = ''
|
||||
|
||||
# Split by multiple commands '&&'
|
||||
# Split by multiple commands (only '&&' separator is supported)
|
||||
for c in cmd.split('&&'):
|
||||
ret += __secure_popen(c)
|
||||
|
||||
|
@ -8,13 +8,14 @@
|
||||
|
||||
"""Manage the Glances server."""
|
||||
|
||||
import json
|
||||
import socket
|
||||
import sys
|
||||
from base64 import b64decode
|
||||
|
||||
from glances import __version__
|
||||
from glances.autodiscover import GlancesAutoDiscoverClient
|
||||
from glances.globals import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer, json_dumps
|
||||
from glances.globals import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
|
||||
from glances.logger import logger
|
||||
from glances.stats_server import GlancesStatsServer
|
||||
from glances.timer import Timer
|
||||
@ -140,39 +141,28 @@ class GlancesInstance:
|
||||
def getAll(self):
|
||||
# Update and return all the stats
|
||||
self.__update__()
|
||||
return json_dumps(self.stats.getAll())
|
||||
return json.dumps(self.stats.getAll())
|
||||
|
||||
def getAllPlugins(self):
|
||||
# Return the plugins list
|
||||
return json_dumps(self.stats.getPluginsList())
|
||||
return json.dumps(self.stats.getPluginsList())
|
||||
|
||||
def getAllLimits(self):
|
||||
# Return all the plugins limits
|
||||
return json_dumps(self.stats.getAllLimitsAsDict())
|
||||
return json.dumps(self.stats.getAllLimitsAsDict())
|
||||
|
||||
def getAllViews(self):
|
||||
# Return all the plugins views
|
||||
return json_dumps(self.stats.getAllViewsAsDict())
|
||||
return json.dumps(self.stats.getAllViewsAsDict())
|
||||
|
||||
def __getattr__(self, item):
|
||||
"""Overwrite the getattr method in case of attribute is not found.
|
||||
def getPlugin(self, plugin):
|
||||
# Update and return the plugin stat
|
||||
self.__update__()
|
||||
return json.dumps(self.stats.get_plugin(plugin).get_raw())
|
||||
|
||||
The goal is to dynamically generate the API get'Stats'() methods.
|
||||
"""
|
||||
header = 'get'
|
||||
# Check if the attribute starts with 'get'
|
||||
if item.startswith(header):
|
||||
try:
|
||||
# Update the stat
|
||||
self.__update__()
|
||||
# Return the attribute
|
||||
return getattr(self.stats, item)
|
||||
except Exception:
|
||||
# The method is not found for the plugin
|
||||
raise AttributeError(item)
|
||||
else:
|
||||
# Default behavior
|
||||
raise AttributeError(item)
|
||||
def getPluginView(self, plugin):
|
||||
# Update and return the plugin view
|
||||
return json.dumps(self.stats.get_plugin(plugin).get_views())
|
||||
|
||||
|
||||
class GlancesServer:
|
||||
|
@ -52,7 +52,7 @@ class GlancesStats:
|
||||
# Get the plugin instance
|
||||
plugin = self._plugins[plugname]
|
||||
if hasattr(plugin, 'get_json_views'):
|
||||
# The method get_views exist, return it
|
||||
# The method get_json_views exist, return it
|
||||
return getattr(plugin, 'get_json_views')
|
||||
# The method get_views is not found for the plugin
|
||||
raise AttributeError(item)
|
||||
@ -61,9 +61,9 @@ class GlancesStats:
|
||||
plugname = item[len('get') :].lower()
|
||||
# Get the plugin instance
|
||||
plugin = self._plugins[plugname]
|
||||
if hasattr(plugin, 'get_stats'):
|
||||
# The method get_stats exist, return it
|
||||
return getattr(plugin, 'get_stats')
|
||||
if hasattr(plugin, 'get_json'):
|
||||
# The method get_json exist, return it
|
||||
return getattr(plugin, 'get_json')
|
||||
# The method get_stats is not found for the plugin
|
||||
raise AttributeError(item)
|
||||
# Default behavior
|
||||
@ -358,11 +358,17 @@ class GlancesStats:
|
||||
return self._plugins
|
||||
|
||||
def get_plugin(self, plugin_name):
|
||||
"""Return the plugin name."""
|
||||
"""Return the plugin stats."""
|
||||
if plugin_name in self._plugins:
|
||||
return self._plugins[plugin_name]
|
||||
return None
|
||||
|
||||
def get_plugin_view(self, plugin_name):
|
||||
"""Return the plugin views."""
|
||||
if plugin_name in self._plugins:
|
||||
return self._plugins[plugin_name].get_views()
|
||||
return None
|
||||
|
||||
def end(self):
|
||||
"""End of the Glances stats."""
|
||||
# Close export modules
|
||||
|
@ -7,35 +7,32 @@ cassandra-driver
|
||||
chevron
|
||||
docker>=6.1.1
|
||||
elasticsearch
|
||||
fastapi; python_version >= "3.8"
|
||||
fastapi
|
||||
graphitesender
|
||||
hddtemp
|
||||
influxdb>=1.0.0 # For InfluxDB < 1.8
|
||||
influxdb-client; python_version >= "3.7" # For InfluxDB >= 1.8
|
||||
influxdb-client # For InfluxDB >= 1.8
|
||||
jinja2
|
||||
kafka-python
|
||||
netifaces
|
||||
nvidia-ml-py; python_version >= "3.5"
|
||||
packaging; python_version >= "3.7"
|
||||
nvidia-ml-py
|
||||
paho-mqtt
|
||||
pika
|
||||
podman; python_version >= "3.6"
|
||||
podman
|
||||
potsdb
|
||||
prometheus_client
|
||||
pycouchdb
|
||||
pydantic
|
||||
pygal
|
||||
pymdstat
|
||||
pymongo; python_version >= "3.7"
|
||||
pymongo
|
||||
pySMART.smartx
|
||||
pysnmp-lextudio; python_version >= "3.7"
|
||||
pysnmp-lextudio
|
||||
python-dateutil
|
||||
pyzmq
|
||||
requests
|
||||
scandir; python_version < "3.5"
|
||||
six
|
||||
sparklines
|
||||
statsd
|
||||
uvicorn; python_version >= "3.8"
|
||||
wifi
|
||||
uvicorn
|
||||
zeroconf==0.131.0 # Waiting correction for ARMv7: https://github.com/python-zeroconf/python-zeroconf/issues/1372
|
||||
|
@ -1,8 +1,3 @@
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
skip-string-normalization = true
|
||||
exclude = '\./glances/outputs/static/*'
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
target-version = "py38"
|
||||
|
@ -1,4 +1,4 @@
|
||||
defusedxml
|
||||
orjson
|
||||
packaging
|
||||
psutil>=5.6.7
|
||||
ujson>=5.4.0
|
||||
|
@ -1,5 +1,5 @@
|
||||
name: glances
|
||||
version: '4.0.7'
|
||||
version: '4.0.8'
|
||||
|
||||
summary: Glances an Eye on your system. A top/htop alternative.
|
||||
description: |
|
||||
@ -9,7 +9,7 @@ description: |
|
||||
depending on the user interface size.
|
||||
|
||||
base: core22
|
||||
grade: stable
|
||||
grade: stable # devel
|
||||
confinement: strict
|
||||
|
||||
apps:
|
||||
@ -49,7 +49,7 @@ parts:
|
||||
glances:
|
||||
plugin: python
|
||||
source: https://github.com/nicolargo/glances.git
|
||||
source-branch: master
|
||||
source-branch: master # develop
|
||||
python-requirements:
|
||||
- requirements.txt
|
||||
- webui-requirements.txt
|
||||
|
2
tox.ini
2
tox.ini
@ -18,7 +18,7 @@ deps =
|
||||
psutil
|
||||
defusedxml
|
||||
packaging
|
||||
ujson
|
||||
orjson
|
||||
fastapi
|
||||
uvicorn
|
||||
jinja2
|
||||
|
@ -17,14 +17,24 @@ import time
|
||||
import unittest
|
||||
|
||||
from glances import __version__
|
||||
from glances.globals import ServerProxy
|
||||
from glances.client import GlancesClient
|
||||
|
||||
SERVER_HOST = 'localhost'
|
||||
SERVER_PORT = 61234
|
||||
URL = f"http://localhost:{SERVER_PORT}"
|
||||
pid = None
|
||||
|
||||
|
||||
# Init the XML-RPC client
|
||||
client = ServerProxy(URL)
|
||||
class args:
|
||||
client = SERVER_HOST
|
||||
port = SERVER_PORT
|
||||
username = ""
|
||||
password = ""
|
||||
time = 3
|
||||
quiet = False
|
||||
|
||||
|
||||
client = GlancesClient(args=args).client
|
||||
|
||||
# Unitest class
|
||||
# ==============
|
||||
@ -71,14 +81,16 @@ class TestGlances(unittest.TestCase):
|
||||
print('INFO: [TEST_002] Get plugins list')
|
||||
print(f"XML-RPC request: {method}")
|
||||
req = json.loads(client.getAllPlugins())
|
||||
print(req)
|
||||
|
||||
self.assertIsInstance(req, list)
|
||||
self.assertIn('cpu', req)
|
||||
|
||||
def test_003_system(self):
|
||||
"""System."""
|
||||
method = "getSystem()"
|
||||
print(f'INFO: [TEST_003] Method: {method}')
|
||||
req = json.loads(client.getSystem())
|
||||
req = json.loads(client.getPlugin('system'))
|
||||
|
||||
self.assertIsInstance(req, dict)
|
||||
|
||||
@ -87,16 +99,16 @@ class TestGlances(unittest.TestCase):
|
||||
method = "getCpu(), getPerCpu(), getLoad() and getCore()"
|
||||
print(f'INFO: [TEST_004] Method: {method}')
|
||||
|
||||
req = json.loads(client.getCpu())
|
||||
req = json.loads(client.getPlugin('cpu'))
|
||||
self.assertIsInstance(req, dict)
|
||||
|
||||
req = json.loads(client.getPerCpu())
|
||||
req = json.loads(client.getPlugin('percpu'))
|
||||
self.assertIsInstance(req, list)
|
||||
|
||||
req = json.loads(client.getLoad())
|
||||
req = json.loads(client.getPlugin('load'))
|
||||
self.assertIsInstance(req, dict)
|
||||
|
||||
req = json.loads(client.getCore())
|
||||
req = json.loads(client.getPlugin('core'))
|
||||
self.assertIsInstance(req, dict)
|
||||
|
||||
def test_005_mem(self):
|
||||
@ -104,10 +116,10 @@ class TestGlances(unittest.TestCase):
|
||||
method = "getMem() and getMemSwap()"
|
||||
print(f'INFO: [TEST_005] Method: {method}')
|
||||
|
||||
req = json.loads(client.getMem())
|
||||
req = json.loads(client.getPlugin('mem'))
|
||||
self.assertIsInstance(req, dict)
|
||||
|
||||
req = json.loads(client.getMemSwap())
|
||||
req = json.loads(client.getPlugin('memswap'))
|
||||
self.assertIsInstance(req, dict)
|
||||
|
||||
def test_006_net(self):
|
||||
@ -115,7 +127,7 @@ class TestGlances(unittest.TestCase):
|
||||
method = "getNetwork()"
|
||||
print(f'INFO: [TEST_006] Method: {method}')
|
||||
|
||||
req = json.loads(client.getNetwork())
|
||||
req = json.loads(client.getPlugin('network'))
|
||||
self.assertIsInstance(req, list)
|
||||
|
||||
def test_007_disk(self):
|
||||
@ -123,13 +135,13 @@ class TestGlances(unittest.TestCase):
|
||||
method = "getFs(), getFolders() and getDiskIO()"
|
||||
print(f'INFO: [TEST_007] Method: {method}')
|
||||
|
||||
req = json.loads(client.getFs())
|
||||
req = json.loads(client.getPlugin('fs'))
|
||||
self.assertIsInstance(req, list)
|
||||
|
||||
req = json.loads(client.getFolders())
|
||||
req = json.loads(client.getPlugin('folders'))
|
||||
self.assertIsInstance(req, list)
|
||||
|
||||
req = json.loads(client.getDiskIO())
|
||||
req = json.loads(client.getPlugin('diskio'))
|
||||
self.assertIsInstance(req, list)
|
||||
|
||||
def test_008_sensors(self):
|
||||
@ -137,7 +149,7 @@ class TestGlances(unittest.TestCase):
|
||||
method = "getSensors()"
|
||||
print(f'INFO: [TEST_008] Method: {method}')
|
||||
|
||||
req = json.loads(client.getSensors())
|
||||
req = json.loads(client.getPlugin('sensors'))
|
||||
self.assertIsInstance(req, list)
|
||||
|
||||
def test_009_process(self):
|
||||
@ -145,10 +157,10 @@ class TestGlances(unittest.TestCase):
|
||||
method = "getProcessCount() and getProcessList()"
|
||||
print(f'INFO: [TEST_009] Method: {method}')
|
||||
|
||||
req = json.loads(client.getProcessCount())
|
||||
req = json.loads(client.getPlugin('processcount'))
|
||||
self.assertIsInstance(req, dict)
|
||||
|
||||
req = json.loads(client.getProcessList())
|
||||
req = json.loads(client.getPlugin('processlist'))
|
||||
self.assertIsInstance(req, list)
|
||||
|
||||
def test_010_all_limits(self):
|
||||
@ -173,7 +185,7 @@ class TestGlances(unittest.TestCase):
|
||||
"""IRQS"""
|
||||
method = "getIrqs()"
|
||||
print(f'INFO: [TEST_012] Method: {method}')
|
||||
req = json.loads(client.getIrq())
|
||||
req = json.loads(client.getPlugin('irq'))
|
||||
self.assertIsInstance(req, list)
|
||||
|
||||
def test_013_plugin_views(self):
|
||||
@ -181,12 +193,13 @@ class TestGlances(unittest.TestCase):
|
||||
method = "getViewsCpu()"
|
||||
print(f'INFO: [TEST_013] Method: {method}')
|
||||
|
||||
req = json.loads(client.getViewsCpu())
|
||||
req = json.loads(client.getPluginView('cpu'))
|
||||
self.assertIsInstance(req, dict)
|
||||
|
||||
def test_999_stop_server(self):
|
||||
"""Stop the Glances Web Server."""
|
||||
print('INFO: [TEST_999] Stop the Glances Server')
|
||||
print(client.system.listMethods())
|
||||
|
||||
print("Stop the Glances Server")
|
||||
pid.terminate()
|
||||
|
Loading…
Reference in New Issue
Block a user