mirror of
https://github.com/nicolargo/glances.git
synced 2024-08-17 00:10:48 +03:00
Compare commits
41 Commits
a1197c2adb
...
03d7380456
Author | SHA1 | Date | |
---|---|---|---|
|
03d7380456 | ||
|
dc24e35786 | ||
|
6af2340c5c | ||
|
46abd4b4c9 | ||
|
2801add7e2 | ||
|
9b853d857b | ||
|
99e65079a0 | ||
|
0e1d462c69 | ||
|
f4c7ca01fe | ||
|
60591630df | ||
|
48103f167e | ||
|
154ae8e610 | ||
|
86c2cd1d4a | ||
|
452fd6497e | ||
|
ccfd8f0aa9 | ||
|
d91bfa2f8b | ||
|
582ca07716 | ||
|
036eb976e9 | ||
|
2c5a1150bd | ||
|
f6066e5d46 | ||
|
cff2e9fc4a | ||
|
e5d5351d31 | ||
|
be89ee0025 | ||
|
f4cd350221 | ||
|
3928007169 | ||
|
eebd769c46 | ||
|
2ee3c86e2b | ||
|
f5ecbf7a1f | ||
|
267e7e2ff0 | ||
|
1e2e36af23 | ||
|
c153e71aa3 | ||
|
f9915d93e8 | ||
|
69c3a948ba | ||
|
8c520e1d94 | ||
|
1edaed52de | ||
|
752bd40a04 | ||
|
fce3aac34e | ||
|
9c482196f3 | ||
|
3beb08b66e | ||
|
0874e13f1d | ||
|
8b4ef8c235 |
3
.github/workflows/test.yml
vendored
3
.github/workflows/test.yml
vendored
@ -99,7 +99,8 @@ jobs:
|
|||||||
runs-on: macos-14
|
runs-on: macos-14
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
# Only test the latest stable version
|
||||||
|
python-version: ["3.12"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
|
34
.readthedocs.yaml
Normal file
34
.readthedocs.yaml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Read the Docs configuration file for Glances projects
|
||||||
|
|
||||||
|
# Required
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
# Set the OS, Python version and other tools you might need
|
||||||
|
build:
|
||||||
|
os: ubuntu-22.04
|
||||||
|
tools:
|
||||||
|
python: "3.12"
|
||||||
|
# You can also specify other tool versions:
|
||||||
|
# nodejs: "20"
|
||||||
|
# rust: "1.70"
|
||||||
|
# golang: "1.20"
|
||||||
|
|
||||||
|
# Build documentation in the "docs/" directory with Sphinx
|
||||||
|
sphinx:
|
||||||
|
configuration: docs/conf.py
|
||||||
|
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
|
||||||
|
# builder: "dirhtml"
|
||||||
|
# Fail on all warnings to avoid broken references
|
||||||
|
# fail_on_warning: true
|
||||||
|
|
||||||
|
# Optionally build your docs in additional formats such as PDF and ePub
|
||||||
|
# formats:
|
||||||
|
# - pdf
|
||||||
|
# - epub
|
||||||
|
|
||||||
|
# Optional but recommended, declare the Python requirements required
|
||||||
|
# to build your documentation
|
||||||
|
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
|
||||||
|
python:
|
||||||
|
install:
|
||||||
|
- requirements: doc-requirements.txt
|
@ -6,7 +6,7 @@ In the interest of fostering an open and welcoming environment, we as
|
|||||||
contributors and maintainers pledge to making participation in our project and
|
contributors and maintainers pledge to making participation in our project and
|
||||||
our community a harassment-free experience for everyone, regardless of age, body
|
our community a harassment-free experience for everyone, regardless of age, body
|
||||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||||
education, socio-economic status, nationality, personal appearance, race,
|
education, socioeconomic status, nationality, personal appearance, race,
|
||||||
religion, or sexual identity and orientation.
|
religion, or sexual identity and orientation.
|
||||||
|
|
||||||
## Our Standards
|
## Our Standards
|
||||||
|
4
Makefile
4
Makefile
@ -93,7 +93,7 @@ lint: ## Lint the code.
|
|||||||
./venv-dev/bin/python -m ruff check . --fix
|
./venv-dev/bin/python -m ruff check . --fix
|
||||||
|
|
||||||
codespell: ## Run codespell to fix common misspellings in text files
|
codespell: ## Run codespell to fix common misspellings in text files
|
||||||
./venv-dev/bin/codespell -S .git,./docs/_build,./Glances.egg-info,./venv*,./glances/outputs,*.svg -L hart,bu,te,statics
|
./venv-dev/bin/codespell -S .git,./docs/_build,./Glances.egg-info,./venv*,./glances/outputs,*.svg -L hart,bu,te,statics -w
|
||||||
|
|
||||||
semgrep: ## Run semgrep to find bugs and enforce code standards
|
semgrep: ## Run semgrep to find bugs and enforce code standards
|
||||||
./venv-dev/bin/semgrep scan --config=auto
|
./venv-dev/bin/semgrep scan --config=auto
|
||||||
@ -185,7 +185,7 @@ flatpak: venv-dev-upgrade ## Generate FlatPack JSON file
|
|||||||
rm -rf ./flatpak-builder-tools
|
rm -rf ./flatpak-builder-tools
|
||||||
@echo "Now follow: https://github.com/flathub/flathub/wiki/App-Submission"
|
@echo "Now follow: https://github.com/flathub/flathub/wiki/App-Submission"
|
||||||
|
|
||||||
# Snap package is automaticaly build on the Snapcraft.io platform
|
# Snap package is automatically build on the Snapcraft.io platform
|
||||||
# https://snapcraft.io/glances
|
# https://snapcraft.io/glances
|
||||||
# But you can try an offline build with the following command
|
# But you can try an offline build with the following command
|
||||||
snapcraft:
|
snapcraft:
|
||||||
|
61
NEWS.rst
61
NEWS.rst
@ -2,13 +2,56 @@
|
|||||||
Glances ChangeLog
|
Glances ChangeLog
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 4.2.0
|
||||||
|
===============
|
||||||
|
|
||||||
|
Under development, see roadmap here: https://github.com/nicolargo/glances/milestone/73
|
||||||
|
|
||||||
|
Contributors are welcome !
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 4.1.1
|
||||||
|
===============
|
||||||
|
|
||||||
|
Bug corrected:
|
||||||
|
|
||||||
|
* Sensors data is not exported using InfluxDB2 exporter #2856
|
||||||
|
|
||||||
===============
|
===============
|
||||||
Version 4.1.0
|
Version 4.1.0
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Under development, see roadmap here: https://github.com/nicolargo/glances/milestone/68
|
Enhancements:
|
||||||
|
|
||||||
Contributors are welcome !
|
* Call process_iter.clear_cache() (PsUtil 6+) when Glances user force a refresh (F5 or CTRL-R) #2753
|
||||||
|
* PsUtil 6+ no longer check PID reused #2755
|
||||||
|
* Add support for automatically hiding network interfaces that are down or that don't have any IP addresses #2799
|
||||||
|
|
||||||
|
Bug corrected:
|
||||||
|
|
||||||
|
* API: Network module is disabled but appears in endpoint "all" #2815
|
||||||
|
* API is not compatible with requests containing special/encoding char #2820
|
||||||
|
* 'j' hot key crashes Glances #2831
|
||||||
|
* Raspberry PI - CPU info is not correct #2616
|
||||||
|
* Graph export is broken if there is no graph section in Glances configuration file #2839
|
||||||
|
* Glances API status check returns Error 405 - Method Not Allowed #2841
|
||||||
|
* Rootless podman containers cause glances to fail with KeyError #2827
|
||||||
|
* --export-process-filter Filter using complete command #2824
|
||||||
|
* Exception when Glances is ran with limited plugin list #2822
|
||||||
|
* Disable separator option do not work #2823
|
||||||
|
|
||||||
|
Continuous integration and documentation:
|
||||||
|
|
||||||
|
* test test_107_fs_plugin_method fails on aarch64-linux #2819
|
||||||
|
|
||||||
|
Thanks to all contributors and bug reporters !
|
||||||
|
|
||||||
|
Special thanks to:
|
||||||
|
|
||||||
|
* Bharath Vignesh J K
|
||||||
|
* RazCrimson
|
||||||
|
* Vadim Small
|
||||||
|
|
||||||
===============
|
===============
|
||||||
Version 4.0.8
|
Version 4.0.8
|
||||||
@ -183,7 +226,7 @@ Many thinks to the contributors:
|
|||||||
* Christoph Zimmermann
|
* Christoph Zimmermann
|
||||||
* RazCrimson
|
* RazCrimson
|
||||||
* Robin Candau
|
* Robin Candau
|
||||||
* Github GPG acces
|
* Github GPG access
|
||||||
* Continuous Integration
|
* Continuous Integration
|
||||||
* Georgiy Timchenko
|
* Georgiy Timchenko
|
||||||
* turbocrime
|
* turbocrime
|
||||||
@ -357,7 +400,7 @@ Documentation and CI:
|
|||||||
* Update Makefile with comments
|
* Update Makefile with comments
|
||||||
* Update Python minimal requirement for py3nvlm
|
* Update Python minimal requirement for py3nvlm
|
||||||
* Update security policy (user can open private issue directly in Github)
|
* Update security policy (user can open private issue directly in Github)
|
||||||
* Add a simple run script. Entry point for IDE debuger
|
* Add a simple run script. Entry point for IDE debugger
|
||||||
|
|
||||||
Cyber security update:
|
Cyber security update:
|
||||||
|
|
||||||
@ -386,7 +429,7 @@ And also a big thanks to @RazCrimson (https://github.com/RazCrimson) for the sup
|
|||||||
Version 3.3.0.4
|
Version 3.3.0.4
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Refactor the Docker images factory, from now, only Alpine image wll be provided.
|
Refactor the Docker images factory, from now, only Alpine image will be provided.
|
||||||
|
|
||||||
The following Docker images (nicolargo/glances) are availables:
|
The following Docker images (nicolargo/glances) are availables:
|
||||||
|
|
||||||
@ -434,9 +477,9 @@ Bug corrected:
|
|||||||
* Correct issue with the regexp filter (use fullmatch instead of match)
|
* Correct issue with the regexp filter (use fullmatch instead of match)
|
||||||
* Errors when running Glances as web service #1702
|
* Errors when running Glances as web service #1702
|
||||||
* Apply alias to Duplicate sensor name #1686
|
* Apply alias to Duplicate sensor name #1686
|
||||||
* Make the hide function in sensors section compliant with lower/upercase #1590
|
* Make the hide function in sensors section compliant with lower/uppercase #1590
|
||||||
* Web UI truncates the days part of CPU time counter of the process list #2108
|
* Web UI truncates the days part of CPU time counter of the process list #2108
|
||||||
* Correct alignement issue with the diskio plugin (Console UI)
|
* Correct alignment issue with the diskio plugin (Console UI)
|
||||||
|
|
||||||
Documentation and CI:
|
Documentation and CI:
|
||||||
|
|
||||||
@ -703,7 +746,7 @@ Bugs corrected:
|
|||||||
* Docker containers information missing with Docker 20.10.x #1878
|
* Docker containers information missing with Docker 20.10.x #1878
|
||||||
* Get system sensors temperatures thresholds #1864
|
* Get system sensors temperatures thresholds #1864
|
||||||
|
|
||||||
Contibutors for this version:
|
Contributors for this version:
|
||||||
|
|
||||||
* Nicolargo
|
* Nicolargo
|
||||||
* Markus Pöschl
|
* Markus Pöschl
|
||||||
@ -1310,7 +1353,7 @@ Enhancements and new features:
|
|||||||
* Add ZeroMQ exporter (issue #939)
|
* Add ZeroMQ exporter (issue #939)
|
||||||
* Add CouchDB exporter (issue #928)
|
* Add CouchDB exporter (issue #928)
|
||||||
* Add hotspot Wifi information (issue #937)
|
* Add hotspot Wifi information (issue #937)
|
||||||
* Add default interface speed and automatic rate thresolds (issue #718)
|
* Add default interface speed and automatic rate thresholds (issue #718)
|
||||||
* Highlight max stats in the processes list (issue #878)
|
* Highlight max stats in the processes list (issue #878)
|
||||||
* Docker alerts and actions (issue #875)
|
* Docker alerts and actions (issue #875)
|
||||||
* Glances API returns the processes PPID (issue #926)
|
* Glances API returns the processes PPID (issue #926)
|
||||||
|
10
README.rst
10
README.rst
@ -2,7 +2,7 @@
|
|||||||
Glances - An eye on your system
|
Glances - An eye on your system
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
| |pypi| |test| |contibutors| |quality|
|
| |pypi| |test| |contributors| |quality|
|
||||||
| |starts| |docker| |pypistat|
|
| |starts| |docker| |pypistat|
|
||||||
| |sponsors| |twitter|
|
| |sponsors| |twitter|
|
||||||
|
|
||||||
@ -25,9 +25,9 @@ Glances - An eye on your system
|
|||||||
:target: https://github.com/nicolargo/glances/actions
|
:target: https://github.com/nicolargo/glances/actions
|
||||||
:alt: Linux tests (GitHub Actions)
|
:alt: Linux tests (GitHub Actions)
|
||||||
|
|
||||||
.. |contibutors| image:: https://img.shields.io/github/contributors/nicolargo/glances
|
.. |contributors| image:: https://img.shields.io/github/contributors/nicolargo/glances
|
||||||
:target: https://github.com/nicolargo/glances/issues?q=is%3Aissue+is%3Aopen+label%3A%22needs+contributor%22
|
:target: https://github.com/nicolargo/glances/issues?q=is%3Aissue+is%3Aopen+label%3A%22needs+contributor%22
|
||||||
:alt: Contibutors
|
:alt: Contributors
|
||||||
|
|
||||||
.. |quality| image:: https://scrutinizer-ci.com/g/nicolargo/glances/badges/quality-score.png?b=develop
|
.. |quality| image:: https://scrutinizer-ci.com/g/nicolargo/glances/badges/quality-score.png?b=develop
|
||||||
:target: https://scrutinizer-ci.com/g/nicolargo/glances/?branch=develop
|
:target: https://scrutinizer-ci.com/g/nicolargo/glances/?branch=develop
|
||||||
@ -141,7 +141,7 @@ stable version.
|
|||||||
To install Glances, simply use the ``pip`` command line.
|
To install Glances, simply use the ``pip`` command line.
|
||||||
|
|
||||||
Warning: on modern Linux operating systems, you may have an externally-managed-environment
|
Warning: on modern Linux operating systems, you may have an externally-managed-environment
|
||||||
error message when you try to use ``pip``. In this case, go to the the PipX section bellow.
|
error message when you try to use ``pip``. In this case, go to the the PipX section below.
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
@ -221,8 +221,6 @@ Run last version of Glances container in *console mode*:
|
|||||||
|
|
||||||
By default, the /etc/glances/glances.conf file is used (based on docker-compose/glances.conf).
|
By default, the /etc/glances/glances.conf file is used (based on docker-compose/glances.conf).
|
||||||
|
|
||||||
By default, the /etc/glances/glances.conf file is used (based on docker-compose/glances.conf).
|
|
||||||
|
|
||||||
Additionally, if you want to use your own glances.conf file, you can
|
Additionally, if you want to use your own glances.conf file, you can
|
||||||
create your own Dockerfile:
|
create your own Dockerfile:
|
||||||
|
|
||||||
|
@ -2,13 +2,10 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
Use this section to tell people about which versions of your project are
|
|
||||||
currently being supported with security updates.
|
|
||||||
|
|
||||||
| Version | Support security updates |
|
| Version | Support security updates |
|
||||||
| ------- | ------------------------ |
|
| ------- | ------------------------ |
|
||||||
| 3.x | :white_check_mark: |
|
| 4.x | :white_check_mark: |
|
||||||
| < 3.0 | :x: |
|
| < 4.0 | :x: |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
@ -31,4 +28,3 @@ If there are any vulnerabilities in {{cookiecutter.project_name}}, don't hesitat
|
|||||||
4. Please do not disclose the vulnerability publicly until a fix is released!
|
4. Please do not disclose the vulnerability publicly until a fix is released!
|
||||||
|
|
||||||
Once we have either a) published a fix, or b) declined to address the vulnerability for whatever reason, you are free to publicly disclose it.
|
Once we have either a) published a fix, or b) declined to address the vulnerability for whatever reason, you are free to publicly disclose it.
|
||||||
|
|
||||||
|
@ -217,9 +217,9 @@ hide=docker.*,lo
|
|||||||
# Define the list of wireless network interfaces to be show (comma-separated)
|
# Define the list of wireless network interfaces to be show (comma-separated)
|
||||||
#show=docker.*
|
#show=docker.*
|
||||||
# Automatically hide interface not up (default is False)
|
# Automatically hide interface not up (default is False)
|
||||||
#hide_no_up=True
|
hide_no_up=True
|
||||||
# Automatically hide interface with no IP address (default is False)
|
# Automatically hide interface with no IP address (default is False)
|
||||||
#hide_no_ip=True
|
hide_no_ip=True
|
||||||
# It is possible to overwrite the bitrate thresholds per interface
|
# It is possible to overwrite the bitrate thresholds per interface
|
||||||
# WLAN 0 Default limits (in bits per second aka bps) for interface bitrate
|
# WLAN 0 Default limits (in bits per second aka bps) for interface bitrate
|
||||||
#wlan0_rx_careful=4000000
|
#wlan0_rx_careful=4000000
|
||||||
@ -375,7 +375,7 @@ temperature_hdd_critical=60
|
|||||||
battery_careful=80
|
battery_careful=80
|
||||||
battery_warning=90
|
battery_warning=90
|
||||||
battery_critical=95
|
battery_critical=95
|
||||||
# Fan speed threashold in RPM
|
# Fan speed threshold in RPM
|
||||||
#fan_speed_careful=100
|
#fan_speed_careful=100
|
||||||
# Sensors alias
|
# Sensors alias
|
||||||
#alias=core 0:CPU Core 0,core 1:CPU Core 1
|
#alias=core 0:CPU Core 0,core 1:CPU Core 1
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
psutil
|
||||||
|
defusedxml
|
||||||
orjson
|
orjson
|
||||||
reuse
|
reuse
|
||||||
setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
|
setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
|
||||||
|
@ -27,7 +27,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- TZ=${TZ}
|
- TZ=${TZ}
|
||||||
- "GLANCES_OPT=-C /glances/conf/glances.conf -w"
|
- "GLANCES_OPT=-C /glances/conf/glances.conf -w"
|
||||||
# Uncomment for GPU compatibilty (Nvidia) inside the container
|
# Uncomment for GPU compatibility (Nvidia) inside the container
|
||||||
# deploy:
|
# deploy:
|
||||||
# resources:
|
# resources:
|
||||||
# reservations:
|
# reservations:
|
||||||
|
@ -15,7 +15,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- TZ=${TZ}
|
- TZ=${TZ}
|
||||||
- "GLANCES_OPT=-C /glances/conf/glances.conf -w"
|
- "GLANCES_OPT=-C /glances/conf/glances.conf -w"
|
||||||
# Uncomment for GPU compatibilty (Nvidia) inside the container
|
# Uncomment for GPU compatibility (Nvidia) inside the container
|
||||||
# deploy:
|
# deploy:
|
||||||
# resources:
|
# resources:
|
||||||
# reservations:
|
# reservations:
|
||||||
|
@ -60,7 +60,7 @@ max_processes_display=25
|
|||||||
#cors_headers=*
|
#cors_headers=*
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# plugins
|
# Plugins
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
[quicklook]
|
[quicklook]
|
||||||
@ -375,7 +375,7 @@ temperature_hdd_critical=60
|
|||||||
battery_careful=80
|
battery_careful=80
|
||||||
battery_warning=90
|
battery_warning=90
|
||||||
battery_critical=95
|
battery_critical=95
|
||||||
# Fan speed threashold in RPM
|
# Fan speed threshold in RPM
|
||||||
#fan_speed_careful=100
|
#fan_speed_careful=100
|
||||||
# Sensors alias
|
# Sensors alias
|
||||||
#alias=core 0:CPU Core 0,core 1:CPU Core 1
|
#alias=core 0:CPU Core 0,core 1:CPU Core 1
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
CLOUD
|
CLOUD
|
||||||
=====
|
=====
|
||||||
|
|
||||||
This plugin diplays information about the cloud provider if your host is running on OpenStack.
|
This plugin displays information about the cloud provider if your host is running on OpenStack.
|
||||||
|
|
||||||
The plugin use the standard OpenStack `metadata`_ service to retrieve the information.
|
The plugin use the standard OpenStack `metadata`_ service to retrieve the information.
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ To switch to per-CPU stats, just hit the ``1`` key:
|
|||||||
.. image:: ../_static/per-cpu.png
|
.. image:: ../_static/per-cpu.png
|
||||||
|
|
||||||
In this case, Glances will show on line per logical CPU on the system.
|
In this case, Glances will show on line per logical CPU on the system.
|
||||||
If you have multiple core, it is possible to define the maximun number
|
If you have multiple core, it is possible to define the maximum number
|
||||||
of CPU to display. The top 'max_cpu_display' will be display and an
|
of CPU to display. The top 'max_cpu_display' will be display and an
|
||||||
extra line with the mean of all others CPU will be added.
|
extra line with the mean of all others CPU will be added.
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ Example:
|
|||||||
|
|
||||||
**NOTE:** Setting low values for `public_refresh_interval` will result in frequent
|
**NOTE:** Setting low values for `public_refresh_interval` will result in frequent
|
||||||
HTTP requests to the onlive service defined in public_api. Recommended range: 120-600 seconds.
|
HTTP requests to the onlive service defined in public_api. Recommended range: 120-600 seconds.
|
||||||
Glances uses online services in order to get the IP addresses and the additional informations.
|
Glances uses online services in order to get the IP addresses and the additional information.
|
||||||
Your IP address could be blocked if too many requests are done.
|
Your IP address could be blocked if too many requests are done.
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ Trend Status
|
|||||||
======== ==============================================================
|
======== ==============================================================
|
||||||
``-`` Mean 15 lasts values equal mean 15 previous values
|
``-`` Mean 15 lasts values equal mean 15 previous values
|
||||||
``↓`` Mean 15 lasts values is lower mean 15 previous values
|
``↓`` Mean 15 lasts values is lower mean 15 previous values
|
||||||
``↑`` Mean 15 lasts values is higher mean 15 previous valuess
|
``↑`` Mean 15 lasts values is higher mean 15 previous values
|
||||||
======== ==============================================================
|
======== ==============================================================
|
||||||
|
|
||||||
Legend:
|
Legend:
|
||||||
|
@ -49,7 +49,7 @@ Trend Status
|
|||||||
======== ==============================================================
|
======== ==============================================================
|
||||||
``-`` Mean 15 lasts values equal mean 15 previous values
|
``-`` Mean 15 lasts values equal mean 15 previous values
|
||||||
``↓`` Mean 15 lasts values is lower mean 15 previous values
|
``↓`` Mean 15 lasts values is lower mean 15 previous values
|
||||||
``↑`` Mean 15 lasts values is higher mean 15 previous valuess
|
``↑`` Mean 15 lasts values is higher mean 15 previous values
|
||||||
======== ==============================================================
|
======== ==============================================================
|
||||||
|
|
||||||
Alerts are only set for used memory and used swap.
|
Alerts are only set for used memory and used swap.
|
||||||
|
@ -48,7 +48,7 @@ virtual docker interface (docker0, docker1, ...):
|
|||||||
# Automatically hide interface with no IP address (default is False)
|
# Automatically hide interface with no IP address (default is False)
|
||||||
hide_no_ip=True
|
hide_no_ip=True
|
||||||
# WLAN 0 alias
|
# WLAN 0 alias
|
||||||
wlan0_alias=Wireless IF
|
alias=wlan0:Wireless IF
|
||||||
# It is possible to overwrite the bitrate thresholds per interface
|
# It is possible to overwrite the bitrate thresholds per interface
|
||||||
# WLAN 0 Default limits (in bits per second aka bps) for interface bitrate
|
# WLAN 0 Default limits (in bits per second aka bps) for interface bitrate
|
||||||
wlan0_rx_careful=4000000
|
wlan0_rx_careful=4000000
|
||||||
@ -64,4 +64,4 @@ Filtering is based on regular expression. Please be sure that your regular
|
|||||||
expression works as expected. You can use an online tool like `regex101`_ in
|
expression works as expected. You can use an online tool like `regex101`_ in
|
||||||
order to test your regular expression.
|
order to test your regular expression.
|
||||||
|
|
||||||
.. _regex101: https://regex101.com/
|
.. _regex101: https://regex101.com/
|
||||||
|
@ -27,8 +27,7 @@ There is no alert on this information.
|
|||||||
.. note 3::
|
.. note 3::
|
||||||
If a sensors has temperature and fan speed with the same name unit,
|
If a sensors has temperature and fan speed with the same name unit,
|
||||||
it is possible to alias it using:
|
it is possible to alias it using:
|
||||||
unitname_temperature_core_alias=Alias for temp
|
alias=unitname_temperature_core_alias:Alias for temp,unitname_fan_speed_alias:Alias for fan speed
|
||||||
unitname_fan_speed_alias=Alias for fan speed
|
|
||||||
|
|
||||||
.. note 4::
|
.. note 4::
|
||||||
If a sensors has multiple identical features names (see #2280), then
|
If a sensors has multiple identical features names (see #2280), then
|
||||||
|
353
docs/api.rst
353
docs/api.rst
@ -141,7 +141,7 @@ Get plugin stats::
|
|||||||
"refresh": 3.0,
|
"refresh": 3.0,
|
||||||
"regex": True,
|
"regex": True,
|
||||||
"result": None,
|
"result": None,
|
||||||
"timer": 0.34838008880615234},
|
"timer": 0.2482151985168457},
|
||||||
{"count": 0,
|
{"count": 0,
|
||||||
"countmax": 20.0,
|
"countmax": 20.0,
|
||||||
"countmin": None,
|
"countmin": None,
|
||||||
@ -150,7 +150,7 @@ Get plugin stats::
|
|||||||
"refresh": 3.0,
|
"refresh": 3.0,
|
||||||
"regex": True,
|
"regex": True,
|
||||||
"result": None,
|
"result": None,
|
||||||
"timer": 0.348278284072876}]
|
"timer": 0.24815130233764648}]
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ Get a specific item when field matches the given value::
|
|||||||
"refresh": 3.0,
|
"refresh": 3.0,
|
||||||
"regex": True,
|
"regex": True,
|
||||||
"result": None,
|
"result": None,
|
||||||
"timer": 0.34838008880615234}]}
|
"timer": 0.2482151985168457}]}
|
||||||
|
|
||||||
GET cloud
|
GET cloud
|
||||||
---------
|
---------
|
||||||
@ -265,19 +265,19 @@ Get plugin stats::
|
|||||||
|
|
||||||
# curl http://localhost:61208/api/4/cpu
|
# curl http://localhost:61208/api/4/cpu
|
||||||
{"cpucore": 16,
|
{"cpucore": 16,
|
||||||
"ctx_switches": 385434943,
|
"ctx_switches": 493080568,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 86.5,
|
||||||
"interrupts": 330921576,
|
"interrupts": 420997918,
|
||||||
"iowait": 0.0,
|
"iowait": 0.5,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"nice": 0.0,
|
"nice": 0.0,
|
||||||
"soft_interrupts": 117854827,
|
"soft_interrupts": 155707720,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"syscalls": 0,
|
"syscalls": 0,
|
||||||
"system": 0.0,
|
"system": 3.5,
|
||||||
"total": 0.0,
|
"total": 12.9,
|
||||||
"user": 0.0}
|
"user": 9.4}
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ Fields descriptions:
|
|||||||
Get a specific field::
|
Get a specific field::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/cpu/total
|
# curl http://localhost:61208/api/4/cpu/total
|
||||||
{"total": 0.0}
|
{"total": 12.9}
|
||||||
|
|
||||||
GET diskio
|
GET diskio
|
||||||
----------
|
----------
|
||||||
@ -320,14 +320,14 @@ Get plugin stats::
|
|||||||
# curl http://localhost:61208/api/4/diskio
|
# curl http://localhost:61208/api/4/diskio
|
||||||
[{"disk_name": "nvme0n1",
|
[{"disk_name": "nvme0n1",
|
||||||
"key": "disk_name",
|
"key": "disk_name",
|
||||||
"read_bytes": 5188239872,
|
"read_bytes": 10167291392,
|
||||||
"read_count": 215068,
|
"read_count": 391026,
|
||||||
"write_bytes": 19667686400,
|
"write_bytes": 31230641152,
|
||||||
"write_count": 1131877},
|
"write_count": 1527146},
|
||||||
{"disk_name": "nvme0n1p1",
|
{"disk_name": "nvme0n1p1",
|
||||||
"key": "disk_name",
|
"key": "disk_name",
|
||||||
"read_bytes": 8869888,
|
"read_bytes": 7558144,
|
||||||
"read_count": 834,
|
"read_count": 605,
|
||||||
"write_bytes": 1024,
|
"write_bytes": 1024,
|
||||||
"write_count": 2}]
|
"write_count": 2}]
|
||||||
|
|
||||||
@ -363,10 +363,10 @@ Get a specific item when field matches the given value::
|
|||||||
# curl http://localhost:61208/api/4/diskio/disk_name/nvme0n1
|
# curl http://localhost:61208/api/4/diskio/disk_name/nvme0n1
|
||||||
{"nvme0n1": [{"disk_name": "nvme0n1",
|
{"nvme0n1": [{"disk_name": "nvme0n1",
|
||||||
"key": "disk_name",
|
"key": "disk_name",
|
||||||
"read_bytes": 5188239872,
|
"read_bytes": 10167291392,
|
||||||
"read_count": 215068,
|
"read_count": 391026,
|
||||||
"write_bytes": 19667686400,
|
"write_bytes": 31230641152,
|
||||||
"write_count": 1131877}]}
|
"write_count": 1527146}]}
|
||||||
|
|
||||||
GET folders
|
GET folders
|
||||||
-----------
|
-----------
|
||||||
@ -393,13 +393,13 @@ Get plugin stats::
|
|||||||
|
|
||||||
# curl http://localhost:61208/api/4/fs
|
# curl http://localhost:61208/api/4/fs
|
||||||
[{"device_name": "/dev/mapper/ubuntu--vg-ubuntu--lv",
|
[{"device_name": "/dev/mapper/ubuntu--vg-ubuntu--lv",
|
||||||
"free": 904171712512,
|
"free": 897378041856,
|
||||||
"fs_type": "ext4",
|
"fs_type": "ext4",
|
||||||
"key": "mnt_point",
|
"key": "mnt_point",
|
||||||
"mnt_point": "/",
|
"mnt_point": "/",
|
||||||
"percent": 5.1,
|
"percent": 5.8,
|
||||||
"size": 1003736440832,
|
"size": 1003736440832,
|
||||||
"used": 48502222848}]
|
"used": 55295893504}]
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -420,13 +420,13 @@ Get a specific item when field matches the given value::
|
|||||||
|
|
||||||
# curl http://localhost:61208/api/4/fs/mnt_point//
|
# curl http://localhost:61208/api/4/fs/mnt_point//
|
||||||
{"/": [{"device_name": "/dev/mapper/ubuntu--vg-ubuntu--lv",
|
{"/": [{"device_name": "/dev/mapper/ubuntu--vg-ubuntu--lv",
|
||||||
"free": 904171712512,
|
"free": 897378041856,
|
||||||
"fs_type": "ext4",
|
"fs_type": "ext4",
|
||||||
"key": "mnt_point",
|
"key": "mnt_point",
|
||||||
"mnt_point": "/",
|
"mnt_point": "/",
|
||||||
"percent": 5.1,
|
"percent": 5.8,
|
||||||
"size": 1003736440832,
|
"size": 1003736440832,
|
||||||
"used": 48502222848}]}
|
"used": 55295893504}]}
|
||||||
|
|
||||||
GET gpu
|
GET gpu
|
||||||
-------
|
-------
|
||||||
@ -500,9 +500,9 @@ Get plugin stats::
|
|||||||
|
|
||||||
# curl http://localhost:61208/api/4/load
|
# curl http://localhost:61208/api/4/load
|
||||||
{"cpucore": 16,
|
{"cpucore": 16,
|
||||||
"min1": 1.5205078125,
|
"min1": 0.40185546875,
|
||||||
"min15": 0.82275390625,
|
"min15": 0.587890625,
|
||||||
"min5": 1.09228515625}
|
"min5": 0.638671875}
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -514,7 +514,7 @@ Fields descriptions:
|
|||||||
Get a specific field::
|
Get a specific field::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/load/min1
|
# curl http://localhost:61208/api/4/load/min1
|
||||||
{"min1": 1.5205078125}
|
{"min1": 0.40185546875}
|
||||||
|
|
||||||
GET mem
|
GET mem
|
||||||
-------
|
-------
|
||||||
@ -522,16 +522,16 @@ GET mem
|
|||||||
Get plugin stats::
|
Get plugin stats::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/mem
|
# curl http://localhost:61208/api/4/mem
|
||||||
{"active": 8721498112,
|
{"active": 5094199296,
|
||||||
"available": 7341674496,
|
"available": 10908983296,
|
||||||
"buffers": 416690176,
|
"buffers": 180162560,
|
||||||
"cached": 7607521280,
|
"cached": 5800796160,
|
||||||
"free": 7341674496,
|
"free": 10908983296,
|
||||||
"inactive": 4933640192,
|
"inactive": 3735175168,
|
||||||
"percent": 55.3,
|
"percent": 33.6,
|
||||||
"shared": 1056010240,
|
"shared": 622718976,
|
||||||
"total": 16422486016,
|
"total": 16422486016,
|
||||||
"used": 9080811520}
|
"used": 5513502720}
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -558,13 +558,13 @@ GET memswap
|
|||||||
Get plugin stats::
|
Get plugin stats::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/memswap
|
# curl http://localhost:61208/api/4/memswap
|
||||||
{"free": 4293390336,
|
{"free": 3836997632,
|
||||||
"percent": 0.0,
|
"percent": 10.7,
|
||||||
"sin": 0,
|
"sin": 186925056,
|
||||||
"sout": 126976,
|
"sout": 1518604288,
|
||||||
"time_since_update": 1,
|
"time_since_update": 1,
|
||||||
"total": 4294963200,
|
"total": 4294963200,
|
||||||
"used": 1572864}
|
"used": 457965568}
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -589,15 +589,15 @@ Get plugin stats::
|
|||||||
# curl http://localhost:61208/api/4/network
|
# curl http://localhost:61208/api/4/network
|
||||||
[{"alias": None,
|
[{"alias": None,
|
||||||
"bytes_all": 0,
|
"bytes_all": 0,
|
||||||
"bytes_all_gauge": 4462887866,
|
"bytes_all_gauge": 6286191015,
|
||||||
"bytes_recv": 0,
|
"bytes_recv": 0,
|
||||||
"bytes_recv_gauge": 4049401085,
|
"bytes_recv_gauge": 5977645732,
|
||||||
"bytes_sent": 0,
|
"bytes_sent": 0,
|
||||||
"bytes_sent_gauge": 413486781,
|
"bytes_sent_gauge": 308545283,
|
||||||
"interface_name": "wlp0s20f3",
|
"interface_name": "wlp0s20f3",
|
||||||
"key": "interface_name",
|
"key": "interface_name",
|
||||||
"speed": 0,
|
"speed": 0,
|
||||||
"time_since_update": 0.3545956611633301}]
|
"time_since_update": 0.2501566410064697}]
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -626,15 +626,15 @@ Get a specific item when field matches the given value::
|
|||||||
# curl http://localhost:61208/api/4/network/interface_name/wlp0s20f3
|
# curl http://localhost:61208/api/4/network/interface_name/wlp0s20f3
|
||||||
{"wlp0s20f3": [{"alias": None,
|
{"wlp0s20f3": [{"alias": None,
|
||||||
"bytes_all": 0,
|
"bytes_all": 0,
|
||||||
"bytes_all_gauge": 4462887866,
|
"bytes_all_gauge": 6286191015,
|
||||||
"bytes_recv": 0,
|
"bytes_recv": 0,
|
||||||
"bytes_recv_gauge": 4049401085,
|
"bytes_recv_gauge": 5977645732,
|
||||||
"bytes_sent": 0,
|
"bytes_sent": 0,
|
||||||
"bytes_sent_gauge": 413486781,
|
"bytes_sent_gauge": 308545283,
|
||||||
"interface_name": "wlp0s20f3",
|
"interface_name": "wlp0s20f3",
|
||||||
"key": "interface_name",
|
"key": "interface_name",
|
||||||
"speed": 0,
|
"speed": 0,
|
||||||
"time_since_update": 0.3545956611633301}]}
|
"time_since_update": 0.2501566410064697}]}
|
||||||
|
|
||||||
GET now
|
GET now
|
||||||
-------
|
-------
|
||||||
@ -642,7 +642,7 @@ GET now
|
|||||||
Get plugin stats::
|
Get plugin stats::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/now
|
# curl http://localhost:61208/api/4/now
|
||||||
{"custom": "2024-06-01 18:28:14 CEST", "iso": "2024-06-01T18:28:14+02:00"}
|
{"custom": "2024-06-29 19:17:41 CEST", "iso": "2024-06-29T19:17:41+02:00"}
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -652,7 +652,7 @@ Fields descriptions:
|
|||||||
Get a specific field::
|
Get a specific field::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/now/iso
|
# curl http://localhost:61208/api/4/now/iso
|
||||||
{"iso": "2024-06-01T18:28:14+02:00"}
|
{"iso": "2024-06-29T19:17:41+02:00"}
|
||||||
|
|
||||||
GET percpu
|
GET percpu
|
||||||
----------
|
----------
|
||||||
@ -663,7 +663,7 @@ Get plugin stats::
|
|||||||
[{"cpu_number": 0,
|
[{"cpu_number": 0,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 1.0,
|
"idle": 21.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -671,12 +671,12 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 99.0,
|
"total": 79.0,
|
||||||
"user": 0.0},
|
"user": 1.0},
|
||||||
{"cpu_number": 1,
|
{"cpu_number": 1,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 23.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -684,7 +684,7 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 77.0,
|
||||||
"user": 0.0}]
|
"user": 0.0}]
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
@ -719,7 +719,7 @@ Get plugin stats::
|
|||||||
"port": 0,
|
"port": 0,
|
||||||
"refresh": 30,
|
"refresh": 30,
|
||||||
"rtt_warning": None,
|
"rtt_warning": None,
|
||||||
"status": 0.006269,
|
"status": 0.006275,
|
||||||
"timeout": 3}]
|
"timeout": 3}]
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
@ -747,7 +747,7 @@ Get a specific item when field matches the given value::
|
|||||||
"port": 0,
|
"port": 0,
|
||||||
"refresh": 30,
|
"refresh": 30,
|
||||||
"rtt_warning": None,
|
"rtt_warning": None,
|
||||||
"status": 0.006269,
|
"status": 0.006275,
|
||||||
"timeout": 3}]}
|
"timeout": 3}]}
|
||||||
|
|
||||||
GET processcount
|
GET processcount
|
||||||
@ -756,7 +756,7 @@ GET processcount
|
|||||||
Get plugin stats::
|
Get plugin stats::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/processcount
|
# curl http://localhost:61208/api/4/processcount
|
||||||
{"pid_max": 0, "running": 0, "sleeping": 290, "thread": 1660, "total": 425}
|
{"pid_max": 0, "running": 2, "sleeping": 277, "thread": 1508, "total": 412}
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -769,7 +769,7 @@ Fields descriptions:
|
|||||||
Get a specific field::
|
Get a specific field::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/processcount/total
|
# curl http://localhost:61208/api/4/processcount/total
|
||||||
{"total": 425}
|
{"total": 412}
|
||||||
|
|
||||||
GET processlist
|
GET processlist
|
||||||
---------------
|
---------------
|
||||||
@ -777,7 +777,78 @@ GET processlist
|
|||||||
Get plugin stats::
|
Get plugin stats::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/processlist
|
# curl http://localhost:61208/api/4/processlist
|
||||||
[]
|
[{"cmdline": ["/snap/firefox/4336/usr/lib/firefox/firefox"],
|
||||||
|
"cpu_percent": 0.0,
|
||||||
|
"cpu_times": {"children_system": 3.08,
|
||||||
|
"children_user": 3.33,
|
||||||
|
"iowait": 0.0,
|
||||||
|
"system": 13.75,
|
||||||
|
"user": 34.7},
|
||||||
|
"gids": {"effective": 1000, "real": 1000, "saved": 1000},
|
||||||
|
"io_counters": [393136128, 195969024, 0, 0, 0],
|
||||||
|
"key": "pid",
|
||||||
|
"memory_info": {"data": 681967616,
|
||||||
|
"dirty": 0,
|
||||||
|
"lib": 0,
|
||||||
|
"rss": 443969536,
|
||||||
|
"shared": 222199808,
|
||||||
|
"text": 987136,
|
||||||
|
"vms": 3721211904},
|
||||||
|
"memory_percent": 2.7034246554842674,
|
||||||
|
"name": "firefox",
|
||||||
|
"nice": 0,
|
||||||
|
"num_threads": 120,
|
||||||
|
"pid": 793506,
|
||||||
|
"status": "S",
|
||||||
|
"time_since_update": 1,
|
||||||
|
"username": "nicolargo"},
|
||||||
|
{"cmdline": ["/snap/firefox/4336/usr/lib/firefox/firefox",
|
||||||
|
"-contentproc",
|
||||||
|
"-childID",
|
||||||
|
"2",
|
||||||
|
"-isForBrowser",
|
||||||
|
"-prefsLen",
|
||||||
|
"28218",
|
||||||
|
"-prefMapSize",
|
||||||
|
"244440",
|
||||||
|
"-jsInitLen",
|
||||||
|
"231800",
|
||||||
|
"-parentBuildID",
|
||||||
|
"20240527194810",
|
||||||
|
"-greomni",
|
||||||
|
"/snap/firefox/4336/usr/lib/firefox/omni.ja",
|
||||||
|
"-appomni",
|
||||||
|
"/snap/firefox/4336/usr/lib/firefox/browser/omni.ja",
|
||||||
|
"-appDir",
|
||||||
|
"/snap/firefox/4336/usr/lib/firefox/browser",
|
||||||
|
"{bc853380-6b8f-46ad-afe0-9da5ba832e62}",
|
||||||
|
"793506",
|
||||||
|
"true",
|
||||||
|
"tab"],
|
||||||
|
"cpu_percent": 0.0,
|
||||||
|
"cpu_times": {"children_system": 0.0,
|
||||||
|
"children_user": 0.0,
|
||||||
|
"iowait": 0.0,
|
||||||
|
"system": 2.54,
|
||||||
|
"user": 19.25},
|
||||||
|
"gids": {"effective": 1000, "real": 1000, "saved": 1000},
|
||||||
|
"io_counters": [1827840, 0, 0, 0, 0],
|
||||||
|
"key": "pid",
|
||||||
|
"memory_info": {"data": 412688384,
|
||||||
|
"dirty": 0,
|
||||||
|
"lib": 0,
|
||||||
|
"rss": 440922112,
|
||||||
|
"shared": 111878144,
|
||||||
|
"text": 987136,
|
||||||
|
"vms": 2946224128},
|
||||||
|
"memory_percent": 2.684868244493684,
|
||||||
|
"name": "Isolated Web Co",
|
||||||
|
"nice": 0,
|
||||||
|
"num_threads": 28,
|
||||||
|
"pid": 793778,
|
||||||
|
"status": "S",
|
||||||
|
"time_since_update": 1,
|
||||||
|
"username": "nicolargo"}]
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -801,7 +872,7 @@ GET psutilversion
|
|||||||
Get plugin stats::
|
Get plugin stats::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/psutilversion
|
# curl http://localhost:61208/api/4/psutilversion
|
||||||
"5.9.8"
|
"6.0.0"
|
||||||
|
|
||||||
GET quicklook
|
GET quicklook
|
||||||
-------------
|
-------------
|
||||||
@ -809,18 +880,18 @@ GET quicklook
|
|||||||
Get plugin stats::
|
Get plugin stats::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/quicklook
|
# curl http://localhost:61208/api/4/quicklook
|
||||||
{"cpu": 0.0,
|
{"cpu": 12.9,
|
||||||
"cpu_hz": 4475000000.0,
|
"cpu_hz": 4475000000.0,
|
||||||
"cpu_hz_current": 1456909124.9999998,
|
"cpu_hz_current": 1666410624.9999998,
|
||||||
"cpu_log_core": 16,
|
"cpu_log_core": 16,
|
||||||
"cpu_name": "13th Gen Intel(R) Core(TM) i7-13620H",
|
"cpu_name": "13th Gen Intel(R) Core(TM) i7-13620H",
|
||||||
"cpu_phys_core": 10,
|
"cpu_phys_core": 10,
|
||||||
"load": 5.1,
|
"load": 3.7,
|
||||||
"mem": 55.3,
|
"mem": 33.6,
|
||||||
"percpu": [{"cpu_number": 0,
|
"percpu": [{"cpu_number": 0,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 1.0,
|
"idle": 21.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -828,12 +899,12 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 99.0,
|
"total": 79.0,
|
||||||
"user": 0.0},
|
"user": 1.0},
|
||||||
{"cpu_number": 1,
|
{"cpu_number": 1,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 23.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -841,25 +912,25 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 77.0,
|
||||||
"user": 0.0},
|
"user": 0.0},
|
||||||
{"cpu_number": 2,
|
{"cpu_number": 2,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 1.0,
|
"idle": 18.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
"nice": 0.0,
|
"nice": 0.0,
|
||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 1.0,
|
||||||
"total": 99.0,
|
"total": 82.0,
|
||||||
"user": 0.0},
|
"user": 5.0},
|
||||||
{"cpu_number": 3,
|
{"cpu_number": 3,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 22.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -867,25 +938,25 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 78.0,
|
||||||
"user": 0.0},
|
"user": 0.0},
|
||||||
{"cpu_number": 4,
|
{"cpu_number": 4,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 1.0,
|
"idle": 8.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
"nice": 0.0,
|
"nice": 0.0,
|
||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 1.0,
|
||||||
"total": 99.0,
|
"total": 92.0,
|
||||||
"user": 0.0},
|
"user": 14.0},
|
||||||
{"cpu_number": 5,
|
{"cpu_number": 5,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 23.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -893,64 +964,64 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 77.0,
|
||||||
"user": 0.0},
|
"user": 0.0},
|
||||||
{"cpu_number": 6,
|
{"cpu_number": 6,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 3.0,
|
||||||
"iowait": 0.0,
|
"iowait": 1.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
"nice": 0.0,
|
"nice": 0.0,
|
||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 4.0,
|
||||||
"total": 100.0,
|
"total": 97.0,
|
||||||
"user": 0.0},
|
"user": 15.0},
|
||||||
{"cpu_number": 7,
|
{"cpu_number": 7,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 1.0,
|
"idle": 23.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
"nice": 0.0,
|
"nice": 0.0,
|
||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 1.0,
|
||||||
"total": 99.0,
|
"total": 77.0,
|
||||||
"user": 0.0},
|
"user": 0.0},
|
||||||
{"cpu_number": 8,
|
{"cpu_number": 8,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 19.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
"nice": 0.0,
|
"nice": 0.0,
|
||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 1.0,
|
||||||
"total": 100.0,
|
"total": 81.0,
|
||||||
"user": 0.0},
|
"user": 3.0},
|
||||||
{"cpu_number": 9,
|
{"cpu_number": 9,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 22.0,
|
||||||
"iowait": 0.0,
|
"iowait": 1.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
"nice": 0.0,
|
"nice": 0.0,
|
||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 78.0,
|
||||||
"user": 0.0},
|
"user": 0.0},
|
||||||
{"cpu_number": 10,
|
{"cpu_number": 10,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 22.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -958,12 +1029,12 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 78.0,
|
||||||
"user": 0.0},
|
"user": 0.0},
|
||||||
{"cpu_number": 11,
|
{"cpu_number": 11,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 23.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -971,25 +1042,25 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 77.0,
|
||||||
"user": 0.0},
|
"user": 0.0},
|
||||||
{"cpu_number": 12,
|
{"cpu_number": 12,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 21.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
"nice": 0.0,
|
"nice": 0.0,
|
||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 1.0,
|
||||||
"total": 100.0,
|
"total": 79.0,
|
||||||
"user": 0.0},
|
"user": 1.0},
|
||||||
{"cpu_number": 13,
|
{"cpu_number": 13,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 23.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -997,12 +1068,12 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 77.0,
|
||||||
"user": 0.0},
|
"user": 0.0},
|
||||||
{"cpu_number": 14,
|
{"cpu_number": 14,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 22.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -1010,12 +1081,12 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 78.0,
|
||||||
"user": 0.0},
|
"user": 0.0},
|
||||||
{"cpu_number": 15,
|
{"cpu_number": 15,
|
||||||
"guest": 0.0,
|
"guest": 0.0,
|
||||||
"guest_nice": 0.0,
|
"guest_nice": 0.0,
|
||||||
"idle": 0.0,
|
"idle": 22.0,
|
||||||
"iowait": 0.0,
|
"iowait": 0.0,
|
||||||
"irq": 0.0,
|
"irq": 0.0,
|
||||||
"key": "cpu_number",
|
"key": "cpu_number",
|
||||||
@ -1023,9 +1094,9 @@ Get plugin stats::
|
|||||||
"softirq": 0.0,
|
"softirq": 0.0,
|
||||||
"steal": 0.0,
|
"steal": 0.0,
|
||||||
"system": 0.0,
|
"system": 0.0,
|
||||||
"total": 100.0,
|
"total": 78.0,
|
||||||
"user": 0.0}],
|
"user": 0.0}],
|
||||||
"swap": 0.0}
|
"swap": 10.7}
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
|
|
||||||
@ -1063,14 +1134,14 @@ Get plugin stats::
|
|||||||
"label": "Ambient",
|
"label": "Ambient",
|
||||||
"type": "temperature_core",
|
"type": "temperature_core",
|
||||||
"unit": "C",
|
"unit": "C",
|
||||||
"value": 35,
|
"value": 39,
|
||||||
"warning": 0},
|
"warning": 0},
|
||||||
{"critical": None,
|
{"critical": None,
|
||||||
"key": "label",
|
"key": "label",
|
||||||
"label": "Ambient 3",
|
"label": "Ambient 3",
|
||||||
"type": "temperature_core",
|
"type": "temperature_core",
|
||||||
"unit": "C",
|
"unit": "C",
|
||||||
"value": 30,
|
"value": 32,
|
||||||
"warning": 0}]
|
"warning": 0}]
|
||||||
|
|
||||||
Fields descriptions:
|
Fields descriptions:
|
||||||
@ -1131,7 +1202,7 @@ Get a specific item when field matches the given value::
|
|||||||
"label": "Ambient",
|
"label": "Ambient",
|
||||||
"type": "temperature_core",
|
"type": "temperature_core",
|
||||||
"unit": "C",
|
"unit": "C",
|
||||||
"value": 35,
|
"value": 39,
|
||||||
"warning": 0}]}
|
"warning": 0}]}
|
||||||
|
|
||||||
GET smart
|
GET smart
|
||||||
@ -1162,7 +1233,7 @@ Fields descriptions:
|
|||||||
* **platform**: Platform (32 or 64 bits) (unit is *None*)
|
* **platform**: Platform (32 or 64 bits) (unit is *None*)
|
||||||
* **linux_distro**: Linux distribution (unit is *None*)
|
* **linux_distro**: Linux distribution (unit is *None*)
|
||||||
* **os_version**: Operating system version (unit is *None*)
|
* **os_version**: Operating system version (unit is *None*)
|
||||||
* **hr_name**: Human readable operating sytem name (unit is *None*)
|
* **hr_name**: Human readable operating system name (unit is *None*)
|
||||||
|
|
||||||
Get a specific field::
|
Get a specific field::
|
||||||
|
|
||||||
@ -1175,7 +1246,7 @@ GET uptime
|
|||||||
Get plugin stats::
|
Get plugin stats::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/uptime
|
# curl http://localhost:61208/api/4/uptime
|
||||||
"18 days, 19:20:46"
|
"20 days, 2:20:27"
|
||||||
|
|
||||||
GET version
|
GET version
|
||||||
-----------
|
-----------
|
||||||
@ -1183,7 +1254,7 @@ GET version
|
|||||||
Get plugin stats::
|
Get plugin stats::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/version
|
# curl http://localhost:61208/api/4/version
|
||||||
"4.1.0_beta01"
|
"4.2.0_beta01"
|
||||||
|
|
||||||
GET wifi
|
GET wifi
|
||||||
--------
|
--------
|
||||||
@ -1251,34 +1322,34 @@ GET stats history
|
|||||||
History of a plugin::
|
History of a plugin::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/cpu/history
|
# curl http://localhost:61208/api/4/cpu/history
|
||||||
{"system": [["2024-06-01T18:28:15.830521", 0.0],
|
{"system": [["2024-06-29T19:17:42.396270", 3.5],
|
||||||
["2024-06-01T18:28:16.865265", 0.0],
|
["2024-06-29T19:17:43.447397", 0.7],
|
||||||
["2024-06-01T18:28:17.937644", 0.0]],
|
["2024-06-29T19:17:44.455830", 0.7]],
|
||||||
"user": [["2024-06-01T18:28:15.830511", 0.0],
|
"user": [["2024-06-29T19:17:42.396268", 9.4],
|
||||||
["2024-06-01T18:28:16.865259", 0.0],
|
["2024-06-29T19:17:43.447396", 4.0],
|
||||||
["2024-06-01T18:28:17.937634", 0.0]]}
|
["2024-06-29T19:17:44.455825", 4.0]]}
|
||||||
|
|
||||||
Limit history to last 2 values::
|
Limit history to last 2 values::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/cpu/history/2
|
# curl http://localhost:61208/api/4/cpu/history/2
|
||||||
{"system": [["2024-06-01T18:28:16.865265", 0.0],
|
{"system": [["2024-06-29T19:17:43.447397", 0.7],
|
||||||
["2024-06-01T18:28:17.937644", 0.0]],
|
["2024-06-29T19:17:44.455830", 0.7]],
|
||||||
"user": [["2024-06-01T18:28:16.865259", 0.0],
|
"user": [["2024-06-29T19:17:43.447396", 4.0],
|
||||||
["2024-06-01T18:28:17.937634", 0.0]]}
|
["2024-06-29T19:17:44.455825", 4.0]]}
|
||||||
|
|
||||||
History for a specific field::
|
History for a specific field::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/cpu/system/history
|
# curl http://localhost:61208/api/4/cpu/system/history
|
||||||
{"system": [["2024-06-01T18:28:14.644798", 0.0],
|
{"system": [["2024-06-29T19:17:41.318736", 3.5],
|
||||||
["2024-06-01T18:28:15.830521", 0.0],
|
["2024-06-29T19:17:42.396270", 3.5],
|
||||||
["2024-06-01T18:28:16.865265", 0.0],
|
["2024-06-29T19:17:43.447397", 0.7],
|
||||||
["2024-06-01T18:28:17.937644", 0.0]]}
|
["2024-06-29T19:17:44.455830", 0.7]]}
|
||||||
|
|
||||||
Limit history for a specific field to last 2 values::
|
Limit history for a specific field to last 2 values::
|
||||||
|
|
||||||
# curl http://localhost:61208/api/4/cpu/system/history
|
# curl http://localhost:61208/api/4/cpu/system/history
|
||||||
{"system": [["2024-06-01T18:28:16.865265", 0.0],
|
{"system": [["2024-06-29T19:17:43.447397", 0.7],
|
||||||
["2024-06-01T18:28:17.937644", 0.0]]}
|
["2024-06-29T19:17:44.455830", 0.7]]}
|
||||||
|
|
||||||
GET limits (used for thresholds)
|
GET limits (used for thresholds)
|
||||||
--------------------------------
|
--------------------------------
|
||||||
@ -1363,6 +1434,8 @@ All limits/thresholds::
|
|||||||
"network": {"history_size": 1200.0,
|
"network": {"history_size": 1200.0,
|
||||||
"network_disable": ["False"],
|
"network_disable": ["False"],
|
||||||
"network_hide": ["docker.*", "lo"],
|
"network_hide": ["docker.*", "lo"],
|
||||||
|
"network_hide_no_ip": ["True"],
|
||||||
|
"network_hide_no_up": ["True"],
|
||||||
"network_rx_careful": 70.0,
|
"network_rx_careful": 70.0,
|
||||||
"network_rx_critical": 90.0,
|
"network_rx_critical": 90.0,
|
||||||
"network_rx_warning": 80.0,
|
"network_rx_warning": 80.0,
|
||||||
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||||
..
|
..
|
||||||
.TH "GLANCES" "1" "Jun 01, 2024" "4.1.0_beta01" "Glances"
|
.TH "GLANCES" "1" "Jun 29, 2024" "4.2.0_beta01" "Glances"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
glances \- An eye on your system
|
glances \- An eye on your system
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -19,7 +19,7 @@ import tracemalloc
|
|||||||
# Global name
|
# Global name
|
||||||
# Version should start and end with a numerical char
|
# Version should start and end with a numerical char
|
||||||
# See https://packaging.python.org/specifications/core-metadata/#version
|
# See https://packaging.python.org/specifications/core-metadata/#version
|
||||||
__version__ = '4.1.0_beta02'
|
__version__ = '4.2.0_beta01'
|
||||||
__apiversion__ = '4'
|
__apiversion__ = '4'
|
||||||
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
|
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
|
||||||
__license__ = 'LGPLv3'
|
__license__ = 'LGPLv3'
|
||||||
@ -55,7 +55,7 @@ if psutil_version_info < psutil_min_version:
|
|||||||
|
|
||||||
|
|
||||||
def __signal_handler(signal, frame):
|
def __signal_handler(signal, frame):
|
||||||
logger.debug(f"Signal {signal} catched")
|
logger.debug(f"Signal {signal} caught")
|
||||||
end()
|
end()
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,12 +95,16 @@ class GlancesClientBrowser:
|
|||||||
# Mandatory stats
|
# Mandatory stats
|
||||||
try:
|
try:
|
||||||
# CPU%
|
# CPU%
|
||||||
cpu_percent = 100 - orjson.loads(s.getPlugin('cpu'))['idle']
|
# logger.info(f"CPU stats {s.getPlugin('cpu')}")
|
||||||
server['cpu_percent'] = f'{cpu_percent:.1f}'
|
# logger.info(f"CPU views {s.getPluginView('cpu')}")
|
||||||
|
server['cpu_percent'] = orjson.loads(s.getPlugin('cpu'))['total']
|
||||||
|
server['cpu_percent_decoration'] = orjson.loads(s.getPluginView('cpu'))['total']['decoration']
|
||||||
# MEM%
|
# MEM%
|
||||||
server['mem_percent'] = orjson.loads(s.getPlugin('mem'))['percent']
|
server['mem_percent'] = orjson.loads(s.getPlugin('mem'))['percent']
|
||||||
|
server['mem_percent_decoration'] = orjson.loads(s.getPluginView('mem'))['percent']['decoration']
|
||||||
# OS (Human Readable name)
|
# OS (Human Readable name)
|
||||||
server['hr_name'] = orjson.loads(s.getPlugin('system'))['hr_name']
|
server['hr_name'] = orjson.loads(s.getPlugin('system'))['hr_name']
|
||||||
|
server['hr_name_decoration'] = 'DEFAULT'
|
||||||
except (OSError, Fault, KeyError) as e:
|
except (OSError, Fault, KeyError) as e:
|
||||||
logger.debug(f"Error while grabbing stats form server ({e})")
|
logger.debug(f"Error while grabbing stats form server ({e})")
|
||||||
server['status'] = 'OFFLINE'
|
server['status'] = 'OFFLINE'
|
||||||
@ -120,8 +124,8 @@ class GlancesClientBrowser:
|
|||||||
# Optional stats (load is not available on Windows OS)
|
# Optional stats (load is not available on Windows OS)
|
||||||
try:
|
try:
|
||||||
# LOAD
|
# LOAD
|
||||||
load_min5 = orjson.loads(s.getPlugin('load'))['min5']
|
server['load_min5'] = round(orjson.loads(s.getPlugin('load'))['min5'], 1)
|
||||||
server['load_min5'] = f'{load_min5:.2f}'
|
server['load_min5_decoration'] = orjson.loads(s.getPluginView('load'))['min5']['decoration']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Error while grabbing stats form server ({e})")
|
logger.warning(f"Error while grabbing stats form server ({e})")
|
||||||
|
|
||||||
|
@ -8,46 +8,68 @@
|
|||||||
|
|
||||||
"""CPU percent stats shared between CPU and Quicklook plugins."""
|
"""CPU percent stats shared between CPU and Quicklook plugins."""
|
||||||
|
|
||||||
|
from typing import List, Optional, TypedDict
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
from glances.logger import logger
|
from glances.logger import logger
|
||||||
from glances.timer import Timer
|
from glances.timer import Timer
|
||||||
|
|
||||||
|
__all__ = ["cpu_percent"]
|
||||||
|
|
||||||
|
|
||||||
|
class CpuInfo(TypedDict):
|
||||||
|
cpu_name: str
|
||||||
|
cpu_hz: Optional[float]
|
||||||
|
cpu_hz_current: Optional[float]
|
||||||
|
|
||||||
|
|
||||||
|
class PerCpuPercentInfo(TypedDict):
|
||||||
|
key: str
|
||||||
|
cpu_number: int
|
||||||
|
total: float
|
||||||
|
user: float
|
||||||
|
system: float
|
||||||
|
idle: float
|
||||||
|
nice: Optional[float]
|
||||||
|
iowait: Optional[float]
|
||||||
|
irq: Optional[float]
|
||||||
|
softirq: Optional[float]
|
||||||
|
steal: Optional[float]
|
||||||
|
guest: Optional[float]
|
||||||
|
guest_nice: Optional[float]
|
||||||
|
dpc: Optional[float]
|
||||||
|
interrupt: Optional[float]
|
||||||
|
|
||||||
|
|
||||||
class CpuPercent:
|
class CpuPercent:
|
||||||
"""Get and store the CPU percent."""
|
"""Get and store the CPU percent."""
|
||||||
|
|
||||||
def __init__(self, cached_timer_cpu=3):
|
def __init__(self, cached_timer_cpu: int = 2):
|
||||||
self.cpu_info = {'cpu_name': None, 'cpu_hz_current': None, 'cpu_hz': None}
|
|
||||||
self.cpu_percent = 0
|
|
||||||
self.percpu_percent = []
|
|
||||||
|
|
||||||
# Get CPU name
|
|
||||||
self.cpu_info['cpu_name'] = self.__get_cpu_name()
|
|
||||||
|
|
||||||
# cached_timer_cpu is the minimum time interval between stats updates
|
# cached_timer_cpu is the minimum time interval between stats updates
|
||||||
# since last update is passed (will retrieve old cached info instead)
|
# since last update is passed (will retrieve old cached info instead)
|
||||||
self.cached_timer_cpu = cached_timer_cpu
|
self.cached_timer_cpu = cached_timer_cpu
|
||||||
self.timer_cpu = Timer(0)
|
|
||||||
self.timer_percpu = Timer(0)
|
|
||||||
|
|
||||||
# psutil.cpu_freq() consumes lots of CPU
|
# psutil.cpu_freq() consumes lots of CPU
|
||||||
# So refresh the stats every refresh*2 (6 seconds)
|
# So refresh CPU frequency stats every refresh * 2
|
||||||
self.cached_timer_cpu_info = cached_timer_cpu * 2
|
self.cached_timer_cpu_info = cached_timer_cpu * 2
|
||||||
|
|
||||||
|
# Get CPU name
|
||||||
self.timer_cpu_info = Timer(0)
|
self.timer_cpu_info = Timer(0)
|
||||||
|
self.cpu_info: CpuInfo = {'cpu_name': self.__get_cpu_name(), 'cpu_hz_current': None, 'cpu_hz': None}
|
||||||
|
|
||||||
|
# Warning from PsUtil documentation
|
||||||
|
# The first time this function is called with interval = 0.0 or None
|
||||||
|
# it will return a meaningless 0.0 value which you are supposed to ignore.
|
||||||
|
self.timer_cpu = Timer(0)
|
||||||
|
self.cpu_percent = self._compute_cpu()
|
||||||
|
self.timer_percpu = Timer(0)
|
||||||
|
self.percpu_percent = self._compute_percpu()
|
||||||
|
|
||||||
def get_key(self):
|
def get_key(self):
|
||||||
"""Return the key of the per CPU list."""
|
"""Return the key of the per CPU list."""
|
||||||
return 'cpu_number'
|
return 'cpu_number'
|
||||||
|
|
||||||
def get(self, percpu=False):
|
def get_info(self) -> CpuInfo:
|
||||||
"""Update and/or return the CPU using the psutil library.
|
|
||||||
If percpu, return the percpu stats"""
|
|
||||||
if percpu:
|
|
||||||
return self.__get_percpu()
|
|
||||||
return self.__get_cpu()
|
|
||||||
|
|
||||||
def get_info(self):
|
|
||||||
"""Get additional information about the CPU"""
|
"""Get additional information about the CPU"""
|
||||||
# Never update more than 1 time per cached_timer_cpu_info
|
# Never update more than 1 time per cached_timer_cpu_info
|
||||||
if self.timer_cpu_info.finished() and hasattr(psutil, 'cpu_freq'):
|
if self.timer_cpu_info.finished() and hasattr(psutil, 'cpu_freq'):
|
||||||
@ -69,65 +91,69 @@ class CpuPercent:
|
|||||||
self.timer_cpu_info.reset(duration=self.cached_timer_cpu_info)
|
self.timer_cpu_info.reset(duration=self.cached_timer_cpu_info)
|
||||||
return self.cpu_info
|
return self.cpu_info
|
||||||
|
|
||||||
def __get_cpu_name(self):
|
@staticmethod
|
||||||
|
def __get_cpu_name() -> str:
|
||||||
# Get the CPU name once from the /proc/cpuinfo file
|
# Get the CPU name once from the /proc/cpuinfo file
|
||||||
# Read the first line with the "model name"
|
# Read the first line with the "model name" ("Model" for Raspberry Pi)
|
||||||
ret = None
|
|
||||||
try:
|
try:
|
||||||
cpuinfo_file = open('/proc/cpuinfo').readlines()
|
cpuinfo_lines = open('/proc/cpuinfo').readlines()
|
||||||
except (FileNotFoundError, PermissionError):
|
except (FileNotFoundError, PermissionError):
|
||||||
pass
|
logger.debug("No permission to read '/proc/cpuinfo'")
|
||||||
else:
|
return 'CPU'
|
||||||
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):
|
for line in cpuinfo_lines:
|
||||||
|
if line.startswith('model name') or line.startswith('Model') or line.startswith('cpu model'):
|
||||||
|
return line.split(':')[1].strip()
|
||||||
|
|
||||||
|
return 'CPU'
|
||||||
|
|
||||||
|
def get_cpu(self) -> float:
|
||||||
"""Update and/or return the CPU using the psutil library."""
|
"""Update and/or return the CPU using the psutil library."""
|
||||||
# Never update more than 1 time per cached_timer_cpu
|
# Never update more than 1 time per cached_timer_cpu
|
||||||
if self.timer_cpu.finished():
|
if self.timer_cpu.finished():
|
||||||
self.cpu_percent = psutil.cpu_percent(interval=0.0)
|
|
||||||
# Reset timer for cache
|
# Reset timer for cache
|
||||||
self.timer_cpu.reset(duration=self.cached_timer_cpu)
|
self.timer_cpu.reset(duration=self.cached_timer_cpu)
|
||||||
|
# Update the stats
|
||||||
|
self.cpu_percent = self._compute_cpu()
|
||||||
return self.cpu_percent
|
return self.cpu_percent
|
||||||
|
|
||||||
def __get_percpu(self):
|
@staticmethod
|
||||||
|
def _compute_cpu() -> float:
|
||||||
|
return psutil.cpu_percent(interval=0.0)
|
||||||
|
|
||||||
|
def get_percpu(self) -> List[PerCpuPercentInfo]:
|
||||||
"""Update and/or return the per CPU list using the psutil library."""
|
"""Update and/or return the per CPU list using the psutil library."""
|
||||||
# Never update more than 1 time per cached_timer_cpu
|
# Never update more than 1 time per cached_timer_cpu
|
||||||
if self.timer_percpu.finished():
|
if self.timer_percpu.finished():
|
||||||
self.percpu_percent = []
|
# Reset timer for cache
|
||||||
for cpu_number, cputimes in enumerate(psutil.cpu_times_percent(interval=0.0, percpu=True)):
|
self.timer_percpu.reset(duration=self.cached_timer_cpu)
|
||||||
cpu = {
|
# Update stats
|
||||||
'key': self.get_key(),
|
self.percpu_percent = self._compute_percpu()
|
||||||
'cpu_number': cpu_number,
|
|
||||||
'total': round(100 - cputimes.idle, 1),
|
|
||||||
'user': cputimes.user,
|
|
||||||
'system': cputimes.system,
|
|
||||||
'idle': cputimes.idle,
|
|
||||||
}
|
|
||||||
# The following stats are for API purposes only
|
|
||||||
if hasattr(cputimes, 'nice'):
|
|
||||||
cpu['nice'] = cputimes.nice
|
|
||||||
if hasattr(cputimes, 'iowait'):
|
|
||||||
cpu['iowait'] = cputimes.iowait
|
|
||||||
if hasattr(cputimes, 'irq'):
|
|
||||||
cpu['irq'] = cputimes.irq
|
|
||||||
if hasattr(cputimes, 'softirq'):
|
|
||||||
cpu['softirq'] = cputimes.softirq
|
|
||||||
if hasattr(cputimes, 'steal'):
|
|
||||||
cpu['steal'] = cputimes.steal
|
|
||||||
if hasattr(cputimes, 'guest'):
|
|
||||||
cpu['guest'] = cputimes.guest
|
|
||||||
if hasattr(cputimes, 'guest_nice'):
|
|
||||||
cpu['guest_nice'] = cputimes.guest_nice
|
|
||||||
# Append new CPU to the list
|
|
||||||
self.percpu_percent.append(cpu)
|
|
||||||
# Reset timer for cache
|
|
||||||
self.timer_percpu.reset(duration=self.cached_timer_cpu)
|
|
||||||
return self.percpu_percent
|
return self.percpu_percent
|
||||||
|
|
||||||
|
def _compute_percpu(self) -> List[PerCpuPercentInfo]:
|
||||||
|
psutil_percpu = enumerate(psutil.cpu_times_percent(interval=0.0, percpu=True))
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
'key': self.get_key(),
|
||||||
|
'cpu_number': cpu_number,
|
||||||
|
'total': round(100 - cpu_times.idle, 1),
|
||||||
|
'user': cpu_times.user,
|
||||||
|
'system': cpu_times.system,
|
||||||
|
'idle': cpu_times.idle,
|
||||||
|
'nice': cpu_times.nice if hasattr(cpu_times, 'nice') else None,
|
||||||
|
'iowait': cpu_times.iowait if hasattr(cpu_times, 'iowait') else None,
|
||||||
|
'irq': cpu_times.irq if hasattr(cpu_times, 'irq') else None,
|
||||||
|
'softirq': cpu_times.softirq if hasattr(cpu_times, 'softirq') else None,
|
||||||
|
'steal': cpu_times.steal if hasattr(cpu_times, 'steal') else None,
|
||||||
|
'guest': cpu_times.guest if hasattr(cpu_times, 'guest') else None,
|
||||||
|
'guest_nice': cpu_times.steal if hasattr(cpu_times, 'guest_nice') else None,
|
||||||
|
'dpc': cpu_times.dpc if hasattr(cpu_times, 'dpc') else None,
|
||||||
|
'interrupt': cpu_times.interrupt if hasattr(cpu_times, 'interrupt') else None,
|
||||||
|
}
|
||||||
|
for cpu_number, cpu_times in psutil_percpu
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# CpuPercent instance shared between plugins
|
# CpuPercent instance shared between plugins
|
||||||
cpu_percent = CpuPercent()
|
cpu_percent = CpuPercent()
|
||||||
|
@ -34,10 +34,12 @@ class Export(GlancesExport):
|
|||||||
|
|
||||||
# Manage options (command line arguments overwrite configuration file)
|
# Manage options (command line arguments overwrite configuration file)
|
||||||
self.path = args.export_graph_path or self.path
|
self.path = args.export_graph_path or self.path
|
||||||
self.generate_every = int(getattr(self, 'generate_every', 0))
|
self.generate_every = int(getattr(self, 'generate_every', 0) or 0)
|
||||||
self.width = int(getattr(self, 'width', 800))
|
self.width = int(getattr(self, 'width', 800) or 800)
|
||||||
self.height = int(getattr(self, 'height', 600))
|
self.height = int(getattr(self, 'height', 600) or 600)
|
||||||
self.style = getattr(pygal.style, getattr(self, 'style', 'DarkStyle'), pygal.style.DarkStyle)
|
self.style = (
|
||||||
|
getattr(pygal.style, getattr(self, 'style', 'DarkStyle'), pygal.style.DarkStyle) or pygal.style.DarkStyle
|
||||||
|
)
|
||||||
|
|
||||||
# Create export folder
|
# Create export folder
|
||||||
try:
|
try:
|
||||||
|
@ -139,8 +139,7 @@ class Export(GlancesExport):
|
|||||||
if k in fields:
|
if k in fields:
|
||||||
tags[k] = str(fields[k])
|
tags[k] = str(fields[k])
|
||||||
# Remove it from the field list (can not be a field and a tag)
|
# Remove it from the field list (can not be a field and a tag)
|
||||||
if k in fields:
|
fields.pop(k)
|
||||||
fields.pop(fields[k])
|
|
||||||
# Add the measurement to the list
|
# Add the measurement to the list
|
||||||
ret.append({'measurement': name, 'tags': tags, 'fields': fields})
|
ret.append({'measurement': name, 'tags': tags, 'fields': fields})
|
||||||
return ret
|
return ret
|
||||||
@ -157,7 +156,7 @@ class Export(GlancesExport):
|
|||||||
try:
|
try:
|
||||||
self.client.write_points(self._normalize(name, columns, points), time_precision="s")
|
self.client.write_points(self._normalize(name, columns, points), time_precision="s")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Log level set to debug instead of error (see: issue #1561)
|
# Log level set to warning instead of error (see: issue #1561)
|
||||||
logger.debug(f"Cannot export {name} stats to InfluxDB ({e})")
|
logger.warning(f"Cannot export {name} stats to InfluxDB ({e})")
|
||||||
else:
|
else:
|
||||||
logger.debug(f"Export {name} stats to InfluxDB")
|
logger.debug(f"Export {name} stats to InfluxDB")
|
||||||
|
@ -147,8 +147,7 @@ class Export(GlancesExport):
|
|||||||
if k in fields:
|
if k in fields:
|
||||||
tags[k] = str(fields[k])
|
tags[k] = str(fields[k])
|
||||||
# Remove it from the field list (can not be a field and a tag)
|
# Remove it from the field list (can not be a field and a tag)
|
||||||
if k in fields:
|
fields.pop(k)
|
||||||
fields.pop(fields[k])
|
|
||||||
# Add the measurement to the list
|
# Add the measurement to the list
|
||||||
ret.append({'measurement': name, 'tags': tags, 'fields': fields})
|
ret.append({'measurement': name, 'tags': tags, 'fields': fields})
|
||||||
return ret
|
return ret
|
||||||
@ -165,7 +164,7 @@ class Export(GlancesExport):
|
|||||||
try:
|
try:
|
||||||
self.client.write(self.bucket, self.org, self._normalize(name, columns, points), time_precision="s")
|
self.client.write(self.bucket, self.org, self._normalize(name, columns, points), time_precision="s")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Log level set to debug instead of error (see: issue #1561)
|
# Log level set to warning instead of error (see: issue #1561)
|
||||||
logger.debug(f"Cannot export {name} stats to InfluxDB ({e})")
|
logger.warning(f"Cannot export {name} stats to InfluxDB ({e})")
|
||||||
else:
|
else:
|
||||||
logger.debug(f"Export {name} stats to InfluxDB")
|
logger.debug(f"Export {name} stats to InfluxDB")
|
||||||
|
@ -89,7 +89,7 @@ def printandflush(string):
|
|||||||
|
|
||||||
def to_ascii(s):
|
def to_ascii(s):
|
||||||
"""Convert the bytes string to a ASCII string
|
"""Convert the bytes string to a ASCII string
|
||||||
Usefull to remove accent (diacritics)"""
|
Useful to remove accent (diacritics)"""
|
||||||
if isinstance(s, binary_type):
|
if isinstance(s, binary_type):
|
||||||
return s.decode()
|
return s.decode()
|
||||||
return s.encode('ascii', 'ignore').decode()
|
return s.encode('ascii', 'ignore').decode()
|
||||||
@ -153,7 +153,7 @@ def subsample(data, sampling):
|
|||||||
|
|
||||||
Data should be a list of numerical itervalues
|
Data should be a list of numerical itervalues
|
||||||
|
|
||||||
Return a subsampled list of sampling lenght
|
Return a subsampled list of sampling length
|
||||||
"""
|
"""
|
||||||
if len(data) <= sampling:
|
if len(data) <= sampling:
|
||||||
return data
|
return data
|
||||||
@ -216,13 +216,13 @@ def key_exist_value_not_none(k, d):
|
|||||||
return k in d and d[k] is not None
|
return k in d and d[k] is not None
|
||||||
|
|
||||||
|
|
||||||
def key_exist_value_not_none_not_v(k, d, value='', lengh=None):
|
def key_exist_value_not_none_not_v(k, d, value='', length=None):
|
||||||
# Return True if:
|
# Return True if:
|
||||||
# - key k exists
|
# - key k exists
|
||||||
# - d[k] is not None
|
# - d[k] is not None
|
||||||
# - d[k] != value
|
# - d[k] != value
|
||||||
# - if lengh is not None and len(d[k]) >= lengh
|
# - if length is not None and len(d[k]) >= length
|
||||||
return k in d and d[k] is not None and d[k] != value and (lengh is None or len(d[k]) >= lengh)
|
return k in d and d[k] is not None and d[k] != value and (length is None or len(d[k]) >= length)
|
||||||
|
|
||||||
|
|
||||||
def disable(class_name, var):
|
def disable(class_name, var):
|
||||||
@ -425,12 +425,12 @@ def weak_lru_cache(maxsize=128, typed=False):
|
|||||||
|
|
||||||
|
|
||||||
def namedtuple_to_dict(data):
|
def namedtuple_to_dict(data):
|
||||||
"""Convert a namedtuple to a dict, using the _asdict() method embeded in PsUtil stats."""
|
"""Convert a namedtuple to a dict, using the _asdict() method embedded in PsUtil stats."""
|
||||||
return {k: (v._asdict() if hasattr(v, '_asdict') else v) for k, v in data.items()}
|
return {k: (v._asdict() if hasattr(v, '_asdict') else v) for k, v in data.items()}
|
||||||
|
|
||||||
|
|
||||||
def list_of_namedtuple_to_list_of_dict(data):
|
def list_of_namedtuple_to_list_of_dict(data):
|
||||||
"""Convert a list of namedtuples to a dict, using the _asdict() method embeded in PsUtil stats."""
|
"""Convert a list of namedtuples to a dict, using the _asdict() method embedded in PsUtil stats."""
|
||||||
return [namedtuple_to_dict(d) for d in data]
|
return [namedtuple_to_dict(d) for d in data]
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ class _GlancesCurses:
|
|||||||
self._init_cursor()
|
self._init_cursor()
|
||||||
|
|
||||||
# Init the colors
|
# Init the colors
|
||||||
self._init_colors()
|
self.colors_list = build_colors_list(args)
|
||||||
|
|
||||||
# Init main window
|
# Init main window
|
||||||
self.term_window = self.screen.subwin(0, 0)
|
self.term_window = self.screen.subwin(0, 0)
|
||||||
@ -216,133 +216,6 @@ class _GlancesCurses:
|
|||||||
curses.cbreak()
|
curses.cbreak()
|
||||||
self.set_cursor(0)
|
self.set_cursor(0)
|
||||||
|
|
||||||
def _init_colors(self):
|
|
||||||
"""Init the Curses color layout."""
|
|
||||||
|
|
||||||
# Set curses options
|
|
||||||
try:
|
|
||||||
if hasattr(curses, 'start_color'):
|
|
||||||
curses.start_color()
|
|
||||||
logger.debug(f'Curses interface compatible with {curses.COLORS} colors')
|
|
||||||
if hasattr(curses, 'use_default_colors'):
|
|
||||||
curses.use_default_colors()
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f'Error initializing terminal color ({e})')
|
|
||||||
|
|
||||||
# Init colors
|
|
||||||
if self.args.disable_bold:
|
|
||||||
A_BOLD = 0
|
|
||||||
self.args.disable_bg = True
|
|
||||||
else:
|
|
||||||
A_BOLD = curses.A_BOLD
|
|
||||||
|
|
||||||
self.title_color = A_BOLD
|
|
||||||
self.title_underline_color = A_BOLD | curses.A_UNDERLINE
|
|
||||||
self.help_color = A_BOLD
|
|
||||||
|
|
||||||
if curses.has_colors():
|
|
||||||
# The screen is compatible with a colored design
|
|
||||||
# ex: export TERM=xterm-256color
|
|
||||||
# export TERM=xterm-color
|
|
||||||
|
|
||||||
curses.init_pair(1, -1, -1)
|
|
||||||
if self.args.disable_bg:
|
|
||||||
curses.init_pair(2, curses.COLOR_RED, -1)
|
|
||||||
curses.init_pair(3, curses.COLOR_GREEN, -1)
|
|
||||||
curses.init_pair(5, curses.COLOR_MAGENTA, -1)
|
|
||||||
else:
|
|
||||||
curses.init_pair(2, -1, curses.COLOR_RED)
|
|
||||||
curses.init_pair(3, -1, curses.COLOR_GREEN)
|
|
||||||
curses.init_pair(5, -1, curses.COLOR_MAGENTA)
|
|
||||||
curses.init_pair(4, curses.COLOR_BLUE, -1)
|
|
||||||
curses.init_pair(6, curses.COLOR_RED, -1)
|
|
||||||
curses.init_pair(7, curses.COLOR_GREEN, -1)
|
|
||||||
curses.init_pair(8, curses.COLOR_MAGENTA, -1)
|
|
||||||
|
|
||||||
# Colors text styles
|
|
||||||
self.no_color = curses.color_pair(1)
|
|
||||||
self.default_color = curses.color_pair(3) | A_BOLD
|
|
||||||
self.nice_color = curses.color_pair(8)
|
|
||||||
self.cpu_time_color = curses.color_pair(8)
|
|
||||||
self.ifCAREFUL_color = curses.color_pair(4) | A_BOLD
|
|
||||||
self.ifWARNING_color = curses.color_pair(5) | A_BOLD
|
|
||||||
self.ifCRITICAL_color = curses.color_pair(2) | A_BOLD
|
|
||||||
self.default_color2 = curses.color_pair(7)
|
|
||||||
self.ifCAREFUL_color2 = curses.color_pair(4)
|
|
||||||
self.ifWARNING_color2 = curses.color_pair(8) | A_BOLD
|
|
||||||
self.ifCRITICAL_color2 = curses.color_pair(6) | A_BOLD
|
|
||||||
self.ifINFO_color = curses.color_pair(4)
|
|
||||||
self.filter_color = A_BOLD
|
|
||||||
self.selected_color = A_BOLD
|
|
||||||
self.separator = curses.color_pair(1)
|
|
||||||
|
|
||||||
if curses.COLORS > 8:
|
|
||||||
# ex: export TERM=xterm-256color
|
|
||||||
colors_list = [curses.COLOR_CYAN, curses.COLOR_YELLOW]
|
|
||||||
for i in range(0, 3):
|
|
||||||
try:
|
|
||||||
curses.init_pair(i + 9, colors_list[i], -1)
|
|
||||||
except Exception:
|
|
||||||
curses.init_pair(i + 9, -1, -1)
|
|
||||||
self.filter_color = curses.color_pair(9) | A_BOLD
|
|
||||||
self.selected_color = curses.color_pair(10) | A_BOLD
|
|
||||||
# Define separator line style
|
|
||||||
try:
|
|
||||||
curses.init_color(11, 500, 500, 500)
|
|
||||||
curses.init_pair(11, curses.COLOR_BLACK, -1)
|
|
||||||
self.separator = curses.color_pair(11)
|
|
||||||
except Exception:
|
|
||||||
# Catch exception in TMUX
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# The screen is NOT compatible with a colored design
|
|
||||||
# switch to B&W text styles
|
|
||||||
# ex: export TERM=xterm-mono
|
|
||||||
self.no_color = -1
|
|
||||||
self.default_color = -1
|
|
||||||
self.nice_color = A_BOLD
|
|
||||||
self.cpu_time_color = A_BOLD
|
|
||||||
self.ifCAREFUL_color = A_BOLD
|
|
||||||
self.ifWARNING_color = curses.A_UNDERLINE
|
|
||||||
self.ifCRITICAL_color = curses.A_REVERSE
|
|
||||||
self.default_color2 = -1
|
|
||||||
self.ifCAREFUL_color2 = A_BOLD
|
|
||||||
self.ifWARNING_color2 = curses.A_UNDERLINE
|
|
||||||
self.ifCRITICAL_color2 = curses.A_REVERSE
|
|
||||||
self.ifINFO_color = A_BOLD
|
|
||||||
self.filter_color = A_BOLD
|
|
||||||
self.selected_color = A_BOLD
|
|
||||||
self.separator = -1
|
|
||||||
|
|
||||||
# Define the colors list (hash table) for stats
|
|
||||||
self.colors_list = {
|
|
||||||
'DEFAULT': self.no_color,
|
|
||||||
'UNDERLINE': curses.A_UNDERLINE,
|
|
||||||
'BOLD': A_BOLD,
|
|
||||||
'SORT': curses.A_UNDERLINE | A_BOLD,
|
|
||||||
'OK': self.default_color2,
|
|
||||||
'MAX': self.default_color2 | A_BOLD,
|
|
||||||
'FILTER': self.filter_color,
|
|
||||||
'TITLE': self.title_color,
|
|
||||||
'PROCESS': self.default_color2,
|
|
||||||
'PROCESS_SELECTED': self.default_color2 | curses.A_UNDERLINE,
|
|
||||||
'STATUS': self.default_color2,
|
|
||||||
'NICE': self.nice_color,
|
|
||||||
'CPU_TIME': self.cpu_time_color,
|
|
||||||
'CAREFUL': self.ifCAREFUL_color2,
|
|
||||||
'WARNING': self.ifWARNING_color2,
|
|
||||||
'CRITICAL': self.ifCRITICAL_color2,
|
|
||||||
'OK_LOG': self.default_color,
|
|
||||||
'CAREFUL_LOG': self.ifCAREFUL_color,
|
|
||||||
'WARNING_LOG': self.ifWARNING_color,
|
|
||||||
'CRITICAL_LOG': self.ifCRITICAL_color,
|
|
||||||
'PASSWORD': curses.A_PROTECT,
|
|
||||||
'SELECTED': self.selected_color,
|
|
||||||
'INFO': self.ifINFO_color,
|
|
||||||
'ERROR': self.selected_color,
|
|
||||||
'SEPARATOR': self.separator,
|
|
||||||
}
|
|
||||||
|
|
||||||
def set_cursor(self, value):
|
def set_cursor(self, value):
|
||||||
"""Configure the curse cursor appearance.
|
"""Configure the curse cursor appearance.
|
||||||
|
|
||||||
@ -497,7 +370,7 @@ class _GlancesCurses:
|
|||||||
logger.info(f"Stop Glances (keypressed: {self.pressedkey})")
|
logger.info(f"Stop Glances (keypressed: {self.pressedkey})")
|
||||||
|
|
||||||
def _handle_refresh(self):
|
def _handle_refresh(self):
|
||||||
pass
|
glances_processes.reset_internal_cache()
|
||||||
|
|
||||||
def loop_position(self):
|
def loop_position(self):
|
||||||
"""Return the current sort in the loop"""
|
"""Return the current sort in the loop"""
|
||||||
@ -1303,3 +1176,128 @@ class GlancesTextboxYesNo(Textbox):
|
|||||||
|
|
||||||
def do_command(self, ch):
|
def do_command(self, ch):
|
||||||
return super().do_command(ch)
|
return super().do_command(ch)
|
||||||
|
|
||||||
|
|
||||||
|
def build_colors_list(args):
|
||||||
|
"""Init the Curses color layout."""
|
||||||
|
# Set curses options
|
||||||
|
try:
|
||||||
|
if hasattr(curses, 'start_color'):
|
||||||
|
curses.start_color()
|
||||||
|
logger.debug(f'Curses interface compatible with {curses.COLORS} colors')
|
||||||
|
if hasattr(curses, 'use_default_colors'):
|
||||||
|
curses.use_default_colors()
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f'Error initializing terminal color ({e})')
|
||||||
|
|
||||||
|
# Init colors
|
||||||
|
if args.disable_bold:
|
||||||
|
A_BOLD = 0
|
||||||
|
args.disable_bg = True
|
||||||
|
else:
|
||||||
|
A_BOLD = curses.A_BOLD
|
||||||
|
|
||||||
|
title_color = A_BOLD
|
||||||
|
|
||||||
|
if curses.has_colors():
|
||||||
|
# The screen is compatible with a colored design
|
||||||
|
# ex: export TERM=xterm-256color
|
||||||
|
# export TERM=xterm-color
|
||||||
|
|
||||||
|
curses.init_pair(1, -1, -1)
|
||||||
|
if args.disable_bg:
|
||||||
|
curses.init_pair(2, curses.COLOR_RED, -1)
|
||||||
|
curses.init_pair(3, curses.COLOR_GREEN, -1)
|
||||||
|
curses.init_pair(5, curses.COLOR_MAGENTA, -1)
|
||||||
|
else:
|
||||||
|
curses.init_pair(2, -1, curses.COLOR_RED)
|
||||||
|
curses.init_pair(3, 0, curses.COLOR_GREEN)
|
||||||
|
curses.init_pair(5, -1, curses.COLOR_MAGENTA)
|
||||||
|
curses.init_pair(4, curses.COLOR_BLUE, -1)
|
||||||
|
curses.init_pair(6, curses.COLOR_RED, -1)
|
||||||
|
curses.init_pair(7, curses.COLOR_GREEN, -1)
|
||||||
|
curses.init_pair(8, curses.COLOR_MAGENTA, -1)
|
||||||
|
|
||||||
|
# Colors text styles
|
||||||
|
no_color = curses.color_pair(1)
|
||||||
|
default_color = curses.color_pair(3) | A_BOLD
|
||||||
|
nice_color = curses.color_pair(8)
|
||||||
|
cpu_time_color = curses.color_pair(8)
|
||||||
|
ifCAREFUL_color = curses.color_pair(4) | A_BOLD
|
||||||
|
ifWARNING_color = curses.color_pair(5) | A_BOLD
|
||||||
|
ifCRITICAL_color = curses.color_pair(2) | A_BOLD
|
||||||
|
default_color2 = curses.color_pair(7)
|
||||||
|
ifCAREFUL_color2 = curses.color_pair(4)
|
||||||
|
ifWARNING_color2 = curses.color_pair(8) | A_BOLD
|
||||||
|
ifCRITICAL_color2 = curses.color_pair(6) | A_BOLD
|
||||||
|
ifINFO_color = curses.color_pair(4)
|
||||||
|
filter_color = A_BOLD
|
||||||
|
selected_color = A_BOLD
|
||||||
|
separator = curses.color_pair(1)
|
||||||
|
|
||||||
|
if curses.COLORS > 8:
|
||||||
|
# ex: export TERM=xterm-256color
|
||||||
|
colors_list = [curses.COLOR_CYAN, curses.COLOR_YELLOW]
|
||||||
|
for i in range(0, 3):
|
||||||
|
try:
|
||||||
|
curses.init_pair(i + 9, colors_list[i], -1)
|
||||||
|
except Exception:
|
||||||
|
curses.init_pair(i + 9, -1, -1)
|
||||||
|
filter_color = curses.color_pair(9) | A_BOLD
|
||||||
|
selected_color = curses.color_pair(10) | A_BOLD
|
||||||
|
# Define separator line style
|
||||||
|
try:
|
||||||
|
curses.init_color(11, 500, 500, 500)
|
||||||
|
curses.init_pair(11, curses.COLOR_BLACK, -1)
|
||||||
|
separator = curses.color_pair(11)
|
||||||
|
except Exception:
|
||||||
|
# Catch exception in TMUX
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# The screen is NOT compatible with a colored design
|
||||||
|
# switch to B&W text styles
|
||||||
|
# ex: export TERM=xterm-mono
|
||||||
|
no_color = -1
|
||||||
|
default_color = -1
|
||||||
|
nice_color = A_BOLD
|
||||||
|
cpu_time_color = A_BOLD
|
||||||
|
ifCAREFUL_color = A_BOLD
|
||||||
|
ifWARNING_color = curses.A_UNDERLINE
|
||||||
|
ifCRITICAL_color = curses.A_REVERSE
|
||||||
|
default_color2 = -1
|
||||||
|
ifCAREFUL_color2 = A_BOLD
|
||||||
|
ifWARNING_color2 = curses.A_UNDERLINE
|
||||||
|
ifCRITICAL_color2 = curses.A_REVERSE
|
||||||
|
ifINFO_color = A_BOLD
|
||||||
|
filter_color = A_BOLD
|
||||||
|
selected_color = A_BOLD
|
||||||
|
separator = -1
|
||||||
|
|
||||||
|
# Define the colors list (hash table) for stats
|
||||||
|
return {
|
||||||
|
'DEFAULT': no_color,
|
||||||
|
'UNDERLINE': curses.A_UNDERLINE,
|
||||||
|
'BOLD': A_BOLD,
|
||||||
|
'SORT': curses.A_UNDERLINE | A_BOLD,
|
||||||
|
'OK': default_color2,
|
||||||
|
'MAX': default_color2 | A_BOLD,
|
||||||
|
'FILTER': filter_color,
|
||||||
|
'TITLE': title_color,
|
||||||
|
'PROCESS': default_color2,
|
||||||
|
'PROCESS_SELECTED': default_color2 | curses.A_UNDERLINE,
|
||||||
|
'STATUS': default_color2,
|
||||||
|
'NICE': nice_color,
|
||||||
|
'CPU_TIME': cpu_time_color,
|
||||||
|
'CAREFUL': ifCAREFUL_color2,
|
||||||
|
'WARNING': ifWARNING_color2,
|
||||||
|
'CRITICAL': ifCRITICAL_color2,
|
||||||
|
'OK_LOG': default_color,
|
||||||
|
'CAREFUL_LOG': ifCAREFUL_color,
|
||||||
|
'WARNING_LOG': ifWARNING_color,
|
||||||
|
'CRITICAL_LOG': ifCRITICAL_color,
|
||||||
|
'PASSWORD': curses.A_PROTECT,
|
||||||
|
'SELECTED': selected_color,
|
||||||
|
'INFO': ifINFO_color,
|
||||||
|
'ERROR': selected_color,
|
||||||
|
'SEPARATOR': separator,
|
||||||
|
}
|
||||||
|
@ -24,11 +24,11 @@ class GlancesCursesBrowser(_GlancesCurses):
|
|||||||
super().__init__(args=args)
|
super().__init__(args=args)
|
||||||
|
|
||||||
_colors_list = {
|
_colors_list = {
|
||||||
'UNKNOWN': self.no_color,
|
'UNKNOWN': self.colors_list['DEFAULT'],
|
||||||
'SNMP': self.default_color2,
|
'SNMP': self.colors_list['OK'],
|
||||||
'ONLINE': self.default_color2,
|
'ONLINE': self.colors_list['OK'],
|
||||||
'OFFLINE': self.ifCRITICAL_color2,
|
'OFFLINE': self.colors_list['CRITICAL'],
|
||||||
'PROTECTED': self.ifWARNING_color2,
|
'PROTECTED': self.colors_list['WARNING'],
|
||||||
}
|
}
|
||||||
self.colors_list.update(_colors_list)
|
self.colors_list.update(_colors_list)
|
||||||
|
|
||||||
@ -299,13 +299,11 @@ class GlancesCursesBrowser(_GlancesCurses):
|
|||||||
# Item description: [stats_id, column name, column size]
|
# Item description: [stats_id, column name, column size]
|
||||||
column_def = [
|
column_def = [
|
||||||
['name', 'Name', 16],
|
['name', 'Name', 16],
|
||||||
['alias', None, None],
|
|
||||||
['load_min5', 'LOAD', 6],
|
['load_min5', 'LOAD', 6],
|
||||||
['cpu_percent', 'CPU%', 5],
|
['cpu_percent', 'CPU%', 5],
|
||||||
['mem_percent', 'MEM%', 5],
|
['mem_percent', 'MEM%', 5],
|
||||||
['status', 'STATUS', 9],
|
['status', 'STATUS', 9],
|
||||||
['ip', 'IP', 15],
|
['ip', 'IP', 15],
|
||||||
# ['port', 'PORT', 5],
|
|
||||||
['hr_name', 'OS', 16],
|
['hr_name', 'OS', 16],
|
||||||
]
|
]
|
||||||
y = 2
|
y = 2
|
||||||
@ -331,24 +329,10 @@ class GlancesCursesBrowser(_GlancesCurses):
|
|||||||
|
|
||||||
# Display table
|
# Display table
|
||||||
line = 0
|
line = 0
|
||||||
for v in current_page:
|
for server_stat in current_page:
|
||||||
# Limit the number of displayed server (see issue #1256)
|
# Limit the number of displayed server (see issue #1256)
|
||||||
if line >= stats_max:
|
if line >= stats_max:
|
||||||
continue
|
continue
|
||||||
# Get server stats
|
|
||||||
server_stat = {}
|
|
||||||
for c in column_def:
|
|
||||||
try:
|
|
||||||
server_stat[c[0]] = v[c[0]]
|
|
||||||
except KeyError as e:
|
|
||||||
logger.debug(f"Cannot grab stats {c[0]} from server (KeyError: {e})")
|
|
||||||
server_stat[c[0]] = '?'
|
|
||||||
# Display alias instead of name
|
|
||||||
try:
|
|
||||||
if c[0] == 'alias' and v[c[0]] is not None:
|
|
||||||
server_stat['name'] = v[c[0]]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Display line for server stats
|
# Display line for server stats
|
||||||
cpt = 0
|
cpt = 0
|
||||||
@ -362,9 +346,20 @@ class GlancesCursesBrowser(_GlancesCurses):
|
|||||||
# Display the line
|
# Display the line
|
||||||
xc += 2
|
xc += 2
|
||||||
for c in column_def:
|
for c in column_def:
|
||||||
if xc < screen_x and y < screen_y and c[1] is not None:
|
if xc < screen_x and y < screen_y:
|
||||||
# Display server stats
|
# Display server stats
|
||||||
self.term_window.addnstr(y, xc, format(server_stat[c[0]]), c[2], self.colors_list[v['status']])
|
value = format(server_stat.get(c[0], '?'))
|
||||||
|
if c[0] == 'name' and 'alias' in server_stat:
|
||||||
|
value = server_stat['alias']
|
||||||
|
decoration = self.colors_list.get(
|
||||||
|
server_stat[c[0] + '_decoration'].replace('_LOG', '')
|
||||||
|
if c[0] + '_decoration' in server_stat
|
||||||
|
else self.colors_list[server_stat['status']],
|
||||||
|
self.colors_list['DEFAULT'],
|
||||||
|
)
|
||||||
|
if c[0] == 'status':
|
||||||
|
decoration = self.colors_list[server_stat['status']]
|
||||||
|
self.term_window.addnstr(y, xc, value, c[2], decoration)
|
||||||
xc += c[2] + self.space_between_column
|
xc += c[2] + self.space_between_column
|
||||||
cpt += 1
|
cpt += 1
|
||||||
# Next line, next server...
|
# Next line, next server...
|
||||||
|
@ -185,6 +185,7 @@ class GlancesRestfulApi:
|
|||||||
router.add_api_route(
|
router.add_api_route(
|
||||||
f'/api/{self.API_VERSION}/status',
|
f'/api/{self.API_VERSION}/status',
|
||||||
status_code=status.HTTP_200_OK,
|
status_code=status.HTTP_200_OK,
|
||||||
|
methods=['HEAD', 'GET'],
|
||||||
response_class=ORJSONResponse,
|
response_class=ORJSONResponse,
|
||||||
endpoint=self._api_status,
|
endpoint=self._api_status,
|
||||||
)
|
)
|
||||||
|
130
glances/outputs/static/package-lock.json
generated
130
glances/outputs/static/package-lock.json
generated
@ -4,7 +4,6 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "static",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "^3.4.1",
|
"bootstrap": "^3.4.1",
|
||||||
"favico.js": "^0.3.10",
|
"favico.js": "^0.3.10",
|
||||||
@ -1975,24 +1974,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-vue": {
|
"node_modules/eslint-plugin-vue": {
|
||||||
"version": "9.17.0",
|
"version": "9.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.27.0.tgz",
|
||||||
"integrity": "sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==",
|
"integrity": "sha512-5Dw3yxEyuBSXTzT5/Ge1X5kIkRTQ3nvBn/VwPwInNiZBSJOO/timWMUaflONnFBzU6NhB68lxnCda7ULV5N7LA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
|
"globals": "^13.24.0",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"nth-check": "^2.1.1",
|
"nth-check": "^2.1.1",
|
||||||
"postcss-selector-parser": "^6.0.13",
|
"postcss-selector-parser": "^6.0.15",
|
||||||
"semver": "^7.5.4",
|
"semver": "^7.6.0",
|
||||||
"vue-eslint-parser": "^9.3.1",
|
"vue-eslint-parser": "^9.4.3",
|
||||||
"xml-name-validator": "^4.0.0"
|
"xml-name-validator": "^4.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.17.0 || >=16.0.0"
|
"node": "^14.17.0 || >=16.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^6.2.0 || ^7.0.0 || ^8.0.0"
|
"eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-scope": {
|
"node_modules/eslint-scope": {
|
||||||
@ -2522,9 +2522,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/globals": {
|
"node_modules/globals": {
|
||||||
"version": "13.20.0",
|
"version": "13.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
|
||||||
"integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
|
"integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"type-fest": "^0.20.2"
|
"type-fest": "^0.20.2"
|
||||||
@ -3371,18 +3371,6 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lru-cache": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"yallist": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.0",
|
"version": "0.30.0",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz",
|
||||||
@ -4127,9 +4115,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-selector-parser": {
|
"node_modules/postcss-selector-parser": {
|
||||||
"version": "6.0.13",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz",
|
||||||
"integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
|
"integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssesc": "^3.0.0",
|
"cssesc": "^3.0.0",
|
||||||
@ -4717,13 +4705,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.5.4",
|
"version": "7.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
||||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
|
||||||
"lru-cache": "^6.0.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
},
|
},
|
||||||
@ -5444,9 +5429,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vue-eslint-parser": {
|
"node_modules/vue-eslint-parser": {
|
||||||
"version": "9.3.1",
|
"version": "9.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
|
||||||
"integrity": "sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==",
|
"integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
@ -5807,9 +5792,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.13.0",
|
"version": "8.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
@ -5836,12 +5821,6 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/yallist": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/yocto-queue": {
|
"node_modules/yocto-queue": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
@ -7400,17 +7379,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint-plugin-vue": {
|
"eslint-plugin-vue": {
|
||||||
"version": "9.17.0",
|
"version": "9.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.27.0.tgz",
|
||||||
"integrity": "sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==",
|
"integrity": "sha512-5Dw3yxEyuBSXTzT5/Ge1X5kIkRTQ3nvBn/VwPwInNiZBSJOO/timWMUaflONnFBzU6NhB68lxnCda7ULV5N7LA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
|
"globals": "^13.24.0",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"nth-check": "^2.1.1",
|
"nth-check": "^2.1.1",
|
||||||
"postcss-selector-parser": "^6.0.13",
|
"postcss-selector-parser": "^6.0.15",
|
||||||
"semver": "^7.5.4",
|
"semver": "^7.6.0",
|
||||||
"vue-eslint-parser": "^9.3.1",
|
"vue-eslint-parser": "^9.4.3",
|
||||||
"xml-name-validator": "^4.0.0"
|
"xml-name-validator": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -7812,9 +7792,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"globals": {
|
"globals": {
|
||||||
"version": "13.20.0",
|
"version": "13.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
|
||||||
"integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
|
"integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"type-fest": "^0.20.2"
|
"type-fest": "^0.20.2"
|
||||||
@ -8422,15 +8402,6 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lru-cache": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"yallist": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"magic-string": {
|
"magic-string": {
|
||||||
"version": "0.30.0",
|
"version": "0.30.0",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz",
|
||||||
@ -8967,9 +8938,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"postcss-selector-parser": {
|
"postcss-selector-parser": {
|
||||||
"version": "6.0.13",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz",
|
||||||
"integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
|
"integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"cssesc": "^3.0.0",
|
"cssesc": "^3.0.0",
|
||||||
@ -9373,13 +9344,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.5.4",
|
"version": "7.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
||||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {
|
|
||||||
"lru-cache": "^6.0.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"send": {
|
"send": {
|
||||||
"version": "0.18.0",
|
"version": "0.18.0",
|
||||||
@ -9909,9 +9877,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue-eslint-parser": {
|
"vue-eslint-parser": {
|
||||||
"version": "9.3.1",
|
"version": "9.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
|
||||||
"integrity": "sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==",
|
"integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
@ -10149,9 +10117,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "8.13.0",
|
"version": "8.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
@ -10161,12 +10129,6 @@
|
|||||||
"integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
|
"integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"yocto-queue": {
|
"yocto-queue": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
|
@ -11,7 +11,7 @@ It should implement a Class named PluginModel (inherited from GlancesPluginModel
|
|||||||
This class should be based on the MVC model.
|
This class should be based on the MVC model.
|
||||||
- model: where the stats are updated (update method)
|
- model: where the stats are updated (update method)
|
||||||
- view: where the stats are prepare to be displayed (update_views)
|
- view: where the stats are prepare to be displayed (update_views)
|
||||||
- controler: where the stats are displayed (msg_curse method)
|
- controller: where the stats are displayed (msg_curse method)
|
||||||
|
|
||||||
A plugin should define the following global variables:
|
A plugin should define the following global variables:
|
||||||
|
|
||||||
|
@ -8,12 +8,14 @@
|
|||||||
|
|
||||||
"""Containers plugin."""
|
"""Containers plugin."""
|
||||||
|
|
||||||
import os
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
|
from glances.globals import iteritems, itervalues
|
||||||
from glances.logger import logger
|
from glances.logger import logger
|
||||||
from glances.plugins.containers.engines.docker import DockerContainersExtension, import_docker_error_tag
|
from glances.plugins.containers.engines import ContainersExtension
|
||||||
from glances.plugins.containers.engines.podman import PodmanContainersExtension, import_podman_error_tag
|
from glances.plugins.containers.engines.docker import DockerExtension, import_docker_error_tag
|
||||||
|
from glances.plugins.containers.engines.podman import PodmanExtension, import_podman_error_tag
|
||||||
from glances.plugins.plugin.model import GlancesPluginModel
|
from glances.plugins.plugin.model import GlancesPluginModel
|
||||||
from glances.processes import glances_processes
|
from glances.processes import glances_processes
|
||||||
from glances.processes import sort_stats as sort_stats_processes
|
from glances.processes import sort_stats as sort_stats_processes
|
||||||
@ -139,14 +141,15 @@ class PluginModel(GlancesPluginModel):
|
|||||||
# We want to display the stat in the curse interface
|
# We want to display the stat in the curse interface
|
||||||
self.display_curse = True
|
self.display_curse = True
|
||||||
|
|
||||||
|
self.watchers: Dict[str, ContainersExtension] = {}
|
||||||
|
|
||||||
# Init the Docker API
|
# Init the Docker API
|
||||||
self.docker_extension = DockerContainersExtension() if not import_docker_error_tag else None
|
if not import_docker_error_tag:
|
||||||
|
self.watchers['docker'] = DockerExtension()
|
||||||
|
|
||||||
# Init the Podman API
|
# Init the Podman API
|
||||||
if import_podman_error_tag:
|
if not import_podman_error_tag:
|
||||||
self.podman_extension = None
|
self.watchers['podman'] = PodmanExtension(podman_sock=self._podman_sock())
|
||||||
else:
|
|
||||||
self.podman_extension = PodmanContainersExtension(podman_sock=self._podman_sock())
|
|
||||||
|
|
||||||
# Sort key
|
# Sort key
|
||||||
self.sort_key = None
|
self.sort_key = None
|
||||||
@ -155,7 +158,7 @@ class PluginModel(GlancesPluginModel):
|
|||||||
self.update()
|
self.update()
|
||||||
self.refresh_timer.set(0)
|
self.refresh_timer.set(0)
|
||||||
|
|
||||||
def _podman_sock(self):
|
def _podman_sock(self) -> str:
|
||||||
"""Return the podman sock.
|
"""Return the podman sock.
|
||||||
Could be desfined in the [docker] section thanks to the podman_sock option.
|
Could be desfined in the [docker] section thanks to the podman_sock option.
|
||||||
Default value: unix:///run/user/1000/podman/podman.sock
|
Default value: unix:///run/user/1000/podman/podman.sock
|
||||||
@ -165,20 +168,19 @@ class PluginModel(GlancesPluginModel):
|
|||||||
return "unix:///run/user/1000/podman/podman.sock"
|
return "unix:///run/user/1000/podman/podman.sock"
|
||||||
return conf_podman_sock[0]
|
return conf_podman_sock[0]
|
||||||
|
|
||||||
def exit(self):
|
def exit(self) -> None:
|
||||||
"""Overwrite the exit method to close threads."""
|
"""Overwrite the exit method to close threads."""
|
||||||
if self.docker_extension:
|
for watcher in itervalues(self.watchers):
|
||||||
self.docker_extension.stop()
|
watcher.stop()
|
||||||
if self.podman_extension:
|
|
||||||
self.podman_extension.stop()
|
|
||||||
# Call the father class
|
# Call the father class
|
||||||
super().exit()
|
super().exit()
|
||||||
|
|
||||||
def get_key(self):
|
def get_key(self) -> str:
|
||||||
"""Return the key of the list."""
|
"""Return the key of the list."""
|
||||||
return 'name'
|
return 'name'
|
||||||
|
|
||||||
def get_export(self):
|
def get_export(self) -> List[Dict]:
|
||||||
"""Overwrite the default export method.
|
"""Overwrite the default export method.
|
||||||
|
|
||||||
- Only exports containers
|
- Only exports containers
|
||||||
@ -197,7 +199,7 @@ class PluginModel(GlancesPluginModel):
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def _all_tag(self):
|
def _all_tag(self) -> bool:
|
||||||
"""Return the all tag of the Glances/Docker configuration file.
|
"""Return the all tag of the Glances/Docker configuration file.
|
||||||
|
|
||||||
# By default, Glances only display running containers
|
# By default, Glances only display running containers
|
||||||
@ -211,52 +213,35 @@ class PluginModel(GlancesPluginModel):
|
|||||||
|
|
||||||
@GlancesPluginModel._check_decorator
|
@GlancesPluginModel._check_decorator
|
||||||
@GlancesPluginModel._log_result_decorator
|
@GlancesPluginModel._log_result_decorator
|
||||||
def update(self):
|
def update(self) -> List[Dict]:
|
||||||
"""Update Docker and podman stats using the input method."""
|
"""Update Docker and podman stats using the input method."""
|
||||||
# Connection should be ok
|
# Connection should be ok
|
||||||
if self.docker_extension is None and self.podman_extension is None:
|
if not self.watchers:
|
||||||
return self.get_init_value()
|
return self.get_init_value()
|
||||||
|
|
||||||
if self.input_method == 'local':
|
if self.input_method != 'local':
|
||||||
# Update stats
|
return self.get_init_value()
|
||||||
stats_docker = self.update_docker() if self.docker_extension else {}
|
|
||||||
stats_podman = self.update_podman() if self.podman_extension else {}
|
# Update stats
|
||||||
stats = stats_docker.get('containers', []) + stats_podman.get('containers', [])
|
stats = []
|
||||||
elif self.input_method == 'snmp':
|
for engine, watcher in iteritems(self.watchers):
|
||||||
# Update stats using SNMP
|
version, containers = watcher.update(all_tag=self._all_tag())
|
||||||
# Not available
|
for container in containers:
|
||||||
pass
|
container["engine"] = 'docker'
|
||||||
|
stats.extend(containers)
|
||||||
|
|
||||||
# Sort and update the stats
|
# Sort and update the stats
|
||||||
# @TODO: Have a look because sort did not work for the moment (need memory stats ?)
|
# @TODO: Have a look because sort did not work for the moment (need memory stats ?)
|
||||||
self.sort_key, self.stats = sort_docker_stats(stats)
|
self.sort_key, self.stats = sort_docker_stats(stats)
|
||||||
|
|
||||||
return self.stats
|
return self.stats
|
||||||
|
|
||||||
def update_docker(self):
|
@staticmethod
|
||||||
"""Update Docker stats using the input method."""
|
def memory_usage_no_cache(mem: Dict[str, float]) -> float:
|
||||||
version, containers = self.docker_extension.update(all_tag=self._all_tag())
|
|
||||||
for container in containers:
|
|
||||||
container["engine"] = 'docker'
|
|
||||||
return {"version": version, "containers": containers}
|
|
||||||
|
|
||||||
def update_podman(self):
|
|
||||||
"""Update Podman stats."""
|
|
||||||
version, containers = self.podman_extension.update(all_tag=self._all_tag())
|
|
||||||
for container in containers:
|
|
||||||
container["engine"] = 'podman'
|
|
||||||
return {"version": version, "containers": containers}
|
|
||||||
|
|
||||||
def get_user_ticks(self):
|
|
||||||
"""Return the user ticks by reading the environment variable."""
|
|
||||||
return os.sysconf(os.sysconf_names['SC_CLK_TCK'])
|
|
||||||
|
|
||||||
def memory_usage_no_cache(self, mem):
|
|
||||||
"""Return the 'real' memory usage by removing inactive_file to usage"""
|
"""Return the 'real' memory usage by removing inactive_file to usage"""
|
||||||
# Ref: https://github.com/docker/docker-py/issues/3210
|
# Ref: https://github.com/docker/docker-py/issues/3210
|
||||||
return mem['usage'] - (mem['inactive_file'] if 'inactive_file' in mem else 0)
|
return mem['usage'] - (mem['inactive_file'] if 'inactive_file' in mem else 0)
|
||||||
|
|
||||||
def update_views(self):
|
def update_views(self) -> bool:
|
||||||
"""Update stats views."""
|
"""Update stats views."""
|
||||||
# Call the father's method
|
# Call the father's method
|
||||||
super().update_views()
|
super().update_views()
|
||||||
@ -305,7 +290,7 @@ class PluginModel(GlancesPluginModel):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def msg_curse(self, args=None, max_width=None):
|
def msg_curse(self, args=None, max_width: Optional[int] = None) -> List[str]:
|
||||||
"""Return the dict to display in the curse interface."""
|
"""Return the dict to display in the curse interface."""
|
||||||
# Init the return message
|
# Init the return message
|
||||||
ret = []
|
ret = []
|
||||||
@ -369,7 +354,9 @@ class PluginModel(GlancesPluginModel):
|
|||||||
if self.views['show_pod_name']:
|
if self.views['show_pod_name']:
|
||||||
ret.append(self.curse_add_line(' {:{width}}'.format(container.get("pod_id", "-"), width=12)))
|
ret.append(self.curse_add_line(' {:{width}}'.format(container.get("pod_id", "-"), width=12)))
|
||||||
# Name
|
# Name
|
||||||
ret.append(self.curse_add_line(self._msg_name(container=container, max_width=name_max_width)))
|
ret.append(
|
||||||
|
self.curse_add_line(' {:{width}}'.format(container['name'][:name_max_width], width=name_max_width))
|
||||||
|
)
|
||||||
# Status
|
# Status
|
||||||
status = self.container_alert(container['status'])
|
status = self.container_alert(container['status'])
|
||||||
msg = '{:>10}'.format(container['status'][0:10])
|
msg = '{:>10}'.format(container['status'][0:10])
|
||||||
@ -441,12 +428,8 @@ class PluginModel(GlancesPluginModel):
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def _msg_name(self, container, max_width):
|
@staticmethod
|
||||||
"""Build the container name."""
|
def container_alert(status: str) -> str:
|
||||||
name = container['name'][:max_width]
|
|
||||||
return ' {:{width}}'.format(name, width=max_width)
|
|
||||||
|
|
||||||
def container_alert(self, status):
|
|
||||||
"""Analyse the container status."""
|
"""Analyse the container status."""
|
||||||
if status == 'running':
|
if status == 'running':
|
||||||
return 'OK'
|
return 'OK'
|
||||||
@ -457,7 +440,7 @@ class PluginModel(GlancesPluginModel):
|
|||||||
return 'CAREFUL'
|
return 'CAREFUL'
|
||||||
|
|
||||||
|
|
||||||
def sort_docker_stats(stats):
|
def sort_docker_stats(stats: List[Dict[str, Any]]) -> Tuple[str, List[Dict[str, Any]]]:
|
||||||
# Sort Docker stats using the same function than processes
|
# Sort Docker stats using the same function than processes
|
||||||
sort_by = glances_processes.sort_key
|
sort_by = glances_processes.sort_key
|
||||||
sort_by_secondary = 'memory_usage'
|
sort_by_secondary = 'memory_usage'
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
from typing import Any, Dict, Protocol, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
class ContainersExtension(Protocol):
|
||||||
|
def stop(self) -> None:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def update(self, all_tag) -> Tuple[Dict, list[Dict[str, Any]]]:
|
||||||
|
raise NotImplementedError
|
@ -207,7 +207,7 @@ class DockerStatsFetcher:
|
|||||||
return stats
|
return stats
|
||||||
|
|
||||||
|
|
||||||
class DockerContainersExtension:
|
class DockerExtension:
|
||||||
"""Glances' Containers Plugin's Docker Extension unit"""
|
"""Glances' Containers Plugin's Docker Extension unit"""
|
||||||
|
|
||||||
CONTAINER_ACTIVE_STATUS = ['running', 'paused']
|
CONTAINER_ACTIVE_STATUS = ['running', 'paused']
|
||||||
|
@ -93,9 +93,9 @@ class PodmanContainerStatsFetcher:
|
|||||||
stats["network"]['tx'] = api_stats["NetOutput"]
|
stats["network"]['tx'] = api_stats["NetOutput"]
|
||||||
stats["network"]['time_since_update'] = 1
|
stats["network"]['time_since_update'] = 1
|
||||||
# Hardcode to 1 as podman already sends at the same fixed rate per second
|
# Hardcode to 1 as podman already sends at the same fixed rate per second
|
||||||
else:
|
elif api_stats["Network"] is not None:
|
||||||
|
# api_stats["Network"] can be None if the infra container of the pod is killed
|
||||||
# For podman in rootless mode
|
# For podman in rootless mode
|
||||||
# Note: No stats are being sent as of now in rootless mode. They are defaulting to 0 on podman end.
|
|
||||||
stats['network'] = {
|
stats['network'] = {
|
||||||
"cumulative_rx": sum(interface["RxBytes"] for interface in api_stats["Network"].values()),
|
"cumulative_rx": sum(interface["RxBytes"] for interface in api_stats["Network"].values()),
|
||||||
"cumulative_tx": sum(interface["TxBytes"] for interface in api_stats["Network"].values()),
|
"cumulative_tx": sum(interface["TxBytes"] for interface in api_stats["Network"].values()),
|
||||||
@ -243,7 +243,7 @@ class PodmanPodStatsFetcher:
|
|||||||
return {"ior": ior, "iow": iow, "time_since_update": 1}
|
return {"ior": ior, "iow": iow, "time_since_update": 1}
|
||||||
|
|
||||||
|
|
||||||
class PodmanContainersExtension:
|
class PodmanExtension:
|
||||||
"""Glances' Containers Plugin's Docker Extension unit"""
|
"""Glances' Containers Plugin's Docker Extension unit"""
|
||||||
|
|
||||||
CONTAINER_ACTIVE_STATUS = ['running', 'paused']
|
CONTAINER_ACTIVE_STATUS = ['running', 'paused']
|
||||||
|
@ -165,8 +165,6 @@ class PluginModel(GlancesPluginModel):
|
|||||||
stats = self.update_local()
|
stats = self.update_local()
|
||||||
elif self.input_method == 'snmp':
|
elif self.input_method == 'snmp':
|
||||||
stats = self.update_snmp()
|
stats = self.update_snmp()
|
||||||
else:
|
|
||||||
stats = self.get_init_value()
|
|
||||||
|
|
||||||
# Update the stats
|
# Update the stats
|
||||||
self.stats = stats
|
self.stats = stats
|
||||||
@ -185,7 +183,7 @@ class PluginModel(GlancesPluginModel):
|
|||||||
# Init new stats
|
# Init new stats
|
||||||
stats = self.get_init_value()
|
stats = self.get_init_value()
|
||||||
|
|
||||||
stats['total'] = cpu_percent.get()
|
stats['total'] = cpu_percent.get_cpu()
|
||||||
|
|
||||||
# Standards stats
|
# Standards stats
|
||||||
# - user: time spent by normal processes executing in user mode; on Linux this also includes guest time
|
# - user: time spent by normal processes executing in user mode; on Linux this also includes guest time
|
||||||
|
@ -114,127 +114,143 @@ class PluginModel(GlancesPluginModel):
|
|||||||
@GlancesPluginModel._log_result_decorator
|
@GlancesPluginModel._log_result_decorator
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Update the FS stats using the input method."""
|
"""Update the FS stats using the input method."""
|
||||||
# Init new stats
|
# Update the stats
|
||||||
stats = self.get_init_value()
|
|
||||||
|
|
||||||
if self.input_method == 'local':
|
if self.input_method == 'local':
|
||||||
# Update stats using the standard system lib
|
stats = self.update_local()
|
||||||
|
else:
|
||||||
# Grab the stats using the psutil disk_partitions
|
stats = self.get_init_value()
|
||||||
# If 'all'=False return physical devices only (e.g. hard disks, cd-rom drives, USB keys)
|
|
||||||
# and ignore all others (e.g. memory partitions such as /dev/shm)
|
|
||||||
try:
|
|
||||||
fs_stat = psutil.disk_partitions(all=False)
|
|
||||||
except (UnicodeDecodeError, PermissionError):
|
|
||||||
logger.debug("Plugin - fs: PsUtil fetch failed")
|
|
||||||
return self.stats
|
|
||||||
|
|
||||||
# Optional hack to allow logical mounts points (issue #448)
|
|
||||||
allowed_fs_types = self.get_conf_value('allow')
|
|
||||||
if allowed_fs_types:
|
|
||||||
# Avoid Psutil call unless mounts need to be allowed
|
|
||||||
try:
|
|
||||||
all_mounted_fs = psutil.disk_partitions(all=True)
|
|
||||||
except (UnicodeDecodeError, PermissionError):
|
|
||||||
logger.debug("Plugin - fs: PsUtil extended fetch failed")
|
|
||||||
else:
|
|
||||||
# Discard duplicates (#2299) and add entries matching allowed fs types
|
|
||||||
tracked_mnt_points = {f.mountpoint for f in fs_stat}
|
|
||||||
for f in all_mounted_fs:
|
|
||||||
if (
|
|
||||||
any(f.fstype.find(fs_type) >= 0 for fs_type in allowed_fs_types)
|
|
||||||
and f.mountpoint not in tracked_mnt_points
|
|
||||||
):
|
|
||||||
fs_stat.append(f)
|
|
||||||
|
|
||||||
# Loop over fs
|
|
||||||
for fs in fs_stat:
|
|
||||||
# Hide the stats if the mount point is in the exclude list
|
|
||||||
if not self.is_display(fs.mountpoint):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Grab the disk usage
|
|
||||||
try:
|
|
||||||
fs_usage = psutil.disk_usage(fs.mountpoint)
|
|
||||||
except OSError:
|
|
||||||
# Correct issue #346
|
|
||||||
# Disk is ejected during the command
|
|
||||||
continue
|
|
||||||
fs_current = {
|
|
||||||
'device_name': fs.device,
|
|
||||||
'fs_type': fs.fstype,
|
|
||||||
# Manage non breaking space (see issue #1065)
|
|
||||||
'mnt_point': u(fs.mountpoint).replace('\u00a0', ' '),
|
|
||||||
'size': fs_usage.total,
|
|
||||||
'used': fs_usage.used,
|
|
||||||
'free': fs_usage.free,
|
|
||||||
'percent': fs_usage.percent,
|
|
||||||
'key': self.get_key(),
|
|
||||||
}
|
|
||||||
|
|
||||||
# Hide the stats if the device name is in the exclude list
|
|
||||||
# Correct issue: glances.conf FS hide not applying #1666
|
|
||||||
if not self.is_display(fs_current['device_name']):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Add alias if exist (define in the configuration file)
|
|
||||||
if self.has_alias(fs_current['mnt_point']) is not None:
|
|
||||||
fs_current['alias'] = self.has_alias(fs_current['mnt_point'])
|
|
||||||
|
|
||||||
stats.append(fs_current)
|
|
||||||
|
|
||||||
elif self.input_method == 'snmp':
|
|
||||||
# Update stats using SNMP
|
|
||||||
|
|
||||||
# SNMP bulk command to get all file system in one shot
|
|
||||||
try:
|
|
||||||
fs_stat = self.get_stats_snmp(snmp_oid=snmp_oid[self.short_system_name], bulk=True)
|
|
||||||
except KeyError:
|
|
||||||
fs_stat = self.get_stats_snmp(snmp_oid=snmp_oid['default'], bulk=True)
|
|
||||||
|
|
||||||
# Loop over fs
|
|
||||||
if self.short_system_name in ('windows', 'esxi'):
|
|
||||||
# Windows or ESXi tips
|
|
||||||
for fs in fs_stat:
|
|
||||||
# Memory stats are grabbed in the same OID table (ignore it)
|
|
||||||
if fs == 'Virtual Memory' or fs == 'Physical Memory' or fs == 'Real Memory':
|
|
||||||
continue
|
|
||||||
size = int(fs_stat[fs]['size']) * int(fs_stat[fs]['alloc_unit'])
|
|
||||||
used = int(fs_stat[fs]['used']) * int(fs_stat[fs]['alloc_unit'])
|
|
||||||
percent = float(used * 100 / size)
|
|
||||||
fs_current = {
|
|
||||||
'device_name': '',
|
|
||||||
'mnt_point': fs.partition(' ')[0],
|
|
||||||
'size': size,
|
|
||||||
'used': used,
|
|
||||||
'percent': percent,
|
|
||||||
'key': self.get_key(),
|
|
||||||
}
|
|
||||||
# Do not take hidden file system into account
|
|
||||||
if self.is_hide(fs_current['mnt_point']):
|
|
||||||
continue
|
|
||||||
stats.append(fs_current)
|
|
||||||
else:
|
|
||||||
# Default behavior
|
|
||||||
for fs in fs_stat:
|
|
||||||
fs_current = {
|
|
||||||
'device_name': fs_stat[fs]['device_name'],
|
|
||||||
'mnt_point': fs,
|
|
||||||
'size': int(fs_stat[fs]['size']) * 1024,
|
|
||||||
'used': int(fs_stat[fs]['used']) * 1024,
|
|
||||||
'percent': float(fs_stat[fs]['percent']),
|
|
||||||
'key': self.get_key(),
|
|
||||||
}
|
|
||||||
# Do not take hidden file system into account
|
|
||||||
if self.is_hide(fs_current['mnt_point']) or self.is_hide(fs_current['device_name']):
|
|
||||||
continue
|
|
||||||
stats.append(fs_current)
|
|
||||||
|
|
||||||
# Update the stats
|
# Update the stats
|
||||||
self.stats = stats
|
self.stats = stats
|
||||||
|
|
||||||
return self.stats
|
return self.stats
|
||||||
|
|
||||||
|
def update_local(self):
|
||||||
|
"""Update the FS stats using the input method."""
|
||||||
|
# Init new stats
|
||||||
|
stats = self.get_init_value()
|
||||||
|
|
||||||
|
# Update stats using the standard system lib
|
||||||
|
|
||||||
|
# Grab the stats using the psutil disk_partitions
|
||||||
|
# If 'all'=False return physical devices only (e.g. hard disks, cd-rom drives, USB keys)
|
||||||
|
# and ignore all others (e.g. memory partitions such as /dev/shm)
|
||||||
|
try:
|
||||||
|
fs_stat = psutil.disk_partitions(all=False)
|
||||||
|
except (UnicodeDecodeError, PermissionError):
|
||||||
|
logger.debug("Plugin - fs: PsUtil fetch failed")
|
||||||
|
return stats
|
||||||
|
|
||||||
|
# Optional hack to allow logical mounts points (issue #448)
|
||||||
|
allowed_fs_types = self.get_conf_value('allow')
|
||||||
|
if allowed_fs_types:
|
||||||
|
# Avoid Psutil call unless mounts need to be allowed
|
||||||
|
try:
|
||||||
|
all_mounted_fs = psutil.disk_partitions(all=True)
|
||||||
|
except (UnicodeDecodeError, PermissionError):
|
||||||
|
logger.debug("Plugin - fs: PsUtil extended fetch failed")
|
||||||
|
else:
|
||||||
|
# Discard duplicates (#2299) and add entries matching allowed fs types
|
||||||
|
tracked_mnt_points = {f.mountpoint for f in fs_stat}
|
||||||
|
for f in all_mounted_fs:
|
||||||
|
if (
|
||||||
|
any(f.fstype.find(fs_type) >= 0 for fs_type in allowed_fs_types)
|
||||||
|
and f.mountpoint not in tracked_mnt_points
|
||||||
|
):
|
||||||
|
fs_stat.append(f)
|
||||||
|
|
||||||
|
# Loop over fs
|
||||||
|
for fs in fs_stat:
|
||||||
|
# Hide the stats if the mount point is in the exclude list
|
||||||
|
# It avoids unnecessary call to PsUtil disk_usage
|
||||||
|
if not self.is_display(fs.mountpoint):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Grab the disk usage
|
||||||
|
try:
|
||||||
|
fs_usage = psutil.disk_usage(fs.mountpoint)
|
||||||
|
except OSError:
|
||||||
|
# Correct issue #346
|
||||||
|
# Disk is ejected during the command
|
||||||
|
continue
|
||||||
|
fs_current = {
|
||||||
|
'device_name': fs.device,
|
||||||
|
'fs_type': fs.fstype,
|
||||||
|
# Manage non breaking space (see issue #1065)
|
||||||
|
'mnt_point': u(fs.mountpoint).replace('\u00a0', ' '),
|
||||||
|
'size': fs_usage.total,
|
||||||
|
'used': fs_usage.used,
|
||||||
|
'free': fs_usage.free,
|
||||||
|
'percent': fs_usage.percent,
|
||||||
|
'key': self.get_key(),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Hide the stats if the device name is in the exclude list
|
||||||
|
# Correct issue: glances.conf FS hide not applying #1666
|
||||||
|
if not self.is_display(fs_current['device_name']):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Add alias if exist (define in the configuration file)
|
||||||
|
if self.has_alias(fs_current['mnt_point']) is not None:
|
||||||
|
fs_current['alias'] = self.has_alias(fs_current['mnt_point'])
|
||||||
|
|
||||||
|
stats.append(fs_current)
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
def update_snmp(self):
|
||||||
|
"""Update the FS stats using the input method."""
|
||||||
|
# Init new stats
|
||||||
|
stats = self.get_init_value()
|
||||||
|
|
||||||
|
# Update stats using SNMP
|
||||||
|
|
||||||
|
# SNMP bulk command to get all file system in one shot
|
||||||
|
try:
|
||||||
|
fs_stat = self.get_stats_snmp(snmp_oid=snmp_oid[self.short_system_name], bulk=True)
|
||||||
|
except KeyError:
|
||||||
|
fs_stat = self.get_stats_snmp(snmp_oid=snmp_oid['default'], bulk=True)
|
||||||
|
|
||||||
|
# Loop over fs
|
||||||
|
if self.short_system_name in ('windows', 'esxi'):
|
||||||
|
# Windows or ESXi tips
|
||||||
|
for fs in fs_stat:
|
||||||
|
# Memory stats are grabbed in the same OID table (ignore it)
|
||||||
|
if fs == 'Virtual Memory' or fs == 'Physical Memory' or fs == 'Real Memory':
|
||||||
|
continue
|
||||||
|
size = int(fs_stat[fs]['size']) * int(fs_stat[fs]['alloc_unit'])
|
||||||
|
used = int(fs_stat[fs]['used']) * int(fs_stat[fs]['alloc_unit'])
|
||||||
|
percent = float(used * 100 / size)
|
||||||
|
fs_current = {
|
||||||
|
'device_name': '',
|
||||||
|
'mnt_point': fs.partition(' ')[0],
|
||||||
|
'size': size,
|
||||||
|
'used': used,
|
||||||
|
'percent': percent,
|
||||||
|
'key': self.get_key(),
|
||||||
|
}
|
||||||
|
# Do not take hidden file system into account
|
||||||
|
if self.is_hide(fs_current['mnt_point']):
|
||||||
|
continue
|
||||||
|
stats.append(fs_current)
|
||||||
|
else:
|
||||||
|
# Default behavior
|
||||||
|
for fs in fs_stat:
|
||||||
|
fs_current = {
|
||||||
|
'device_name': fs_stat[fs]['device_name'],
|
||||||
|
'mnt_point': fs,
|
||||||
|
'size': int(fs_stat[fs]['size']) * 1024,
|
||||||
|
'used': int(fs_stat[fs]['used']) * 1024,
|
||||||
|
'percent': float(fs_stat[fs]['percent']),
|
||||||
|
'key': self.get_key(),
|
||||||
|
}
|
||||||
|
# Do not take hidden file system into account
|
||||||
|
if self.is_hide(fs_current['mnt_point']) or self.is_hide(fs_current['device_name']):
|
||||||
|
continue
|
||||||
|
stats.append(fs_current)
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
def update_views(self):
|
def update_views(self):
|
||||||
"""Update stats views."""
|
"""Update stats views."""
|
||||||
# Call the father's method
|
# Call the father's method
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"""Per-CPU plugin."""
|
"""Per-CPU plugin."""
|
||||||
|
|
||||||
from glances.cpu_percent import cpu_percent
|
from glances.cpu_percent import cpu_percent
|
||||||
|
from glances.globals import BSD, LINUX, MACOS, WINDOWS
|
||||||
from glances.plugins.plugin.model import GlancesPluginModel
|
from glances.plugins.plugin.model import GlancesPluginModel
|
||||||
|
|
||||||
# Fields description
|
# Fields description
|
||||||
@ -76,9 +77,16 @@ guest operating systems under the control of the Linux kernel.',
|
|||||||
'description': '*(Linux)*: percent of time spent handling software interrupts.',
|
'description': '*(Linux)*: percent of time spent handling software interrupts.',
|
||||||
'unit': 'percent',
|
'unit': 'percent',
|
||||||
},
|
},
|
||||||
|
'dpc': {
|
||||||
|
'description': '*(Windows)*: percent of time spent handling deferred procedure calls.',
|
||||||
|
'unit': 'percent',
|
||||||
|
},
|
||||||
|
'interrupt': {
|
||||||
|
'description': '*(Windows)*: percent of time spent handling software interrupts.',
|
||||||
|
'unit': 'percent',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Define the history items list
|
# Define the history items list
|
||||||
items_history_list = [
|
items_history_list = [
|
||||||
{'name': 'user', 'description': 'User CPU usage', 'y_unit': '%'},
|
{'name': 'user', 'description': 'User CPU usage', 'y_unit': '%'},
|
||||||
@ -120,16 +128,12 @@ class PluginModel(GlancesPluginModel):
|
|||||||
@GlancesPluginModel._log_result_decorator
|
@GlancesPluginModel._log_result_decorator
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Update per-CPU stats using the input method."""
|
"""Update per-CPU stats using the input method."""
|
||||||
# Init new stats
|
# Grab per-CPU stats using psutil's
|
||||||
stats = self.get_init_value()
|
|
||||||
|
|
||||||
# Grab per-CPU stats using psutil's cpu_percent(percpu=True) and
|
|
||||||
# cpu_times_percent(percpu=True) methods
|
|
||||||
if self.input_method == 'local':
|
if self.input_method == 'local':
|
||||||
stats = cpu_percent.get(percpu=True)
|
stats = cpu_percent.get_percpu()
|
||||||
else:
|
else:
|
||||||
# Update stats using SNMP
|
# Update stats using SNMP
|
||||||
pass
|
stats = self.get_init_value()
|
||||||
|
|
||||||
# Update the stats
|
# Update the stats
|
||||||
self.stats = stats
|
self.stats = stats
|
||||||
@ -145,8 +149,17 @@ class PluginModel(GlancesPluginModel):
|
|||||||
if not self.stats or not self.args.percpu or self.is_disabled():
|
if not self.stats or not self.args.percpu or self.is_disabled():
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# Define the default header
|
# Define the headers based on OS
|
||||||
header = ['user', 'system', 'idle', 'iowait', 'steal']
|
header = ['user', 'system']
|
||||||
|
|
||||||
|
if LINUX:
|
||||||
|
header.extend(['iowait', 'idle', 'irq', 'nice', 'steal', 'guest'])
|
||||||
|
elif MACOS:
|
||||||
|
header.extend(['idle', 'nice'])
|
||||||
|
elif BSD:
|
||||||
|
header.extend(['idle', 'irq', 'nice'])
|
||||||
|
elif WINDOWS:
|
||||||
|
header.extend(['dpc', 'interrupt'])
|
||||||
|
|
||||||
# Build the string message
|
# Build the string message
|
||||||
if self.is_disabled('quicklook'):
|
if self.is_disabled('quicklook'):
|
||||||
@ -156,8 +169,6 @@ class PluginModel(GlancesPluginModel):
|
|||||||
|
|
||||||
# Per CPU stats displayed per line
|
# Per CPU stats displayed per line
|
||||||
for stat in header:
|
for stat in header:
|
||||||
if stat not in self.stats[0]:
|
|
||||||
continue
|
|
||||||
msg = f'{stat:>7}'
|
msg = f'{stat:>7}'
|
||||||
ret.append(self.curse_add_line(msg))
|
ret.append(self.curse_add_line(msg))
|
||||||
|
|
||||||
@ -183,8 +194,6 @@ class PluginModel(GlancesPluginModel):
|
|||||||
msg = '{:4} '.format('?')
|
msg = '{:4} '.format('?')
|
||||||
ret.append(self.curse_add_line(msg))
|
ret.append(self.curse_add_line(msg))
|
||||||
for stat in header:
|
for stat in header:
|
||||||
if stat not in self.stats[0]:
|
|
||||||
continue
|
|
||||||
try:
|
try:
|
||||||
msg = f'{cpu[stat]:6.1f}%'
|
msg = f'{cpu[stat]:6.1f}%'
|
||||||
except TypeError:
|
except TypeError:
|
||||||
@ -196,12 +205,10 @@ class PluginModel(GlancesPluginModel):
|
|||||||
ret.append(self.curse_new_line())
|
ret.append(self.curse_new_line())
|
||||||
if self.is_disabled('quicklook'):
|
if self.is_disabled('quicklook'):
|
||||||
ret.append(self.curse_add_line('CPU* '))
|
ret.append(self.curse_add_line('CPU* '))
|
||||||
|
|
||||||
for stat in header:
|
for stat in header:
|
||||||
if stat not in self.stats[0]:
|
percpu_stats = [i[stat] for i in percpu_list[0 : self.max_cpu_display]]
|
||||||
continue
|
cpu_stat = sum(percpu_stats) / len(percpu_stats)
|
||||||
cpu_stat = sum([i[stat] for i in percpu_list[0 : self.max_cpu_display]]) / len(
|
|
||||||
[i[stat] for i in percpu_list[0 : self.max_cpu_display]]
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
msg = f'{cpu_stat:6.1f}%'
|
msg = f'{cpu_stat:6.1f}%'
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -98,7 +98,7 @@ class GlancesPluginModel:
|
|||||||
logger.debug(f'Load section {self.plugin_name} in Glances configuration file')
|
logger.debug(f'Load section {self.plugin_name} in Glances configuration file')
|
||||||
self.load_limits(config=config)
|
self.load_limits(config=config)
|
||||||
|
|
||||||
# Init the alias (dictionnary)
|
# Init the alias (dictionary)
|
||||||
self.alias = self.read_alias()
|
self.alias = self.read_alias()
|
||||||
|
|
||||||
# Init the actions
|
# Init the actions
|
||||||
|
@ -543,7 +543,7 @@ class PluginModel(GlancesPluginModel):
|
|||||||
# Process list
|
# Process list
|
||||||
# Loop over processes (sorted by the sort key previously compute)
|
# Loop over processes (sorted by the sort key previously compute)
|
||||||
# This is a Glances bottleneck (see flame graph),
|
# This is a Glances bottleneck (see flame graph),
|
||||||
# TODO: get_process_curses_data should be optimzed
|
# TODO: get_process_curses_data should be optimized
|
||||||
for position, process in enumerate(processes_list_sorted):
|
for position, process in enumerate(processes_list_sorted):
|
||||||
ret.extend(self.get_process_curses_data(process, position == args.cursor_position, args))
|
ret.extend(self.get_process_curses_data(process, position == args.cursor_position, args))
|
||||||
|
|
||||||
|
@ -118,8 +118,8 @@ class PluginModel(GlancesPluginModel):
|
|||||||
|
|
||||||
# Get the CPU percent value (global and per core)
|
# Get the CPU percent value (global and per core)
|
||||||
# Stats is shared across all plugins
|
# Stats is shared across all plugins
|
||||||
stats['cpu'] = cpu_percent.get()
|
stats['cpu'] = cpu_percent.get_cpu()
|
||||||
stats['percpu'] = cpu_percent.get(percpu=True)
|
stats['percpu'] = cpu_percent.get_percpu()
|
||||||
|
|
||||||
# Get the virtual and swap memory
|
# Get the virtual and swap memory
|
||||||
stats['mem'] = psutil.virtual_memory().percent
|
stats['mem'] = psutil.virtual_memory().percent
|
||||||
|
@ -48,7 +48,7 @@ fields_description = {
|
|||||||
'description': 'Operating system version',
|
'description': 'Operating system version',
|
||||||
},
|
},
|
||||||
'hr_name': {
|
'hr_name': {
|
||||||
'description': 'Human readable operating sytem name',
|
'description': 'Human readable operating system name',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
"""Wifi plugin.
|
"""Wifi plugin.
|
||||||
|
|
||||||
Stats are retreived from the /proc/net/wireless file (Linux only):
|
Stats are retrieved from the /proc/net/wireless file (Linux only):
|
||||||
|
|
||||||
# cat /proc/net/wireless
|
# cat /proc/net/wireless
|
||||||
Inter-| sta-| Quality | Discarded packets | Missed | WE
|
Inter-| sta-| Quality | Discarded packets | Missed | WE
|
||||||
|
@ -119,6 +119,14 @@ class GlancesProcesses:
|
|||||||
"""Set args."""
|
"""Set args."""
|
||||||
self.args = args
|
self.args = args
|
||||||
|
|
||||||
|
def reset_internal_cache(self):
|
||||||
|
"""Reset the internal cache."""
|
||||||
|
self.cache_timer = Timer(0)
|
||||||
|
self.processlist_cache = {}
|
||||||
|
if hasattr(psutil.process_iter, 'cache_clear'):
|
||||||
|
# Cache clear only available in PsUtil 6 or higher
|
||||||
|
psutil.process_iter.cache_clear()
|
||||||
|
|
||||||
def reset_processcount(self):
|
def reset_processcount(self):
|
||||||
"""Reset the global process count"""
|
"""Reset the global process count"""
|
||||||
self.processcount = {'total': 0, 'running': 0, 'sleeping': 0, 'thread': 0, 'pid_max': None}
|
self.processcount = {'total': 0, 'running': 0, 'sleeping': 0, 'thread': 0, 'pid_max': None}
|
||||||
@ -285,7 +293,7 @@ class GlancesProcesses:
|
|||||||
# - connections (TCP and UDP)
|
# - connections (TCP and UDP)
|
||||||
# - CPU min/max/mean
|
# - CPU min/max/mean
|
||||||
|
|
||||||
# Set the extended stats list (OS dependant)
|
# Set the extended stats list (OS dependent)
|
||||||
extended_stats = ['cpu_affinity', 'ionice', 'num_ctx_switches']
|
extended_stats = ['cpu_affinity', 'ionice', 'num_ctx_switches']
|
||||||
if LINUX:
|
if LINUX:
|
||||||
# num_fds only available on Unix system (see issue #1351)
|
# num_fds only available on Unix system (see issue #1351)
|
||||||
@ -410,7 +418,7 @@ class GlancesProcesses:
|
|||||||
#####################
|
#####################
|
||||||
sorted_attrs = ['cpu_percent', 'cpu_times', 'memory_percent', 'name', 'status', 'num_threads']
|
sorted_attrs = ['cpu_percent', 'cpu_times', 'memory_percent', 'name', 'status', 'num_threads']
|
||||||
displayed_attr = ['memory_info', 'nice', 'pid']
|
displayed_attr = ['memory_info', 'nice', 'pid']
|
||||||
# The following attributes are cached and only retreive every self.cache_timeout seconds
|
# The following attributes are cached and only retrieve every self.cache_timeout seconds
|
||||||
# Warning: 'name' can not be cached because it is used for filtering
|
# Warning: 'name' can not be cached because it is used for filtering
|
||||||
cached_attrs = ['cmdline', 'username']
|
cached_attrs = ['cmdline', 'username']
|
||||||
|
|
||||||
@ -445,7 +453,9 @@ class GlancesProcesses:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
# Only get the info key
|
# Only get the info key
|
||||||
processlist = [p.info for p in processlist]
|
# PsUtil 6+ no longer check PID reused #2755 so use is_running in the loop
|
||||||
|
# Note: not sure it is realy needed but CPU consumption look the same with or without it
|
||||||
|
processlist = [p.info for p in processlist if p.is_running()]
|
||||||
# Sort the processes list by the current sort_key
|
# Sort the processes list by the current sort_key
|
||||||
processlist = sort_stats(processlist, sorted_by=self.sort_key, reverse=True)
|
processlist = sort_stats(processlist, sorted_by=self.sort_key, reverse=True)
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ class GlancesStats:
|
|||||||
"""Load additional plugins if defined"""
|
"""Load additional plugins if defined"""
|
||||||
|
|
||||||
def get_addl_plugins(self, plugin_path):
|
def get_addl_plugins(self, plugin_path):
|
||||||
"""Get list of additonal plugins"""
|
"""Get list of additional plugins"""
|
||||||
_plugin_list = []
|
_plugin_list = []
|
||||||
for plugin in os.listdir(plugin_path):
|
for plugin in os.listdir(plugin_path):
|
||||||
path = os.path.join(plugin_path, plugin)
|
path = os.path.join(plugin_path, plugin)
|
||||||
@ -167,7 +167,7 @@ class GlancesStats:
|
|||||||
sys.path.insert(0, path)
|
sys.path.insert(0, path)
|
||||||
for plugin in get_addl_plugins(self, path):
|
for plugin in get_addl_plugins(self, path):
|
||||||
if plugin in sys.modules:
|
if plugin in sys.modules:
|
||||||
logger.warn(f"Pugin {plugin} already in sys.modules, skipping (workaround: rename plugin)")
|
logger.warn(f"Plugin {plugin} already in sys.modules, skipping (workaround: rename plugin)")
|
||||||
else:
|
else:
|
||||||
start_duration.reset()
|
start_duration.reset()
|
||||||
try:
|
try:
|
||||||
@ -260,19 +260,13 @@ class GlancesStats:
|
|||||||
self._plugins[p].update_views()
|
self._plugins[p].update_views()
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Wrapper method to update the stats.
|
"""Wrapper method to update all stats.
|
||||||
|
|
||||||
Only called by standalone and server modes
|
Only called by standalone and server modes
|
||||||
"""
|
"""
|
||||||
threads = []
|
|
||||||
# Start update of all enable plugins
|
# Start update of all enable plugins
|
||||||
for p in self.getPluginsList():
|
for p in self.getPluginsList(enable=True):
|
||||||
thread = threading.Thread(target=self.__update_plugin, args=(p,))
|
self.__update_plugin(p)
|
||||||
thread.start()
|
|
||||||
threads.append(thread)
|
|
||||||
# Wait the end of the update
|
|
||||||
for t in threads:
|
|
||||||
t.join()
|
|
||||||
|
|
||||||
def export(self, input_stats=None):
|
def export(self, input_stats=None):
|
||||||
"""Export all the stats.
|
"""Export all the stats.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name: glances
|
name: glances
|
||||||
version: '4.0.8+build2'
|
version: '4.1.1+build01' # Put the current stable version+buildXX
|
||||||
|
|
||||||
summary: Glances an Eye on your system. A top/htop alternative.
|
summary: Glances an Eye on your system. A top/htop alternative.
|
||||||
description: |
|
description: |
|
||||||
|
25
test-data/issues/issue2849.py
Normal file
25
test-data/issues/issue2849.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
sys.path.insert(0, '../glances')
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
# from glances.cpu_percent import cpu_percent
|
||||||
|
|
||||||
|
# for _ in range(0, 5):
|
||||||
|
# print([i['total'] for i in cpu_percent.get_percpu()])
|
||||||
|
# time.sleep(2)
|
||||||
|
|
||||||
|
###########
|
||||||
|
|
||||||
|
from glances.main import GlancesMain
|
||||||
|
from glances.stats import GlancesStats
|
||||||
|
|
||||||
|
core = GlancesMain()
|
||||||
|
stats = GlancesStats(config=core.get_config(), args=core.get_args())
|
||||||
|
|
||||||
|
for _ in range(0, 5):
|
||||||
|
stats.update()
|
||||||
|
print([i['total'] for i in stats.get_plugin('percpu').get_raw()])
|
||||||
|
time.sleep(2)
|
Loading…
Reference in New Issue
Block a user