Solve conflicts

This commit is contained in:
nicolargo 2022-10-29 11:13:13 +02:00
commit 30f7dbc566
97 changed files with 2683 additions and 1394 deletions

View File

@ -7,7 +7,7 @@
"""
Script which downloads exe and wheel files hosted on AppVeyor:
https://ci.appveyor.com/project/giampaolo/psutil
Copied and readapted from the original recipe of Ibarra Corretge'
Copied and re-adapted from the original recipe of Ibarra Corretge'
<saghul@gmail.com>:
http://code.saghul.net/index.php/2015/09/09/
"""

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
.dockerignore
.git

View File

@ -12,6 +12,7 @@ For an enhancement or new feature: Describe your needs.
* Glances & psutil (glances -V):
* Operating System (lsb_release -a):
* How do you install Glances (Pypi package, script, package manager, source):
#### Logs

View File

@ -12,7 +12,7 @@ A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Start Glances with the followings options '...'
1. Start Glances with the following options '...'
2. Press the key '....'
3. See error

View File

@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install pip install build tools
run: >-
@ -100,43 +100,43 @@ jobs:
tag: ${{ fromJson(needs.create_Docker_builds.outputs.tags) }}
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Retrieve Repository Docker metadata
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v2.5.0
uses: crazy-max/ghaction-docker-meta@v4.1.1
with:
images: ${{ env.DEFAULT_DOCKER_IMAGE }}
labels: |
org.opencontainers.image.url=https://nicolargo.github.io/glances/
- name: Cache Docker layers
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ env.NODE_ENV }}-${{ matrix.os }}-${{ matrix.tag.tag }}
restore-keys: ${{ runner.os }}-buildx-${{ env.NODE_ENV }}-${{ matrix.os }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v2
with:
platforms: all
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v2
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v1
uses: docker/login-action@v2
if: ${{ env.PUSH_BRANCH == 'true' }}
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push image
uses: docker/build-push-action@v2
uses: docker/build-push-action@v3
with:
push: ${{ env.PUSH_BRANCH == 'true' }}
tags: "${{ env.DEFAULT_DOCKER_IMAGE }}:${{ matrix.os != 'debian' && format('{0}-', matrix.os) || '' }}${{ matrix.tag.tag }}"

View File

@ -39,7 +39,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

View File

@ -14,10 +14,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

View File

@ -61,6 +61,9 @@ format: venv-dev-upgrade ## Format the code
flake8: venv-dev-upgrade ## Run flake8 linter.
@git ls-files '*.py' | xargs ./venv/bin/python -m flake8 --config=.flake8
codespell: venv-dev-upgrade ## Run codespell to fix common misspellings in text files
./venv/bin/codespell -S .git,./docs/_build,./Glances.egg-info,./venv,./glances/outputs,*.svg -L hart,bu,te,statics
profiling: ## How to start the profiling of the Glances software
@echo "Please complete and run: sudo ./venv/bin/py-spy record -o ./docs/_static/glances-flame.svg -d 60 -s --pid <GLANCES PID>"
@ -98,6 +101,9 @@ webui: venv-dev-upgrade ## Build the Web UI
webui-audit: venv-dev-upgrade ## Audit the Web UI
cd glances/outputs/static/ && npm audit
webui-audit-fix: venv-dev-upgrade ## Fix audit the Web UI
cd glances/outputs/static/ && npm audit fix && npm ci && npm run build
# ===================================================================
# Packaging
# ===================================================================
@ -108,6 +114,22 @@ flatpak: venv-dev-upgrade ## Generate FlatPack JSON file
rm -rf ./flatpak-builder-tools
@echo "Now follow: https://github.com/flathub/flathub/wiki/App-Submission"
# ===================================================================
# Docker
# ===================================================================
docker: docker-alpine docker-debian
docker-alpine:
docker build --target full -f ./docker-files/alpine.Dockerfile -t glances:local-alpine-full .
docker build --target minimal -f ./docker-files/alpine.Dockerfile -t glances:local-alpine-minimal .
docker build --target dev -f ./docker-files/alpine.Dockerfile -t glances:local-alpine-dev .
docker-debian:
docker build --target full -f ./docker-files/debian.Dockerfile -t glances:local-debian-full .
docker build --target minimal -f ./docker-files/debian.Dockerfile -t glances:local-debian-minimal .
docker build --target dev -f ./docker-files/debian.Dockerfile -t glances:local-debian-dev .
# ===================================================================
# Run
# ===================================================================
@ -118,6 +140,27 @@ run: ## Start Glances in console mode (also called standalone)
run-debug: ## Start Glances in debug console mode (also called standalone)
./venv/bin/python -m glances -C ./conf/glances.conf -d
run-local-conf: ## Start Glances in console mode with the system conf file
./venv/bin/python -m glances
run-docker-alpine-minimal: ## Start Glances Alpine Docker minimal in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-alpine-minimal
run-docker-alpine-full: ## Start Glances Alpine Docker full in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-alpine-full
run-docker-alpine-dev: ## Start Glances Alpine Docker dev in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-alpine-dev
run-docker-debian-minimal: ## Start Glances Debian Docker minimal in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-debian-minimal
run-docker-debian-full: ## Start Glances Debian Docker full in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-debian-full
run-docker-debian-dev: ## Start Glances Debian Docker dev in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-debian-dev
run-webserver: ## Start Glances in Web server mode
./venv/bin/python -m glances -C ./conf/glances.conf -w

100
NEWS.rst
View File

@ -2,11 +2,63 @@
Glances changelog
==============================================================================
===============
Version 3.3.1
===============
Under development, see milestone https://github.com/nicolargo/glances/milestone/61
===============
Version 3.3.0
===============
Version under development: see roadmap here https://github.com/nicolargo/glances/milestone/60
Enhancements:
* Migration from AngularJS to Angular/React/Vue #2100 (many thanks to @fr4nc0is)
* Improve the IP module with a link to Censys #2105
* Add the public IP information to the WebUI #2105
* Add an option to show a configurable clock/time module to display #2150
* Add sort information on Docker plugin (console mode). Related to #2138
* Password files in same configuration dir in effect #2143
* If the container name is long, then display the start, not the end - Related to #1732
* Make the Web UI same than Console for CPU plugin
* [WINDOWS] Reorganise CPU stats display #2131
* Remove the static exportable_plugins list from glances_export.py #1556
* Limiting data exported for economic storage #1443
Bug corrected:
* glances.conf FS hide not applying #1666
* AMP: regex with special chars #2152
* fix(help-screen): add missing shortcuts and columnize algorithmically #2135
* Correct issue with the regexp filter (use fullmatch instead of match)
* Errors when running Glances as web service #1702
* Apply alias to Duplicate sensor name #1686
* Make the hide function in sensors section compliant with lower/upercase #1590
* Web UI truncates the days part of CPU time counter of the process list #2108
* Correct alignement issue with the diskio plugin (Console UI)
Documentation and CI:
* Refactor Docker file CI
* Add Codespell to the CI pipeline #2148
* Please add docker-compose example and document example. #2151
* [DOC] Glances failed to start and some other issues - BSD #2106
* [REQUEST Docker image] Output log to stdout #2128 (for debian)
* Fix code scanning alert - Clear-text logging of sensitive information #2124
* Improve makefile (with online documentation)
* buildx failed with: ERROR: failed to solve: python:3.10-slim-buster: no match for platform in manifest #2120
* [Update docs] Can I export only the fields I need in csv report #2113
* Windows Python 3 installation fails on dependency package "future" #2109
Contributors for this version:
* fr4nc0is : a very special thanks to @fr4nc0is for his huge work on the Glances v3.3.0 WebUI !!!
* Kostis Anagnostopoulos
* Kian-Meng Ang
* dependabot[bot]
* matthewaaronthacker
* and your servant Nicolargo
===============
Version 3.2.7
@ -18,8 +70,8 @@ Enhancements:
* Keybind(s) for modifying nice level #2081
* [WEBUI] Reorganize help screen #2037
* Add a Json stdout option #2060
* Improve error message when export error occures
* Improve error message when MQTT error occures
* Improve error message when export error occurs
* Improve error message when MQTT error occurs
* Change the way core are displayed
* Remove unused key in the process list
* Refactor top menu of the curse interface
@ -126,7 +178,7 @@ Bugs corrected:
* Failure to start on Apple M1 Max #1939
* Influxdb2 via SSL #1934
* Update WebUI (security patch). Thanks to @notFloran.
* Swith from black <> white theme with the '9' hotkey - Related to issue #976
* Switch from black <> white theme with the '9' hotkey - Related to issue #976
* Fix: Docker plugin - Invalid IO stats with Arch Linux #1945
* Bug Fix: Docker plugin - Network stats not being displayed #1944
* Fix Grafana CPU temperature panel #1954
@ -219,7 +271,7 @@ Enhancement and development requests:
- Add caching for processing username and cmdline
- Correct and improve refresh time method
- Set refresh rate for global CPU percent
- Set the dafault refresh rate of system stats to 60 seconds
- Set the default refresh rate of system stats to 60 seconds
- Default refresh time for sensors is refresh rate * 2
- Improve history perf
- Change main curses loop
@ -301,7 +353,7 @@ Version 3.1.6.1
Bugs corrected:
* Glances crash after installing module for shown GPU informations on Windows 10 #1800
* Glances crash after installing module for shown GPU information on Windows 10 #1800
Version 3.1.6
=============
@ -359,7 +411,7 @@ Enhancements and new features:
* Enhancement: RSS for containers enhancement #1694
* exports: support rabbitmq amqps enhancement #1687
* Quick Look missing CPU Infos enhancement #1685
* Add amqps protocol suppport for rabbitmq export #1688
* Add amqps protocol support for rabbitmq export #1688
* Select host in Grafana json #1684
* Value for free disk space is counterintuative on ext file systems enhancement #644
@ -403,7 +455,7 @@ Bugs corrected:
* Disk IO stats missing after upgrade to 5.5.x kernel #1601
* Glances don't want to run on Crostini (LXC Container, Debian 10, python 3.7.3) #1600
* Kafka key name needs to be bytes #1593
* Cant start glances with glances --export mqtt #1581
* Can't start glances with glances --export mqtt #1581
* [WEBUI] AMP plugins is not displayed correctly in the Web Interface #1574
* Unhandled AttributeError when no config files found #1569
* Glances writing lots of Docker Error message in logs file enhancement #1561
@ -641,7 +693,7 @@ Graph:
# generate_every to a non zero value corresponding to the seconds between
# two generation. Set it to 0 to disable graph auto generation.
generate_every=60
# See followings configuration keys definitions in the Pygal lib documentation
# See following configuration keys definitions in the Pygal lib documentation
# http://pygal.org/en/stable/documentation/index.html
width=800
height=600
@ -701,7 +753,7 @@ Bugs corrected:
* glances_network `OSError: [Errno 19] No such device` (issue #1106)
* GPU plugin. <class 'TypeError'>: ... not JSON serializable"> (issue #1112)
* PermissionError on macOS (issue #1120)
* Cant move up or down in glances --browser (issue #1113)
* Can't move up or down in glances --browser (issue #1113)
* Unable to give aliases to or hide network interfaces and disks (issue #1126)
* `UnicodeDecodeError` on mountpoints with non-breaking spaces (issue #1128)
@ -758,7 +810,7 @@ Bugs corrected:
* On Windows --export-statsd terminates immediately and does not export (issue #1067)
* Glances v2.8.7 issues with Curses UI on Android (issue #1053)
* Fails to start, OSError in sensors_temperatures (issue #1057)
* Crashs after long time running the glances --browser (issue #1059)
* Crashes after long time running the glances --browser (issue #1059)
* Sensor values don't refresh since psutil backend (issue #1061)
* glances-version.db Permission denied (issue #1066)
@ -857,7 +909,7 @@ Enhancements and new features:
* Not compatible with the new Docker API 2.0 (Docker 1.13) (issue #1000)
* Add ZeroMQ exporter (issue #939)
* Add CouchDB exporter (issue #928)
* Add hotspot Wifi informations (issue #937)
* Add hotspot Wifi information (issue #937)
* Add default interface speed and automatic rate thresolds (issue #718)
* Highlight max stats in the processes list (issue #878)
* Docker alerts and actions (issue #875)
@ -880,8 +932,8 @@ Version 2.7.1
Bugs corrected:
* AMP plugin crashs on start with Python 3 (issue #917)
* Ports plugin crashs on start with Python 3 (issue #918)
* AMP plugin crashes on start with Python 3 (issue #917)
* Ports plugin crashes on start with Python 3 (issue #918)
Version 2.7
===========
@ -902,7 +954,7 @@ Enhancements and new features:
* Add a new "Ports scanner" plugin (issue #734)
* Add a new IRQ monitoring plugin (issue #911)
* Improve IP plugin to display public IP address (issue #646)
* CPU additionnal stats monitoring: Context switch, Interrupts... (issue #810)
* CPU additional stats monitoring: Context switch, Interrupts... (issue #810)
* Filter processes by others stats (username) (issue #748)
* [Folders] Differentiate permission issue and non-existence of a directory (issue #828)
* [Web UI] Add cpu name in quicklook plugin (issue #825)
@ -1042,10 +1094,10 @@ Enhancements and new features:
Bugs corrected:
* The WebUI displays bad sensors stats (issue #632)
* Filter processes crashs with a bad regular expression pattern (issue #665)
* Filter processes crashes with a bad regular expression pattern (issue #665)
* Error with IP plugin (issue #651)
* Crach with Docker plugin (issue #649)
* Docker plugin crashs with webserver mode (issue #654)
* Docker plugin crashes with webserver mode (issue #654)
* Infrequently crashing due to assert (issue #623)
* Value for free disk space is counterintuative on ext file systems (issue #644)
* Try/catch for unexpected psutil.NoSuchProcess: process no longer exists (issue #432)
@ -1125,7 +1177,7 @@ Enhancements and new features:
* Add InfluxDB export module (--export-influxdb) (issue #455)
* Add StatsD export module (--export-statsd) (issue #465)
* Refactor export module (CSV export option is now --export-csv). It is now possible to export stats from the Glances client mode (issue #463)
* The Web inteface is now based on Bootstrap / RWD grid (issue #417, #366 and #461) Thanks to Nicolas Hart @nclsHart
* The Web interface is now based on Bootstrap / RWD grid (issue #417, #366 and #461) Thanks to Nicolas Hart @nclsHart
* It is now possible, through the configuration file, to define if an alarm should be logged or not (using the _log option) (issue #437)
* You can now set alarm for Disk IO
* API: add getAllLimits and getAllViews methods (issue #481) and allow CORS request (issue #479)
@ -1181,7 +1233,7 @@ Version 2.1.1
Enhancement:
* Automaticaly compute top processes number for the current screen (issue #408)
* Automatically compute top processes number for the current screen (issue #408)
* CPU and Memory footprint optimization (issue #401)
Bugs corrected:
@ -1190,7 +1242,7 @@ Bugs corrected:
* Process no longer exists (issue #421)
* Error with Glances Client with Python 3.4.1 (issue #419)
* TypeError: memory_maps() takes exactly 2 arguments (issue #413)
* No filesystem informations since Glances 2.0 bug enhancement (issue #381)
* No filesystem information since Glances 2.0 bug enhancement (issue #381)
Version 2.1
===========
@ -1200,7 +1252,7 @@ Version 2.1
The pattern could be defined from the command line (-f <pattern>)
or by pressing the ENTER key in the curse interface.
For the moment, process filter feature is only available in standalone mode.
* Add extended processes informations for top process
* Add extended processes information for top process
Top process stats availables: CPU affinity, extended memory information (shared, text, lib, datat, dirty, swap), open threads/files and TCP/UDP network sessions, IO nice level
For the moment, extended processes stats are only available in standalone mode.
* Add --process-short-name tag and '/' key to switch between short/command line
@ -1396,7 +1448,7 @@ Version 1.6.1
* Key 'u' shows cumulative net traffic
* Work in improving autoUnit
* Take into account the number of core in the CPU process limit
* API improvment add time_since_update for disk, process_disk and network
* API improvement add time_since_update for disk, process_disk and network
* Improve help display
* Add more dummy FS to the ignore list
* Code refactory: psutil < 0.4.1 is deprecated (Thk to Alessio)
@ -1504,7 +1556,7 @@ Version 1.3.7
=============
* Display (if terminal space is available) an alerts history (logs)
* Add a limits classe to manage stats limits
* Add a limits class to manage stats limits
* Manage black and white console (issue #31)
Version 1.3.6
@ -1533,7 +1585,7 @@ Version 1.3.4
Version 1.3.3
=============
* Automatically swith between process short and long name
* Automatically switch between process short and long name
* Center the host / system information
* Always put the hour/date in the bottom/right
* Correct a bug if there is a lot of Disk/IO

View File

@ -57,15 +57,6 @@ Glances is written in Python and uses libraries to grab information from
your system. It is based on an open architecture where developers can
add new plugins or exports modules.
Social networks
===============
.. image:: https://raw.githubusercontent.com/nicolargo/glances/develop/docs/_static/twitter-icon.png
:target: https://twitter.com/nicolargo
.. image:: https://raw.githubusercontent.com/nicolargo/glances/develop/docs/_static/reddit.png
:target: https://www.reddit.com/r/glances/
Requirements
============
@ -80,6 +71,7 @@ Please uses Glances version 3 if you need Python 2 support.
Optional dependencies:
- ``batinfo`` (for battery monitoring)
- ``bernhard`` (for the Riemann export module)
- ``bottle`` (for Web server mode)
- ``cassandra-driver`` (for the Cassandra export module)
@ -142,7 +134,7 @@ To install it, use the following command:
pip install --user 'glances[web]'
For a full installation (with all features:
For a full installation (with all features):
.. code-block:: console
@ -190,16 +182,18 @@ Get the Glances container:
.. code-block:: console
docker pull nicolargo/glances:<version>
docker pull nicolargo/glances:alpine-latest-full
Available versions on the Docker Hub repository:
The following tags are availables:
- *nicolargo/glances:latest* for a basic Debian Glances image version with minimal dependencies
- *nicolargo/glances:alpine-latest* for a basic Alpine Glances image version with minimal dependencies
- *nicolargo/glances:latest-full* for a full Debian Glances image version with all dependencies
- *nicolargo/glances:alpine-latest-full* for a full Alpine Glances image version with all dependencies
- *alpine-latest-full* for a full Alpine Glances image (latest release) with all dependencies
- *latest-full* for a full Debian Glances image (latest release) with all dependencies
- *alpine-latest* for a basic Alpine Glances (latest release) version with minimal dependencies
- *latest* for a basic Debian Glances image (latest release) with minimal dependencies
- *alpine-dev* for a basic Alpine Glances image (development branch) with all dependencies
- *dev* for a basic Debian Glances image (development branch) with all dependencies
You can also specify a version by replacing latest by 3.2.6.4 (for example).
You can also specify a version (example: *alpine-3.2.7-full*).
Run last version of Glances container in *console mode*:
@ -242,7 +236,8 @@ may not be the latest version.
Note: The Debian package (and all other Debian-based distributions) do
not include anymore the JS statics files used by the Web interface
(see ``issue2021``).
(see ``issue2021``). If you want to add it to your Glances installation,
follow the instructions: ``issue2021comment``.
FreeBSD
-------
@ -406,7 +401,7 @@ or in a CSV format thanks to the stdout-csv option:
2018-12-08 22:04:23 CEST,5.4,5949136896,4,1.04,0.99,1.04
...
or in a JSON format thanks to the stdout-json option (attibute not supported in this mode in order to have a real JSON object in output):
or in a JSON format thanks to the stdout-json option (attribute not supported in this mode in order to have a real JSON object in output):
.. code-block:: console
@ -446,7 +441,9 @@ Donation
If you like this open-source project, you can become a sponsor.
See the sponsors_ page (one-time or monthly tier available).
See the Github sponsors_ page (one-time or monthly tier available).
Or send me some bitcoins: 185KN9FCix3svJYp7JQM7hRMfSKyeaJR4X
Author
======
@ -470,4 +467,5 @@ Glances is distributed under the LGPL version 3 license. See ``COPYING`` for mor
.. _wiki: https://github.com/nicolargo/glances/wiki/How-to-contribute-to-Glances-%3F
.. _package: https://repology.org/metapackage/glances/packages
.. _sponsors: https://github.com/sponsors/nicolargo
.. _issue2021: https://github.com/nicolargo/glances/issues/2021#issuecomment-1197831157
.. _issue2021: https://github.com/nicolargo/glances/issues/2021#issuecomment-1197831157
.. _issue2021comment: https://github.com/nicolargo/glances/issues/2021#issuecomment-1197831157

View File

@ -181,7 +181,7 @@ public_ip_disabled=False
# Need to create an aacount: https://censys.io/login
censys_url=https://search.censys.io/api
# Get your own credential here: https://search.censys.io/account/api
# Enter your creadential and uncomment the following lines
# Enter your credential and uncomment the following lines
#censys_username=<censys_api_id>
#censys_password=<censys_secret>
# List of fields to be displayed in user interface (comma separated)
@ -220,9 +220,9 @@ hide=loop.*,/dev/loop*
[fs]
disable=False
# Define the list of hidden file system (comma-separated regexp)
# Define the list of file system to hide (comma-separated regexp)
hide=/boot.*,/snap.*
# Define the list of file system to be show (comma-separated)
# Define the list of file system to show (comma-separated regexp)
#show=/,/srv
# Define filesystem space thresholds in %
# Default values if not defined: 50/70/90
@ -249,7 +249,7 @@ disable=False
# * careful: optional careful threshold (in MB)
# * warning: optional warning threshold (in MB)
# * critical: optional critical threshold (in MB)
# * refresh: interval in second between two refreshs
# * refresh: interval in second between two refreshes
#folder_1_path=/tmp
#folder_1_careful=2500
#folder_1_warning=3000
@ -372,7 +372,7 @@ port_default_gateway=True
# web_x_url is the URL to monitor (example: http://my.site.com/folder)
# web_x_description is optional (if not set, define to URL)
# web_x_timeout is optional and overwrite the default timeout value
# web_x_rtt_warning is optional and defines the warning respond time in ms (approximatively)
# web_x_rtt_warning is optional and defines the warning respond time in ms (approximately)
#
#web_1_url=https://blog.nicolargo.com
#web_1_description=My Blog
@ -385,10 +385,10 @@ port_default_gateway=True
[docker]
disable=False
# Only show specific containers (comma separeted list of container name or regular expression)
# Only show specific containers (comma separated list of container name or regular expression)
# Comment this line to display all containers (default configuration)
#show=telegraf
# Hide some containers (comma separeted list of container name or regular expression)
# Hide some containers (comma separated list of container name or regular expression)
# Comment this line to display all containers (default configuration)
#hide=telegraf
# Define the maximum docker size name (default is 20 chars)
@ -432,13 +432,16 @@ disable=False
#server_4_port=61237
[passwords]
# Define the passwords list
# Define the passwords list related to the [serverlist] section
# Syntax: host=password
# Where: host is the hostname
# password is the clear password
# Additionally (and optionally) a default password could be defined
#localhost=abc
#default=defaultpassword
#
# Define the path of the local '.pwd' file (default is system one)
#local_password_path=~/.config/glances
##############################################################################
# Exports
@ -453,7 +456,7 @@ path=/tmp
# generate_every to a non zero value corresponding to the seconds between
# two generation. Set it to 0 to disable graph auto generation.
generate_every=60
# See followings configuration keys definitions in the Pygal lib documentation
# See following configuration keys definitions in the Pygal lib documentation
# http://pygal.org/en/stable/documentation/index.html
width=800
height=600
@ -478,7 +481,7 @@ db=glances
# => foo.mem
# You can also use dynamic values
#prefix=foo
# Followings tags will be added for all measurements
# Following tags will be added for all measurements
# You can also use dynamic values.
# Note: hostname is always added as a tag
#tags=foo:bar,spam:eggs,domain:`domainname`
@ -498,7 +501,7 @@ token=EjFUTWe8U-MIseEAkaVIgVnej_TrnbdvEcRkaB1imstW7gapSqy6_6-8XD-yd51V0zUUpDy-kA
# => foo.mem
# You can also use dynamic values
#prefix=foo
# Followings tags will be added for all measurements
# Following tags will be added for all measurements
# You can also use dynamic values.
# Note: hostname is always added as a tag
#tags=foo:bar,spam:eggs,domain:`domainname`
@ -574,6 +577,7 @@ host=localhost
port=5984
db=glances
# user and password are optional (comment if not configured on the server side)
# If they are used, then the https protocol will be used
#user=root
#password=root

View File

@ -5,3 +5,4 @@ requirements-parser
flake8
autopep8
autoflake
codespell

View File

@ -1,3 +1,3 @@
FROM nicolargo/glances:dev
FROM nicolargo/glances:alpine-dev
COPY glances.conf /glances/conf/glances.conf
CMD python -m glances -C /glances/conf/glances.conf $GLANCES_OPT

View File

@ -0,0 +1,29 @@
version: "3.9"
services:
reverse-proxy:
image: traefik
command: --api --docker
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
whoami:
image: emilevauge/whoami
labels:
- "traefik.frontend.rule=Host:whoami.docker.localhost"
monitoring:
image: nicolargo/glances:alpine-dev
restart: unless-stopped
pid: host
privileged: true
network_mode: "host"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "GLANCES_OPT=-w"
labels:
- "traefik.port=61208"
- "traefik.frontend.rule=Host:glances.docker.localhost"

View File

@ -1,4 +1,4 @@
version: '3.7'
version: '3.9'
services:
glances:
build:
@ -13,3 +13,5 @@ services:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./glances.conf:/glances/conf/glances.conf"
pid: "host"
privileged: true
network_mode: "host"

View File

@ -175,6 +175,17 @@ tx_critical=90
[ip]
disable=False
public_refresh_interval=300
public_ip_disabled=False
# Configuration for the Censys online service
# Need to create an aacount: https://censys.io/login
censys_url=https://search.censys.io/api
# Get your own credential here: https://search.censys.io/account/api
# Enter your credential and uncomment the following lines
#censys_username=<censys_api_id>
#censys_password=<censys_secret>
# List of fields to be displayed in user interface (comma separated)
censys_fields=location:continent,location:country,autonomous_system:name
[connections]
# Display additional information about TCP connections
@ -209,9 +220,9 @@ hide=loop.*,/dev/loop*
[fs]
disable=False
# Define the list of hidden file system (comma-separated regexp)
# Define the list of file system to hide (comma-separated regexp)
hide=/boot.*,/snap.*
# Define the list of file system to be show (comma-separated)
# Define the list of file system to show (comma-separated regexp)
#show=/,/srv
# Define filesystem space thresholds in %
# Default values if not defined: 50/70/90
@ -238,7 +249,7 @@ disable=False
# * careful: optional careful threshold (in MB)
# * warning: optional warning threshold (in MB)
# * critical: optional critical threshold (in MB)
# * refresh: interval in second between two refreshs
# * refresh: interval in second between two refreshes
#folder_1_path=/tmp
#folder_1_careful=2500
#folder_1_warning=3000
@ -290,6 +301,9 @@ battery_critical=95
# Sensors alias
#temp1_alias=Motherboard 0
#temp2_alias=Motherboard 1
#core 0_temperature_core_alias=CPU Core 0 temp
#core 0_fans_speed_alias=CPU Core 0 fan
#or
#core 0_alias=CPU Core 0
#core 1_alias=CPU Core 1
@ -359,7 +373,7 @@ port_default_gateway=True
# web_x_url is the URL to monitor (example: http://my.site.com/folder)
# web_x_description is optional (if not set, define to URL)
# web_x_timeout is optional and overwrite the default timeout value
# web_x_rtt_warning is optional and defines the warning respond time in ms (approximatively)
# web_x_rtt_warning is optional and defines the warning respond time in ms (approximately)
#
#web_1_url=https://blog.nicolargo.com
#web_1_description=My Blog
@ -372,10 +386,10 @@ port_default_gateway=True
[docker]
disable=False
# Only show specific containers (comma separeted list of container name or regular expression)
# Only show specific containers (comma separated list of container name or regular expression)
# Comment this line to display all containers (default configuration)
#show=telegraf
# Hide some containers (comma separeted list of container name or regular expression)
# Hide some containers (comma separated list of container name or regular expression)
# Comment this line to display all containers (default configuration)
#hide=telegraf
# Define the maximum docker size name (default is 20 chars)
@ -419,13 +433,16 @@ disable=False
#server_4_port=61237
[passwords]
# Define the passwords list
# Define the passwords list related to the [serverlist] section
# Syntax: host=password
# Where: host is the hostname
# password is the clear password
# Additionally (and optionally) a default password could be defined
#localhost=abc
#default=defaultpassword
#
# Define the path of the local '.pwd' file (default is system one)
#local_password_path=~/.config/glances
##############################################################################
# Exports
@ -440,7 +457,7 @@ path=/tmp
# generate_every to a non zero value corresponding to the seconds between
# two generation. Set it to 0 to disable graph auto generation.
generate_every=60
# See followings configuration keys definitions in the Pygal lib documentation
# See following configuration keys definitions in the Pygal lib documentation
# http://pygal.org/en/stable/documentation/index.html
width=800
height=600
@ -465,7 +482,7 @@ db=glances
# => foo.mem
# You can also use dynamic values
#prefix=foo
# Followings tags will be added for all measurements
# Following tags will be added for all measurements
# You can also use dynamic values.
# Note: hostname is always added as a tag
#tags=foo:bar,spam:eggs,domain:`domainname`
@ -485,7 +502,7 @@ token=EjFUTWe8U-MIseEAkaVIgVnej_TrnbdvEcRkaB1imstW7gapSqy6_6-8XD-yd51V0zUUpDy-kA
# => foo.mem
# You can also use dynamic values
#prefix=foo
# Followings tags will be added for all measurements
# Following tags will be added for all measurements
# You can also use dynamic values.
# Note: hostname is always added as a tag
#tags=foo:bar,spam:eggs,domain:`domainname`
@ -561,6 +578,7 @@ host=localhost
port=5984
db=glances
# user and password are optional (comment if not configured on the server side)
# If they are used, then the https protocol will be used
#user=root
#password=root

View File

@ -1,38 +1,11 @@
# Dockerfiles
The Dockerfiles used here are using multi-staged builds.
For building a specific stage locally docker needs to know the target stage with `--target`.
```bash
make docker
```
## Examples for Debian images
Then test the image with:
For the dev image:
``bash
docker build --target dev -f ./docker-files/debian.Dockerfile -t glances:dev .
``
For the minimal image:
``bash
docker build --target minimal -f ./docker-files/debian.Dockerfile -t glances:minimal .
``
For the full image:
``bash
docker build --target full -f ./docker-files/debian.Dockerfile -t glances:full .
``
## Examples for Alpine images
For the dev image:
``bash
docker build --target dev -f ./docker-files/alpine.Dockerfile -t glances:dev .
``
For the minimal image:
``bash
docker build --target minimal -f ./docker-files/alpine.Dockerfile -t glances:minimal .
``
For the full image:
``bash
docker build --target full -f ./docker-files/alpine.Dockerfile -t glances:full .
``
```bash
make run-docker-alpine-dev
```

View File

@ -28,36 +28,43 @@ RUN apk add --no-cache \
wireless-tools \
iputils
FROM build as remoteInstall
ARG PYTHON_VERSION
##############################################################################
# Install the dependencies beforehand to make them cacheable
FROM build as buildRequirements
ARG PYTHON_VERSION
COPY requirements.txt .
COPY webui-requirements.txt .
RUN pip3 install --no-cache-dir --user -r requirements.txt
# Minimal means no webui, but it break what is done previously (see #2155)
# So install the webui requirements...
RUN pip3 install --no-cache-dir --user -r webui-requirements.txt
# As minimal image we want to monitor others docker containers
RUN pip3 install --no-cache-dir --user docker
# Force install otherwise it could be cached without rerun
ARG CHANGING_ARG
RUN pip3 install --no-cache-dir --user glances[all]
RUN pip3 install --no-cache-dir --user glances
##############################################################################
FROM build as additional-packages
FROM build as buildOptionalRequirements
ARG PYTHON_VERSION
COPY *requirements.txt ./
COPY requirements.txt .
COPY optional-requirements.txt .
RUN CASS_DRIVER_NO_CYTHON=1 pip3 install --no-cache-dir --user -r optional-requirements.txt
##############################################################################
# dev image
# full image
##############################################################################
FROM build as dev
FROM build as full
ARG PYTHON_VERSION
COPY --from=remoteInstall /root/.local/bin /usr/local/bin/
COPY --from=remoteInstall /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=additional-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/site-packages/
COPY . /glances
COPY --from=buildRequirements /root/.local/bin /usr/local/bin/
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=buildOptionalRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/site-packages/
COPY ./docker-compose/glances.conf /etc/glances.conf
# EXPOSE PORT (XMLRPC / WebUI)
@ -72,7 +79,7 @@ CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT
# minimal image
##############################################################################
#Create running images without any building dependency
# Create running images without any building dependency
FROM alpine:${IMAGE_VERSION} as minimal
ARG PYTHON_VERSION
@ -83,28 +90,39 @@ RUN apk add --no-cache \
wireless-tools \
iputils
COPY --from=remoteInstall /root/.local/bin /usr/local/bin/
COPY --from=remoteInstall /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=buildRequirements /root/.local/bin /usr/local/bin/
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/site-packages/
COPY ./docker-compose/glances.conf /etc/glances.conf
# EXPOSE PORT (XMLRPC)
# EXPOSE PORT (XMLRPC only because WebUI is not available)
EXPOSE 61209
# Define default command.
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT
##############################################################################
# full image
# dev image
##############################################################################
FROM minimal as full
FROM full as dev
ARG PYTHON_VERSION
COPY --from=additional-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=buildRequirements /root/.local/bin /usr/local/bin/
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=buildOptionalRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/lib/python${PYTHON_VERSION}/site-packages/
COPY ./docker-compose/glances.conf /etc/glances.conf
# Copy the current Glances source code
COPY . /glances
# EXPOSE PORT (XMLRPC / WebUI)
EXPOSE 61209 61208
# Forward access and error logs to Docker's log collector
RUN ln -sf /dev/stdout /tmp/glances-root.log \
&& ln -sf /dev/stderr /var/log/error.log
WORKDIR /glances
# Define default command.
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT

View File

@ -5,11 +5,11 @@
#
# WARNING: the version should be set.
# Ex: Python 3.10 for 3.10-slim-buster
# Ex: Python 3.11 for 3.11-slim-buster
# Note: ENV is for future running containers. ARG for building your Docker image.
ARG IMAGE_VERSION=3.10-slim-buster
ARG PYTHON_VERSION=3.10
ARG PYTHON_IMAGE_VERSION=3.11
ARG IMAGE_VERSION=${PYTHON_IMAGE_VERSION}-slim-buster
FROM python:${IMAGE_VERSION} as build
ARG PYTHON_VERSION
@ -25,36 +25,44 @@ RUN apt-get update && \
iputils-ping && \
apt-get clean && rm -rf /var/lib/apt/lists/*
FROM build as remoteInstall
ARG PYTHON_VERSION
##############################################################################
# Install the dependencies beforehand to make them cacheable
FROM build as buildRequirements
ARG PYTHON_VERSION
COPY requirements.txt .
COPY webui-requirements.txt .
RUN pip3 install --no-cache-dir --user -r requirements.txt
# Minimal means no webui, but it break what is done previously (see #2155)
# So install the webui requirements...
RUN pip3 install --no-cache-dir --user -r webui-requirements.txt
# As minimal image we want to monitor others docker containers
RUN pip3 install --no-cache-dir --user docker
# Force install otherwise it could be cached without rerun
ARG CHANGING_ARG
RUN pip3 install --no-cache-dir --user glances[all]
RUN pip3 install --no-cache-dir --user glances
##############################################################################
FROM build as additional-packages
FROM build as buildOptionalRequirements
ARG PYTHON_VERSION
COPY *requirements.txt ./
COPY requirements.txt .
COPY optional-requirements.txt .
RUN CASS_DRIVER_NO_CYTHON=1 pip3 install --no-cache-dir --user -r optional-requirements.txt
##############################################################################
# dev image
# full image
##############################################################################
FROM build as dev
FROM build as full
ARG PYTHON_VERSION
ARG PYTHON_IMAGE_VERSION
COPY --from=remoteInstall /root/.local/bin /usr/local/bin/
COPY --from=remoteInstall /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/local/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=additional-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/local/lib/python${PYTHON_VERSION}/site-packages/
COPY . /glances
COPY --from=buildRequirements /root/.local/bin /usr/local/bin/
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_IMAGE_VERSION}/site-packages /usr/local/lib/python${PYTHON_IMAGE_VERSION}/site-packages/
COPY --from=buildOptionalRequirements /root/.local/lib/python${PYTHON_IMAGE_VERSION}/site-packages /usr/local/lib/python${PYTHON_IMAGE_VERSION}/site-packages/
COPY ./docker-compose/glances.conf /etc/glances.conf
# EXPOSE PORT (XMLRPC / WebUI)
@ -72,6 +80,7 @@ CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT
# Create running images without any building dependency
FROM python:${IMAGE_VERSION} as minimal
ARG PYTHON_VERSION
ARG PYTHON_IMAGE_VERSION
RUN apt-get update && \
apt-get install -y --no-install-recommends \
@ -82,8 +91,8 @@ RUN apt-get update && \
iputils-ping && \
apt-get clean && rm -rf /var/lib/apt/lists/*
COPY --from=remoteInstall /root/.local/bin /usr/local/bin/
COPY --from=remoteInstall /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/local/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=buildRequirements /root/.local/bin /usr/local/bin/
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_IMAGE_VERSION}/site-packages /usr/local/lib/python${PYTHON_IMAGE_VERSION}/site-packages/
COPY ./docker-compose/glances.conf /etc/glances.conf
# EXPOSE PORT (XMLRPC)
@ -93,17 +102,29 @@ EXPOSE 61209
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT
##############################################################################
# full image
# dev image
##############################################################################
FROM minimal as full
FROM full as dev
ARG PYTHON_VERSION
ARG PYTHON_IMAGE_VERSION
COPY --from=additional-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages /usr/local/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=buildRequirements /root/.local/bin /usr/local/bin/
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_IMAGE_VERSION}/site-packages /usr/lib/python${PYTHON_IMAGE_VERSION}/site-packages/
COPY --from=buildOptionalRequirements /root/.local/lib/python${PYTHON_IMAGE_VERSION}/site-packages /usr/lib/python${PYTHON_IMAGE_VERSION}/site-packages/
COPY ./docker-compose/glances.conf /etc/glances.conf
# Copy the current Glances source code
COPY . /glances
# EXPOSE PORT (XMLRPC / WebUI)
EXPOSE 61209 61208
# Forward access and error logs to Docker's log collector
RUN ln -sf /dev/stdout /tmp/glances-root.log \
&& ln -sf /dev/stderr /var/log/error.log
WORKDIR /glances
# Define default command.
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 139 KiB

View File

@ -16,7 +16,7 @@ then add the ``_action`` line to the Glances configuration file:
critical_action=python /path/to/foo.py
All the stats are available in the command line through the use of the
`{{mustache}}`_ syntax. `Chevron`_ is required to render the mustache's template syntax.
`Mustache`_ syntax. `Chevron`_ is required to render the mustache's template syntax.
Another example would be to create a log file
containing used vs total disk space if a space trigger warning is
@ -27,11 +27,11 @@ reached:
[fs]
warning=70
warning_action=echo {{mnt_point}} {{used}}/{{size}} > /tmp/fs.alert
A last example would be to create a log file containing the total user disk
space usage for a device and notify by email each time a space trigger
A last example would be to create a log file containing the total user disk
space usage for a device and notify by email each time a space trigger
critical is reached:
.. code-block:: ini
[fs]
@ -40,7 +40,7 @@ critical is reached:
.. note::
Use && as seprator for multiple commands
Use && as separator for multiple commands
Within ``/etc/glances/actions.d/fs-critical.py``:
@ -61,6 +61,7 @@ Within ``/etc/glances/actions.d/fs-critical.py``:
subprocess.call(['mail', '-s', 'CRITICAL: disk usage above 90%', '-r', 'postmaster@example.com', 'glances@example.com'], stdin=ps.stdout)
.. note::
You can use all the stats for the current plugin. See
https://github.com/nicolargo/glances/wiki/The-Glances-RESTFULL-JSON-API
for the stats list.
@ -75,5 +76,5 @@ use with caution:
critical=5.0
critical_action_repeat=/home/myhome/bin/bipper.sh
.. _{{mustache}}: https://mustache.github.io/
.. _Mustache: https://mustache.github.io/
.. _Chevron: https://github.com/noahmorrison/chevron

View File

@ -55,6 +55,7 @@ CPU stats description:
0 on Windows and SunOS.
- **syscal**: number of system calls per second. Do not displayed on
Linux (always 0).
- **dpc**: *(Windows)*: time spent servicing deferred procedure calls.
To switch to per-CPU stats, just hit the ``1`` key:

View File

@ -10,7 +10,7 @@ dynamically.
You can display:
- bytes per second (default behavor / Bytes/s, KBytes/s, MBytes/s, etc)
- bytes per second (default behavior / Bytes/s, KBytes/s, MBytes/s, etc)
- requests per second (using --diskio-iops option or *B* hotkey)
There is no alert on this information.

View File

@ -21,11 +21,11 @@ under the ``[docker]`` section:
[docker]
disable=False
# Only show specific containers (comma separeted list of container name or regular expression)
# Only show specific containers (comma separated list of container name or regular expression)
show=thiscontainer,andthisone,andthoseones.*
# Hide some containers (comma separeted list of container name or regular expression)
# Hide some containers (comma separated list of container name or regular expression)
hide=donotshowthisone,andthose.*
# Show only specific containers (comma separeted list of container name or regular expression)
# Show only specific containers (comma separated list of container name or regular expression)
#show=showthisone,andthose.*
# Define the maximum docker size name (default is 20 chars)
max_name_size=20

View File

@ -46,7 +46,7 @@ To hide all mount points starting with /boot and /snap:
Filtering are also applied on device name (Glances 3.1.4 or higher).
It is also possible to configure a white list of devices to display:
It is also possible to configure a white list of devices to display.
Example to only show /dev/sdb mount points:
.. code-block:: ini

View File

@ -50,7 +50,7 @@ configuration file.
# web_x_url is the URL to monitor (example: http://my.site.com/folder)
# web_x_description is optional (if not set, define to URL)
# web_x_timeout is optional and overwrite the default timeout value
# web_x_rtt_warning is optional and defines the warning respond time in ms (approximatively)
# web_x_rtt_warning is optional and defines the warning respond time in ms (approximately)
#
web_1_url=https://blog.nicolargo.com
web_1_description=My Blog

View File

@ -19,7 +19,7 @@ sparkline using 'S' hot key or --sparkline command line option (need the
sparklines Python lib on your system). Please be aware that sparklines use
the Glances history and will not be available if the history is disabled
from the command line. For the moment sparkline is not available in
client/server mode (see isse ).
client/server mode (see issue ).
.. image:: ../_static/sparkline.png

View File

@ -28,4 +28,10 @@ There is no alert on this information.
If a sensors has temperature and fan speed with the same name unit,
it is possible to alias it using:
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::
The plugin could crash on some operating system (FreeBSD) with the
TCP or UDP blackhole option > 0 (see issue #2106). In this case, you
should disable the sensors (--disable-plugin sensors or from the
configuration file).

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ You can put your own ``glances.conf`` file in the following locations:
``Linux``, ``SunOS`` ~/.config/glances/, /etc/glances/, /usr/share/docs/glances/
``*BSD`` ~/.config/glances/, /usr/local/etc/glances/, /usr/share/docs/glances/
``macOS`` ~/Library/Application Support/glances/, /usr/local/etc/glances/, /usr/share/docs/glances/
``Windows`` %APPDATA%\\glances\glances.conf
``Windows`` %APPDATA%\\glances\\glances.conf
==================== =============================================================
- On Windows XP, ``%APPDATA%`` is: ``C:\Documents and Settings\<USERNAME>\Application Data``.

View File

@ -17,7 +17,7 @@ starts every time the 'g' key is pressed in the CLI interface.
# generate_every to a non zero value corresponding to the seconds between
# two generation. Set it to 0 to disable graph auto generation.
generate_every=60
# See followings configuration keys definitions in the Pygal lib documentation
# See following configuration keys definitions in the Pygal lib documentation
# http://pygal.org/en/stable/documentation/index.html
width=800
height=600

View File

@ -56,7 +56,7 @@ following:
# => foo.mem
# You can also use dynamic values
#prefix=foo
# Followings tags will be added for all measurements
# Following tags will be added for all measurements
# You can also use dynamic values.
# Note: hostname is always added as a tag
#tags=foo:bar,spam:eggs,domain:`domainname`
@ -98,7 +98,7 @@ following:
# => foo.mem
# You can also use dynamic values
#prefix=foo
# Followings tags will be added for all measurements
# Following tags will be added for all measurements
# You can also use dynamic values.
# Note: hostname is always added as a tag
#tags=foo:bar,spam:eggs,domain:`domainname`

View File

@ -25,5 +25,5 @@ and run Glances with:
$ glances --export mqtt
The topic_structure field aims at configuring the way stats are exported to MQTT (see #1798):
- per-metric: one event per metric (default behavor)
- per-metric: one event per metric (default behavior)
- per-plugin: one event per plugin

View File

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "GLANCES" "1" "Sep 03, 2022" "3.3.0_beta1" "Glances"
.TH "GLANCES" "1" "Oct 23, 2022" "3.3.1_beta1" "Glances"
.SH NAME
glances \- An eye on your system
.SH SYNOPSIS
@ -577,7 +577,7 @@ _
T{
\fBWindows\fP
T} T{
%APPDATA%\eglancesglances.conf
%APPDATA%\eglances\eglances.conf
T}
_
.TE

View File

@ -47,7 +47,7 @@ or in a CSV format thanks to the stdout-csv option:
2018-12-08 22:04:23 CEST,5.4,5949136896,4,1.04,0.99,1.04
...
or as a JSON format thanks to the stdout-json option (attibute not supported in this mode):
or as a JSON format thanks to the stdout-json option (attribute not supported in this mode):
.. code-block:: console
@ -124,7 +124,7 @@ When the list is displayed, you can navigate through the Glances servers with
up/down keys. It is also possible to sort the server using:
- '1' is normal (do not sort)
- '2' is using sorting with ascending order (ONLINE > SNMP > PROTECTED > OFFLINE > UNKNOWN)
- '3' is using sorting with descending order (UNKNOW > OFFLINE > PROTECTED > SNMP > ONLINE)
- '3' is using sorting with descending order (UNKNOWN > OFFLINE > PROTECTED > SNMP > ONLINE)
SNMP
^^^^

View File

@ -19,7 +19,7 @@ import sys
# Global name
# Version should start and end with a numerical char
# See https://packaging.python.org/specifications/core-metadata/#version
__version__ = '3.3.0_beta1'
__version__ = '3.3.1_beta1'
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
__license__ = 'LGPLv3'
@ -68,7 +68,7 @@ def end():
"""Stop Glances."""
try:
mode.end()
except NameError:
except (NameError, KeyError):
# NameError: name 'mode' is not defined in case of interrupt shortly...
# ...after starting the server mode (issue #1175)
pass
@ -133,7 +133,7 @@ def start(config, args):
snapshot_end = tracemalloc.take_snapshot()
snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename')
memory_leak = sum([s.size_diff for s in snapshot_diff])
print("Memory comsumption: {0:.1f}KB (see log for details)".format(memory_leak / 1000))
print("Memory consumption: {0:.1f}KB (see log for details)".format(memory_leak / 1000))
logger.info("Memory consumption (top 5):")
for stat in snapshot_diff[:5]:
logger.info(stat)

View File

@ -54,7 +54,7 @@ class AmpsList(object):
# TODO: Change the way AMP are loaded (use folder/module instead of glances_foo.py file)
# See https://github.com/nicolargo/glances/issues/1930
header = "glances_"
# For each AMP scrip, call the load_config method
# For each AMP script, call the load_config method
for s in self.config.sections():
if s.startswith("amp_"):
# An AMP section exists in the configuration file
@ -140,18 +140,11 @@ class AmpsList(object):
try:
# Search in both cmdline and name (for kernel thread, see #1261)
for p in processlist:
add_it = False
if re.search(amp_value.regex(), p['name']) is not None:
add_it = True
else:
if p['cmdline'] is None:
# See issue #1689 (thanks to @darylkell)
continue
for c in p['cmdline']:
if re.search(amp_value.regex(), c) is not None:
add_it = True
break
if add_it:
if (re.search(amp_value.regex(), p['name']) is not None) or (
p['cmdline'] is not None
and p['cmdline'] != []
and re.search(amp_value.regex(), ' '.join(p['cmdline'])) is not None
):
ret.append(
{'pid': p['pid'], 'cpu_percent': p['cpu_percent'], 'memory_percent': p['memory_percent']}
)

View File

@ -32,7 +32,7 @@ if zeroconf_tag:
sys.exit(1)
# Global var
# Recent versions of the zeroconf python package doesnt like a zeroconf type that ends with '._tcp.'.
# Recent versions of the zeroconf python package doesn't like a zeroconf type that ends with '._tcp.'.
# Correct issue: zeroconf problem with zeroconf_type = "_%s._tcp." % 'glances' #888
zeroconf_type = "_%s._tcp.local." % 'glances'

View File

@ -203,7 +203,7 @@ else:
return s.encode('utf-8', errors=errors)
def system_exec(command):
"""Execute a system command and return the resul as a str"""
"""Execute a system command and return the result as a str"""
try:
res = subprocess.check_output(command.split(' '))
except Exception as e:

View File

@ -50,7 +50,9 @@ class Export(GlancesExport):
if self.user is None:
server_uri = 'http://{}:{}/'.format(self.host, self.port)
else:
server_uri = 'http://{}:{}@{}:{}/'.format(self.user, self.password, self.host, self.port)
# Force https if a login/password is provided
# Related to https://github.com/nicolargo/glances/issues/2124
server_uri = 'https://{}:{}@{}:{}/'.format(self.user, self.password, self.host, self.port)
try:
s = couchdb.Server(server_uri)
@ -58,7 +60,7 @@ class Export(GlancesExport):
logger.critical("Cannot connect to CouchDB server %s (%s)" % (server_uri, e))
sys.exit(2)
else:
logger.info("Connected to the CouchDB server %s" % server_uri)
logger.info("Connected to the CouchDB server")
try:
s[self.db]

View File

@ -47,7 +47,7 @@ class GlancesFilter(object):
@property
def filter_input(self):
"""Return the filter given by the user (as a sting)"""
"""Return the filter given by the user (as a string)"""
return self._filter_input
@property
@ -57,7 +57,7 @@ class GlancesFilter(object):
@filter.setter
def filter(self, value):
"""Set the filter (as a sting) and compute the regular expression
"""Set the filter (as a string) and compute the regular expression
A filter could be one of the following:
- python > Process name of cmd start with python
@ -131,7 +131,7 @@ class GlancesFilter(object):
# If the key did not exist
return False
try:
return self._filter_re.match(value) is None
return self._filter_re.fullmatch(value) is None
except (AttributeError, TypeError):
# AttributeError - Filter processes crashes with a bad regular expression pattern (issue #665)
# TypeError - Filter processes crashes if value is None (issue #1105)

View File

@ -122,10 +122,10 @@ Examples of use:
'--disable-plugin',
'--disable-plugins',
dest='disable_plugin',
help='disable plugin (comma separed list or all). If all is used, then you need to configure --enable-plugin.',
help='disable plugin (comma separated list or all). If all is used, then you need to configure --enable-plugin.',
)
parser.add_argument(
'--enable-plugin', '--enable-plugins', dest='enable_plugin', help='enable plugin (comma separed list)'
'--enable-plugin', '--enable-plugins', dest='enable_plugin', help='enable plugin (comma separated list)'
)
parser.add_argument(
'--disable-process',
@ -252,7 +252,7 @@ Examples of use:
help='Accumulate processes by program',
)
# Export modules feature
parser.add_argument('--export', dest='export', help='enable export module (comma separed list)')
parser.add_argument('--export', dest='export', help='enable export module (comma separated list)')
parser.add_argument(
'--export-csv-file', default='./glances.csv', dest='export_csv_file', help='file path for CSV exporter'
)
@ -772,5 +772,5 @@ Examples of use:
"""
from glances.password import GlancesPassword
password = GlancesPassword(username=username)
password = GlancesPassword(username=username, config=self.get_config())
return password.get_password(description, confirm, clear)

View File

@ -127,7 +127,8 @@ class GlancesBottle(object):
if username == self.args.username:
from glances.password import GlancesPassword
pwd = GlancesPassword()
pwd = GlancesPassword(username=username,
config=self.config)
return pwd.check_password(self.args.password, pwd.sha256_hash(password))
else:
return False

View File

@ -1074,7 +1074,8 @@ class _GlancesCurses(object):
if not display_additional and m['additional']:
continue
# Is it possible to display the stat with the current screen size
if screen_x - x > 0:
# !!! Crash if not try/except... Why ???
try:
self.term_window.addnstr(
y,
x,
@ -1083,10 +1084,21 @@ class _GlancesCurses(object):
screen_x - x,
self.colors_list[m['decoration']],
)
# New column
x += len(u(m['msg']))
if x > x_max:
x_max = x
except Exception:
pass
else:
# New column
# Python 2: we need to decode to get real screen size because
# UTF-8 special tree chars occupy several bytes.
# Python 3: strings are strings and bytes are bytes, all is
# good.
try:
x += len(u(m['msg']))
except UnicodeDecodeError:
# Quick and dirty hack for issue #745
pass
if x > x_max:
x_max = x
# Compute the next Glances column/line position
self.next_column = max(self.next_column, x_max + self.space_between_column)

View File

@ -84,13 +84,14 @@ class GlancesStdoutIssue(object):
except Exception:
pass
time.sleep(3)
time.sleep(2)
counter_total = Counter()
for plugin in sorted(stats._plugins):
if stats._plugins[plugin].is_disabled():
# If current plugin is disable
# then continue to next plugin
result = colors.NO + '[N/A]'.rjust(19 - len(plugin))
result = colors.NO + '[NA]'.rjust(18 - len(plugin))
message = colors.NO
self.print_issue(plugin, result, message)
continue
@ -122,5 +123,10 @@ class GlancesStdoutIssue(object):
message = colors.NO + str(stat_error)[0 : TERMINAL_WIDTH - 41]
self.print_issue(plugin, result, message)
# Display total time need to update all plugins
sys.stdout.write('=' * TERMINAL_WIDTH + '\n')
print("Total time to update all stats: {}{:.5f}s{}".format(colors.BLUE, counter_total.get(), colors.NO))
sys.stdout.write('=' * TERMINAL_WIDTH + '\n')
# Return True to exit directly (no refresh)
return True

View File

@ -20,12 +20,11 @@ body {
text-align: right;
}
.top-plugin {
margin-bottom: 20px;
}
.plugin {
margin-bottom: 20px;
.table:last-child {
margin-bottom: 0;
}
}
.plugin.table-row-group .table-row:last-child .table-cell {
padding-bottom: 20px;
@ -43,6 +42,7 @@ body {
}
.sortable {
cursor: pointer;
text-decoration: underline;
}
.text-right {
text-align: right;
@ -115,7 +115,7 @@ body {
white-space: nowrap;
}
#quicklook-plugin {
#quicklook {
.progress {
margin-bottom: 0px;
min-width: 100px;
@ -159,6 +159,22 @@ body {
text-overflow: ellipsis;
}
#ip {
padding-left: 10px;
}
#ip span {
padding-left: 10px;
}
#processcount > span:nth-child(1) {
padding-left: 0px;
}
#processcount span {
padding-left: 10px;
}
/* Loading page */
#loading-page .glances-logo {

View File

@ -4,14 +4,14 @@
<div class="loader">Loading...</div>
</div>
<glances-help v-else-if="args.help_tag"></glances-help>
<div v-else class="container-fluid">
<div class="top-plugin">
<main v-else>
<div class="container-fluid">
<div class="row">
<div class="col-sm-24">
<div class="pull-left">
<glances-plugin-system :data="data"></glances-plugin-system>
</div>
<div class="pull-left" v-if="args.disable_ip">
<div class="pull-left" v-if="!args.disable_ip">
<glances-plugin-ip :data="data"></glances-plugin-ip>
</div>
<div class="pull-right">
@ -19,6 +19,8 @@
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-sm-24">
<div class="pull-left">
@ -26,115 +28,124 @@
</div>
</div>
</div>
</div>
<div class="row">
<div class="hidden-xs hidden-sm hidden-md col-lg-6" v-if="!args.disable_quicklook">
<glances-plugin-quicklook :data="data"></glances-plugin-quicklook>
</div>
<div class="col-sm-6 col-md-8 col-lg-6" v-if="!args.disable_cpu && !args.percpu">
<glances-plugin-cpu :data="data"></glances-plugin-cpu>
</div>
<div class="col-sm-12 col-md-8 col-lg-6" v-if="!args.disable_cpu && args.percpu">
<glances-plugin-percpu :data="data"></glances-plugin-percpu>
</div>
<div class="col-sm-6 col-md-4 col-lg-3" v-if="!args.disable_gpu && hasGpu">
<glances-plugin-gpu :data="data"></glances-plugin-gpu>
</div>
<div class="col-sm-6 col-md-4 col-lg-3" v-if="!args.disable_mem">
<glances-plugin-mem :data="data"></glances-plugin-mem>
</div>
<!-- NOTE: display if MEM enabled and GPU disabled -->
<div
v-if="!args.disable_mem && !(!args.disable_gpu && hasGpu)"
class="hidden-xs hidden-sm col-md-4 col-lg-3"
>
<glances-plugin-mem-more :data="data"></glances-plugin-mem-more>
</div>
<div class="col-sm-6 col-md-4 col-lg-3" v-if="!args.disable_memswap">
<glances-plugin-memswap :data="data"></glances-plugin-memswap>
</div>
<div class="col-sm-6 col-md-4 col-lg-3" v-if="!args.disable_load">
<glances-plugin-load :data="data"></glances-plugin-load>
</div>
</div>
<div class="row">
<div class="col-sm-6 sidebar" v-if="!args.disable_left_sidebar">
<div class="table">
<glances-plugin-network
id="plugin-network"
class="plugin table-row-group"
v-if="!args.disable_network"
:data="data"
></glances-plugin-network>
<glances-plugin-connections
id="plugin-connections"
class="plugin table-row-group"
v-if="isLinux && !args.disable_connections"
:data="data"
></glances-plugin-connections>
<glances-plugin-wifi
id="plugin-wifi"
class="plugin table-row-group"
v-if="!args.disable_wifi"
:data="data"
></glances-plugin-wifi>
<glances-plugin-ports
id="plugin-ports"
class="plugin table-row-group"
v-if="!args.disable_ports"
:data="data"
></glances-plugin-ports>
<glances-plugin-diskio
id="plugin-diskio"
class="plugin table-row-group"
v-if="!args.disable_diskio"
:data="data"
></glances-plugin-diskio>
<glances-plugin-fs
id="plugin-fs"
class="plugin table-row-group"
v-if="!args.disable_fs"
:data="data"
></glances-plugin-fs>
<glances-plugin-irq
id="plugin-irq"
class="plugin table-row-group"
v-if="args.enable_irq"
:data="data"
></glances-plugin-irq>
<glances-plugin-folders
id="plugin-folders"
class="plugin table-row-group"
v-if="!args.disable_folders"
:data="data"
></glances-plugin-folders>
<glances-plugin-raid
id="plugin-raid"
class="plugin table-row-group"
v-if="!args.raid"
:data="data"
></glances-plugin-raid>
<glances-plugin-sensors
id="plugin-sensors"
class="plugin table-row-group"
v-if="!args.disable_sensors"
:data="data"
></glances-plugin-sensors>
<div class="row">
<div class="hidden-xs hidden-sm hidden-md col-lg-6" v-if="!args.disable_quicklook">
<glances-plugin-quicklook :data="data"></glances-plugin-quicklook>
</div>
<div class="col-sm-6 col-md-8 col-lg-6" v-if="!args.disable_cpu && !args.percpu">
<glances-plugin-cpu :data="data"></glances-plugin-cpu>
</div>
<div class="col-sm-12 col-md-8 col-lg-6" v-if="!args.disable_cpu && args.percpu">
<glances-plugin-percpu :data="data"></glances-plugin-percpu>
</div>
<div class="col-sm-6 col-md-4 col-lg-3" v-if="!args.disable_gpu && hasGpu">
<glances-plugin-gpu :data="data"></glances-plugin-gpu>
</div>
<div class="col-sm-6 col-md-4 col-lg-3" v-if="!args.disable_mem">
<glances-plugin-mem :data="data"></glances-plugin-mem>
</div>
<!-- NOTE: display if MEM enabled and GPU disabled -->
<div
v-if="!args.disable_mem && !(!args.disable_gpu && hasGpu)"
class="hidden-xs hidden-sm col-md-4 col-lg-3"
>
<glances-plugin-mem-more :data="data"></glances-plugin-mem-more>
</div>
<div class="col-sm-6 col-md-4 col-lg-3" v-if="!args.disable_memswap">
<glances-plugin-memswap :data="data"></glances-plugin-memswap>
</div>
<div class="col-sm-6 col-md-4 col-lg-3" v-if="!args.disable_load">
<glances-plugin-load :data="data"></glances-plugin-load>
</div>
</div>
<div class="col-sm-18">
<glances-plugin-docker
v-if="!args.disable_docker"
:data="data"
></glances-plugin-docker>
<glances-plugin-alert
v-if="!args.disable_alert"
:data="data"
></glances-plugin-alert>
<glances-plugin-process :data="data"></glances-plugin-process>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-sm-6 sidebar" v-if="!args.disable_left_sidebar">
<div class="table">
<glances-plugin-network
id="plugin-network"
class="plugin table-row-group"
v-if="!args.disable_network"
:data="data"
></glances-plugin-network>
<glances-plugin-connections
id="plugin-connections"
class="plugin table-row-group"
v-if="isLinux && !args.disable_connections"
:data="data"
></glances-plugin-connections>
<glances-plugin-wifi
id="plugin-wifi"
class="plugin table-row-group"
v-if="!args.disable_wifi"
:data="data"
></glances-plugin-wifi>
<glances-plugin-ports
id="plugin-ports"
class="plugin table-row-group"
v-if="!args.disable_ports"
:data="data"
></glances-plugin-ports>
<glances-plugin-diskio
id="plugin-diskio"
class="plugin table-row-group"
v-if="!args.disable_diskio"
:data="data"
></glances-plugin-diskio>
<glances-plugin-fs
id="plugin-fs"
class="plugin table-row-group"
v-if="!args.disable_fs"
:data="data"
></glances-plugin-fs>
<glances-plugin-irq
id="plugin-irq"
class="plugin table-row-group"
v-if="args.enable_irq"
:data="data"
></glances-plugin-irq>
<glances-plugin-folders
id="plugin-folders"
class="plugin table-row-group"
v-if="!args.disable_folders"
:data="data"
></glances-plugin-folders>
<glances-plugin-raid
id="plugin-raid"
class="plugin table-row-group"
v-if="!args.raid"
:data="data"
></glances-plugin-raid>
<glances-plugin-sensors
id="plugin-sensors"
class="plugin table-row-group"
v-if="!args.disable_sensors"
:data="data"
></glances-plugin-sensors>
</div>
</div>
<div class="col-sm-18">
<glances-plugin-docker
v-if="!args.disable_docker"
:data="data"
></glances-plugin-docker>
<glances-plugin-process :data="data"></glances-plugin-process>
<glances-plugin-alert
v-if="!args.disable_alert"
:data="data"
></glances-plugin-alert>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-sm-24">
<glances-plugin-now :data="data"></glances-plugin-now>
</div>
</div>
</div>
</main>
</template>
<script>
@ -159,6 +170,7 @@ import GlancesPluginMem from './components/plugin-mem.vue';
import GlancesPluginMemMore from './components/plugin-mem-more.vue';
import GlancesPluginMemswap from './components/plugin-memswap.vue';
import GlancesPluginNetwork from './components/plugin-network.vue';
import GlancesPluginNow from './components/plugin-now.vue';
import GlancesPluginPercpu from './components/plugin-percpu.vue';
import GlancesPluginPorts from './components/plugin-ports.vue';
import GlancesPluginProcess from './components/plugin-process.vue';
@ -188,6 +200,7 @@ export default {
GlancesPluginMemMore,
GlancesPluginMemswap,
GlancesPluginNetwork,
GlancesPluginNow,
GlancesPluginPercpu,
GlancesPluginPorts,
GlancesPluginProcess,
@ -234,6 +247,41 @@ export default {
},
methods: {
setupHotKeys() {
// a => Sort processes/docker automatically
hotkeys('a', () => {
this.store.args.sort_processes_key = null;
});
// c => Sort processes/docker by CPU%
hotkeys('c', () => {
this.store.args.sort_processes_key = 'cpu_percent';
});
// m => Sort processes/docker by MEM%
hotkeys('m', () => {
this.store.args.sort_processes_key = 'memory_percent';
});
// u => Sort processes/docker by user
hotkeys('u', () => {
this.store.args.sort_processes_key = 'username';
});
// p => Sort processes/docker by name
hotkeys('p', () => {
this.store.args.sort_processes_key = 'name';
});
// i => Sort processes/docker by I/O rate
hotkeys('i', () => {
this.store.args.sort_processes_key = 'io_counters';
});
// t => Sort processes/docker by time
hotkeys('t', () => {
this.store.args.sort_processes_key = 'timemillis';
});
// A => Enable/disable AMPs
hotkeys('shift+A', () => {
this.store.args.disable_amps = !this.store.args.disable_amps;

View File

@ -1,12 +1,12 @@
<template>
<div>
<div class="plugin">
<section id="alerts">
<span class="title" v-if="hasAlerts">
Warning or critical alerts (last {{ countAlerts }} entries)
</span>
<span class="title" v-else>No warning or critical alert detected</span>
</section>
<section id="alert" class="plugin">
<section id="alert">
<div class="table">
<div class="table-row" v-for="(alert, alertId) in alerts" :key="alertId">
<div class="table-cell text-left">

View File

@ -1,5 +1,5 @@
<template>
<section id="cloud">
<section id="cloud" class="plugin" v-if="instance || provider">
<span class="title">{{ provider }}</span> {{ instance }}
</section>
</template>

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="connections">
<div class="table-row">
<div class="table-cell text-left title">TCP CONNECTIONS</div>
<div class="table-cell"></div>

View File

@ -15,52 +15,48 @@
<div class="table-cell text-left">system:</div>
<div class="table-cell" :class="getDecoration('system')">{{ system }}%</div>
</div>
<div class="table-row">
<div class="table-cell text-left">idle:</div>
<div class="table-cell">{{ idle }}%</div>
<div class="table-row" v-show="iowait != undefined">
<div class="table-cell text-left">iowait:</div>
<div class="table-cell" :class="getDecoration('iowait')">{{ iowait }}%</div>
</div>
<div class="table-row" v-show="iowait == undefined && dpc != undefined">
<div class="table-cell text-left">dpc:</div>
<div class="table-cell" :class="getDecoration('dpc')">{{ dpc }}%</div>
</div>
</div>
</div>
<div class="hidden-xs hidden-sm col-md-12 col-lg-8">
<div class="table">
<div class="table-row" v-show="nice != undefined">
<div class="table-cell text-left">nice:</div>
<div class="table-cell">{{ nice }}%</div>
<div class="table-row">
<div class="table-cell text-left">idle:</div>
<div class="table-cell">{{ idle }}%</div>
</div>
<div class="table-row" v-show="irq != undefined">
<div class="table-cell text-left">irq:</div>
<div class="table-cell">{{ irq }}%</div>
</div>
<div class="table-row" v-show="iowait != undefined">
<div class="table-cell text-left">iowait:</div>
<div class="table-cell" :class="getDecoration('iowait')">{{ iowait }}%</div>
</div>
<div class="table-row" v-show="steal != undefined">
<div class="table-cell text-left">steal:</div>
<div class="table-cell" :class="getDecoration('steal')">{{ steal }}%</div>
</div>
</div>
</div>
<div class="hidden-xs hidden-sm hidden-md col-lg-8">
<div class="table">
<div class="table-row" v-if="ctx_switches">
<div class="table-cell text-left">ctx_sw:</div>
<div class="table-cell" :class="getDecoration('ctx_switches')">
{{ ctx_switches }}
</div>
</div>
<div class="table-row" v-if="interrupts">
<!-- If no irq, display interrupts -->
<div class="table-row" v-show="irq == undefined">
<div class="table-cell text-left">inter:</div>
<div class="table-cell">
{{ interrupts }}
</div>
</div>
<div class="table-row" v-if="soft_interrupts">
<div class="table-cell text-left">sw_int:</div>
<div class="table-cell">
{{ soft_interrupts }}
<div class="table-row" v-show="nice != undefined">
<div class="table-cell text-left">nice:</div>
<div class="table-cell">{{ nice }}%</div>
</div>
<!-- If no nice, display ctx_switches -->
<div class="table-row" v-if="nice == undefined && ctx_switches">
<div class="table-cell text-left">ctx_sw:</div>
<div class="table-cell" :class="getDecoration('ctx_switches')">
{{ ctx_switches }}
</div>
</div>
<div class="table-row" v-show="steal != undefined">
<div class="table-cell text-left">steal:</div>
<div class="table-cell" :class="getDecoration('steal')">{{ steal }}%</div>
</div>
<div class="table-row" v-if="!isLinux && syscalls">
<div class="table-cell text-left">syscal:</div>
<div class="table-cell">
@ -69,6 +65,30 @@
</div>
</div>
</div>
<div class="hidden-xs hidden-sm hidden-md col-lg-8">
<div class="table">
<!-- If not already display instead of nice, then display ctx_switches -->
<div class="table-row" v-if="nice != undefined && ctx_switches">
<div class="table-cell text-left">ctx_sw:</div>
<div class="table-cell" :class="getDecoration('ctx_switches')">
{{ ctx_switches }}
</div>
</div>
<!-- If not already display instead of irq, then display interrupts -->
<div class="table-row" v-if="irq != undefined && interrupts">
<div class="table-cell text-left">inter:</div>
<div class="table-cell">
{{ interrupts }}
</div>
</div>
<div class="table-row" v-if="!isWindows && !isSunOS && soft_interrupts">
<div class="table-cell text-left">sw_int:</div>
<div class="table-cell">
{{ soft_interrupts }}
</div>
</div>
</div>
</div>
</div>
</section>
</template>
@ -90,6 +110,12 @@ export default {
isLinux() {
return this.data.isLinux;
},
isSunOS() {
return this.data.isSunOS;
},
isWindows() {
return this.data.isWindows;
},
total() {
return this.stats.total;
},
@ -111,6 +137,9 @@ export default {
iowait() {
return this.stats.iowait;
},
dpc() {
return this.stats.dpc;
},
steal() {
return this.stats.steal;
},

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="diskio">
<div class="table-row" v-if="disks.length > 0">
<div class="table-cell text-left title">DISK I/O</div>
<div class="table-cell" v-show="!args.diskio_iops">R/s</div>

View File

@ -1,15 +1,33 @@
<template>
<section id="containers-plugin" class="plugin" v-if="containers.length">
<span class="title">CONTAINERS</span>
{{ containers.length }} (served by Docker {{ version }})
{{ containers.length }} sorted by {{ sorter.getColumnLabel(sorter.column) }}
<div class="table">
<div class="table-row">
<div class="table-cell text-left">Name</div>
<div
class="table-cell text-left"
:class="['sortable', sorter.column === 'name' && 'sort']"
@click="args.sort_processes_key = 'name'"
>
Name
</div>
<div class="table-cell">Status</div>
<div class="table-cell">Uptime</div>
<div class="table-cell">CPU%</div>
<div class="table-cell">MEM</div>
<div class="table-cell">RSS</div>
<div
class="table-cell"
:class="['sortable', sorter.column === 'cpu_percent' && 'sort']"
@click="args.sort_processes_key = 'cpu_percent'"
>
CPU%
</div>
<div
class="table-cell"
:class="['sortable', sorter.column === 'memory_percent' && 'sort']"
@click="args.sort_processes_key = 'memory_percent'"
>
MEM
</div>
<div class="table-cell">/MAX</div>
<div class="table-cell">IOR/s</div>
<div class="table-cell">IOW/s</div>
<div class="table-cell">RX/s</div>
@ -29,13 +47,13 @@
{{ container.uptime }}
</div>
<div class="table-cell">
{{ $filters.number(container.cpu, 1) }}
{{ $filters.number(container.cpu_percent, 1) }}
</div>
<div class="table-cell">
{{ $filters.bytes(container.memory) }}
{{ $filters.bytes(container.memory_usage) }}
</div>
<div class="table-cell">
{{ $filters.bytes(container.rss) }}
{{ $filters.bytes(container.limit) }}
</div>
<div class="table-cell">
{{ $filters.bits(container.ior / container.io_time_since_update) }}
@ -58,40 +76,93 @@
</template>
<script>
import { orderBy } from 'lodash';
import { store } from '../store.js';
export default {
props: {
data: {
type: Object
}
},
data() {
return {
store,
sorter: undefined
};
},
computed: {
args() {
return this.store.args || {};
},
sortProcessesKey() {
return this.args.sort_processes_key;
},
stats() {
return this.data.stats['docker'];
},
containers() {
return (this.stats.containers || []).map((containerData) => {
const { sorter } = this;
const containers = (this.stats.containers || []).map((containerData) => {
// prettier-ignore
return {
'id': containerData.Id,
'name': containerData.name,
'status': containerData.Status,
'uptime': containerData.Uptime,
'cpu': containerData.cpu.total,
'memory': containerData.memory.usage != undefined ? containerData.memory.usage : '?',
'rss': containerData.memory.rss != undefined ? containerData.memory.rss : '?',
'cpu_percent': containerData.cpu.total,
'memory_usage': containerData.memory.usage != undefined ? containerData.memory.usage : '?',
'limit': containerData.memory.limit != undefined ? containerData.memory.limit : '?',
'ior': containerData.io.ior != undefined ? containerData.io.ior : '?',
'iow': containerData.io.iow != undefined ? containerData.io.iow : '?',
'io_time_since_update': containerData.io.time_since_update,
'rx': containerData.network.rx != undefined ? containerData.network.rx : '?',
'tx': containerData.network.tx != undefined ? containerData.network.tx : '?',
'net_time_since_update': containerData.network.time_since_update,
'command': containerData.Command,
'command': containerData.Command.join(' '),
'image': containerData.Image
};
};
});
},
version() {
return (this.stats['version'] || {})['Version'];
return orderBy(
containers,
[sorter.column].reduce((retval, col) => {
if (col === 'memory_percent') {
col = ['memory_usage'];
}
return retval.concat(col);
}, []),
[sorter.isReverseColumn(sorter.column) ? 'desc' : 'asc']
);
}
},
watch: {
sortProcessesKey: {
immediate: true,
handler(sortProcessesKey) {
const sortable = ['cpu_percent', 'memory_percent', 'name'];
function isReverseColumn(column) {
return !['name'].includes(column);
}
function getColumnLabel(value) {
const labels = {
io_counters: 'disk IO',
cpu_percent: 'CPU consumption',
memory_usage: 'memory consumption',
cpu_times: 'uptime',
name: 'container name',
None: 'None'
};
return labels[value] || value;
}
if (!sortProcessesKey || sortable.includes(sortProcessesKey)) {
this.sorter = {
column: this.args.sort_processes_key || 'cpu_percent',
auto: !this.args.sort_processes_key,
isReverseColumn,
getColumnLabel
};
}
}
}
}
};

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="folders">
<div class="table-row" v-if="folders.length > 0">
<div class="table-cell text-left title">FOLDERS</div>
<div class="table-cell"></div>

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="fs">
<div class="table-row">
<div class="table-cell text-left title">FILE SYS</div>
<div class="table-cell">

View File

@ -1,11 +1,10 @@
<template>
<section id="ip" v-if="address != undefined">
-
<section class="plugin" id="ip" v-if="address != undefined">
<span v-if="address != undefined" class="title">IP</span>
<span v-if="address != undefined">{{ address }}/{{ maskCidr }}</span>
<span v-if="publicAddress" class="title">Pub</span>
<span v-if="publicAddress">{{ publicAddress }}</span>
<span v-if="publicInfo">({{ publicInfo }})</span>
<span v-if="address != undefined">{{ address }}/{{ maskCdir }}</span>
<span v-if="publicAddress != undefined" class="title">Pub</span>
<span v-if="publicAddress != undefined">{{ publicAddress }}</span>
<span v-if="publicInfo != undefined">{{ publicInfo }}</span>
</section>
</template>
@ -26,9 +25,9 @@ export default {
gateway() {
return this.ipStats.gateway;
},
mask() {
return this.ipStats.mask;
},
// mask() {
// return this.ipStats.mask;
// },
maskCdir() {
return this.ipStats.mask_cidr;
},

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="irq">
<div class="table-row" v-if="irqs.length > 0">
<div class="table-cell text-left title">IRQ</div>
<div class="table-cell"></div>

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="network">
<div class="table-row">
<div class="table-cell text-left title">NETWORK</div>
<div class="table-cell" v-show="!args.network_cumul && !args.network_sum">Rx/s</div>

View File

@ -0,0 +1,20 @@
<template>
<section id="now" class="plugin">
<span>{{ value }}</span>
</section>
</template>
<script>
export default {
props: {
data: {
type: Object
}
},
computed: {
value() {
return this.data.stats['now'];
}
}
};
</script>

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="ports">
<div class="table-row" v-for="(port, portId) in ports" :key="portId">
<div class="table-cell text-left">
<!-- prettier-ignore -->
@ -10,7 +10,7 @@
<span v-if="port.status == 'null'">Scanning</span>
<span v-else-if="port.status == 'false'">Timeout</span>
<span v-else-if="port.status == 'true'">Open</span>
<span v-else> {{ $filters.number(numberport.status * 1000.0, 0) }}ms </span>
<span v-else>{{ $filters.number(port.status * 1000.0, 0) }}ms</span>
</div>
<div :class="getWebDecoration(port)" class="table-cell" v-if="port.url">
<span v-if="port.status == 'null'">Scanning</span>

View File

@ -10,13 +10,12 @@
<glances-plugin-processlist
:sorter="sorter"
:data="data"
@update:sorter="sorter.column = $event"
@update:sorter="args.sort_processes_key = $event"
></glances-plugin-processlist>
</div>
</template>
<script>
import hotkeys from 'hotkeys-js';
import { store } from '../store.js';
import GlancesPluginAmps from './plugin-amps.vue';
import GlancesPluginProcesscount from './plugin-processcount.vue';
@ -36,83 +35,56 @@ export default {
data() {
return {
store,
sorter: {
column: 'cpu_percent',
auto: true,
isReverseColumn(column) {
return !(column === 'username' || column === 'name');
},
getColumnLabel(column) {
if (column === 'io_read' || column === 'io_write') {
return 'io_counters';
} else {
return column;
}
}
}
sorter: undefined
};
},
computed: {
args() {
return this.store.args || {};
},
sortProcessesKey() {
return this.args.sort_processes_key;
}
},
methods: {
setupHotKeys() {
// a => Sort processes automatically
hotkeys('a', () => {
this.sorter.column = 'cpu_percent';
this.sorter.auto = true;
});
// c => Sort processes by CPU%
hotkeys('c', () => {
this.sorter.column = 'cpu_percent';
this.sorter.auto = false;
});
// m => Sort processes by MEM%
hotkeys('m', () => {
this.sorter.column = 'memory_percent';
this.sorter.auto = false;
});
// u => Sort processes by user
hotkeys('u', () => {
this.sorter.column = 'username';
this.sorter.auto = false;
});
// p => Sort processes by name
hotkeys('p', () => {
this.sorter.column = 'name';
this.sorter.auto = false;
});
// i => Sort processes by I/O rate
hotkeys('i', () => {
this.sorter.column = ['io_read', 'io_write'];
this.sorter.auto = false;
});
// t => Sort processes by time
hotkeys('t', () => {
this.sorter.column = 'timemillis';
this.sorter.auto = false;
});
watch: {
sortProcessesKey: {
immediate: true,
handler(sortProcessesKey) {
const sortable = [
'cpu_percent',
'memory_percent',
'username',
'timemillis',
'num_threads',
'io_counters',
'name'
];
function isReverseColumn(column) {
return !['username', 'name'].includes(column);
}
function getColumnLabel(value) {
const labels = {
io_counters: 'disk IO',
cpu_percent: 'CPU consumption',
memory_percent: 'memory consumption',
cpu_times: 'process time',
username: 'user name',
name: 'process name',
timemillis: 'process time',
None: 'None'
};
return labels[value] || value;
}
if (!sortProcessesKey || sortable.includes(sortProcessesKey)) {
this.sorter = {
column: this.args.sort_processes_key || 'cpu_percent',
auto: !this.args.sort_processes_key,
isReverseColumn,
getColumnLabel
};
}
}
}
},
mounted() {
this.setupHotKeys();
},
beforeUnmount() {
hotkeys.unbind('a');
hotkeys.unbind('c');
hotkeys.unbind('m');
hotkeys.unbind('u');
hotkeys.unbind('p');
hotkeys.unbind('i');
hotkeys.unbind('t');
}
};
</script>

View File

@ -5,10 +5,8 @@
<span>{{ running }} run,</span>
<span>{{ sleeping }} slp,</span>
<span>{{ stopped }} oth</span>
<span>
sorted {{ sorter.auto ? 'automatically' : '' }} by
{{ sorter.getColumnLabel(sorter.column) }}, flat view
</span>
<span class="title">{{ sorter.auto ? 'sorted automatically' : 'sorted' }}</span>
<span>by {{ sorter.getColumnLabel(sorter.column) }}</span>
</section>
</template>

View File

@ -6,7 +6,7 @@
<div
class="table-cell"
:class="['sortable', sorter.column === 'cpu_percent' && 'sort']"
@click="$emit('update:sorter', 'cpu_percen')"
@click="$emit('update:sorter', 'cpu_percent')"
>
CPU%
</div>
@ -46,16 +46,16 @@
<div
v-show="ioReadWritePresent"
class="table-cell hidden-xs hidden-sm"
:class="['sortable', sorter.column === 'io_read' && 'sort']"
@click="$emit('update:sorter', 'io_read')"
:class="['sortable', sorter.column === 'io_counters' && 'sort']"
@click="$emit('update:sorter', 'io_counters')"
>
IOR/s
</div>
<div
v-show="ioReadWritePresent"
class="table-cell text-left hidden-xs hidden-sm"
:class="['sortable', sorter.column === 'io_write' && 'sort']"
@click="$emit('update:sorter', 'io_write')"
:class="['sortable', sorter.column === 'io_counters' && 'sort']"
@click="$emit('update:sorter', 'io_counters')"
>
IOW/s
</div>
@ -215,7 +215,12 @@ export default {
return orderBy(
processes,
[sorter.column],
[sorter.column].reduce((retval, col) => {
if (col === 'io_counters') {
col = ['io_read', 'io_write']
}
return retval.concat(col);
}, []),
[sorter.isReverseColumn(sorter.column) ? 'desc' : 'asc']
).slice(0, this.limit);
},

View File

@ -1,5 +1,5 @@
<template>
<section id="quicklook-plugin" class="plugin">
<section id="quicklook" class="plugin">
<div class="cpu-name">
{{ cpu_name }}
</div>

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="raid">
<div class="table-row" v-if="hasDisks">
<div class="table-cell text-left title">RAID disks</div>
<div class="table-cell">Used</div>

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="sensors">
<div class="table-row" v-if="sensors.length > 0">
<div class="table-cell text-left title">SENSORS</div>
</div>

View File

@ -1,5 +1,5 @@
<template>
<section id="system">
<section class="plugin" id="system">
<span v-if="isDisconnected" class="critical">Disconnected from</span>
<span class="title">{{ hostname }}</span>
<span v-if="isLinux" class="hidden-xs hidden-sm">

View File

@ -1,5 +1,5 @@
<template>
<section id="uptime">
<section class="plugin" id="uptime">
<span>Uptime: {{ value }}</span>
</section>
</template>

View File

@ -1,5 +1,5 @@
<template>
<section>
<section class="plugin" id="wifi">
<div class="table-row" v-if="hotspots.length > 0">
<div class="table-cell text-left title">WIFI</div>
<div class="table-cell"></div>

View File

@ -64,6 +64,7 @@ class GlancesStatsService {
views: response[1],
isBsd: response[0]['system']['os_name'] === 'FreeBSD',
isLinux: response[0]['system']['os_name'] === 'Linux',
isSunOS: response[0]['system']['os_name'] === 'SunOS',
isMac: response[0]['system']['os_name'] === 'Darwin',
isWindows: response[0]['system']['os_name'] === 'Windows'
};

File diff suppressed because it is too large Load Diff

View File

@ -3,28 +3,28 @@
"dependencies": {
"bootstrap": "^3.4.1",
"favico.js": "^0.3.10",
"hotkeys-js": "^3.9.5",
"hotkeys-js": "^3.10.0",
"lodash": "^4.17.21",
"sanitize-html": "^2.7.1",
"vue": "^3.2.38"
"sanitize-html": "^2.7.2",
"vue": "^3.2.41"
},
"devDependencies": {
"copy-webpack-plugin": "^9.0.1",
"css-loader": "^6.5.1",
"del": "^6.0.0",
"eslint": "^8.23.0",
"eslint-plugin-vue": "^9.4.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1",
"del": "^7.0.0",
"eslint": "^8.25.0",
"eslint-plugin-vue": "^9.6.0",
"html-webpack-plugin": "^5.5.0",
"less": "^4.0.0",
"less-loader": "^10.2.0",
"sass": "^1.54.5",
"sass-loader": "^12.6.0",
"less": "^4.1.3",
"less-loader": "^11.1.0",
"sass": "^1.55.0",
"sass-loader": "^13.1.0",
"style-loader": "^3.3.1",
"url-loader": "^4.1.1",
"vue-loader": "^17.0.0",
"webpack": "^5.63.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.10.0"
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1"
},
"scripts": {
"build": "webpack --progress --mode=production",

File diff suppressed because one or more lines are too long

View File

@ -25,12 +25,25 @@ class GlancesPassword(object):
"""This class contains all the methods relating to password."""
def __init__(self, username='glances'):
def __init__(self, username='glances', config=None):
self.username = username
self.password_dir = user_config_dir()
self.config = config
self.password_dir = self.local_password_path()
self.password_filename = self.username + '.pwd'
self.password_file = os.path.join(self.password_dir, self.password_filename)
def local_password_path(self):
"""Return the local password path.
Related toissue: Password files in same configuration dir in effect #2143
"""
if self.config is None:
return user_config_dir()
else:
return self.config.get_value('passwords',
'local_password_path',
default=user_config_dir())
def sha256_hash(self, plain_password):
"""Return the SHA-256 of the given password."""
return hashlib.sha256(b(plain_password)).hexdigest()

View File

@ -10,7 +10,7 @@
"""Cloud plugin.
Supported Cloud API:
- OpenStack meta data (class ThreadOpenStack, see bellow): AWS, OVH...
- OpenStack meta data (class ThreadOpenStack, see below): AWS, OVH...
"""
import threading

View File

@ -10,7 +10,7 @@
"""CPU plugin."""
from glances.timer import getTimeSinceLastUpdate
from glances.globals import LINUX, iterkeys
from glances.globals import LINUX, WINDOWS, SUNOS, iterkeys
from glances.cpu_percent import cpu_percent
from glances.plugins.core.model import PluginModel as CorePluginModel
from glances.plugins.plugin.model import GlancesPluginModel
@ -35,6 +35,10 @@ User CPU time is the time spent on the processor running your program\'s code (o
operations to complete.',
'unit': 'percent',
},
'dpc': {
'description': '*(Windows)*: time spent servicing deferred procedure calls (DPCs)',
'unit': 'percent',
},
'idle': {
'description': 'percent of CPU used by any program. Every program or task \
that runs on a computer system occupies a certain amount of processing \
@ -164,8 +168,23 @@ class PluginModel(GlancesPluginModel):
stats = self.get_init_value()
stats['total'] = cpu_percent.get()
# Grab: 'user', 'system', 'idle', 'nice', 'iowait',
# 'irq', 'softirq', 'steal', 'guest', 'guest_nice'
# Standards stats
# - user: time spent by normal processes executing in user mode; on Linux this also includes guest time
# - system: time spent by processes executing in kernel mode
# - idle: time spent doing nothing
# - nice (UNIX): time spent by niced (prioritized) processes executing in user mode
# on Linux this also includes guest_nice time
# - iowait (Linux): time spent waiting for I/O to complete.
# This is not accounted in idle time counter.
# - irq (Linux, BSD): time spent for servicing hardware interrupts
# - softirq (Linux): time spent for servicing software interrupts
# - steal (Linux 2.6.11+): time spent by other operating systems running in a virtualized environment
# - guest (Linux 2.6.24+): time spent running a virtual CPU for guest operating systems under
# the control of the Linux kernel
# - guest_nice (Linux 3.2.0+): time spent running a niced guest (virtual CPU for guest operating systems
# under the control of the Linux kernel)
# - interrupt (Windows): time spent for servicing hardware interrupts ( similar to “irq” on UNIX)
# - dpc (Windows): time spent servicing deferred procedure calls (DPCs)
cpu_times_percent = psutil.cpu_times_percent(interval=0.0)
for stat in cpu_times_percent._fields:
stats[stat] = getattr(cpu_times_percent, stat)
@ -255,7 +274,7 @@ class PluginModel(GlancesPluginModel):
# Add specifics information
# Alert and log
for key in ['user', 'system', 'iowait', 'total']:
for key in ['user', 'system', 'iowait', 'dpc', 'total']:
if key in self.stats:
self.views[key]['decoration'] = self.get_alert_log(self.stats[key], header=key)
# Alert only
@ -308,19 +327,9 @@ class PluginModel(GlancesPluginModel):
msg = '{:4.1f}%'.format(self.stats['idle'])
ret.append(self.curse_add_line(msg, optional=self.get_views(key='idle', option='optional')))
# ctx_switches
if 'ctx_switches' in self.stats:
msg = ' {:8}'.format('ctx_sw:')
ret.append(self.curse_add_line(msg, optional=self.get_views(key='ctx_switches', option='optional')))
msg = '{:>5}'.format(
self.auto_unit(int(self.stats['ctx_switches'] // self.stats['time_since_update']), min_symbol='K')
)
ret.append(
self.curse_add_line(
msg,
self.get_views(key='ctx_switches', option='decoration'),
optional=self.get_views(key='ctx_switches', option='optional'),
)
)
# On WINDOWS/SUNOS the ctx_switches is displayed in the third line
if not WINDOWS and not SUNOS:
ret.extend(self.curse_add_stat('ctx_switches', width=15, header=' '))
# New line
ret.append(self.curse_new_line())
@ -360,27 +369,20 @@ class PluginModel(GlancesPluginModel):
# Nice CPU
ret.extend(self.curse_add_stat('nice', width=14, header=' '))
# soft_interrupts
if 'soft_interrupts' in self.stats:
msg = ' {:8}'.format('sw_int:')
ret.append(self.curse_add_line(msg, optional=self.get_views(key='soft_interrupts', option='optional')))
msg = '{:>5}'.format(int(self.stats['soft_interrupts'] // self.stats['time_since_update']))
ret.append(self.curse_add_line(msg, optional=self.get_views(key='soft_interrupts', option='optional')))
if not WINDOWS and not SUNOS:
ret.extend(self.curse_add_stat('soft_interrupts', width=15, header=' '))
else:
ret.extend(self.curse_add_stat('ctx_switches', width=15, header=' '))
# Fourth line
# iowait + steal + syscalls
ret.append(self.curse_new_line())
# IOWait CPU
if 'iowait' in self.stats:
msg = '{:8}'.format('iowait:')
ret.append(self.curse_add_line(msg, optional=self.get_views(key='iowait', option='optional')))
msg = '{:5.1f}%'.format(self.stats['iowait'])
ret.append(
self.curse_add_line(
msg,
self.get_views(key='iowait', option='decoration'),
optional=self.get_views(key='iowait', option='optional'),
)
)
# IOWait CPU
ret.extend(self.curse_add_stat('iowait', width=15))
elif 'dpc' in self.stats:
# DPC CPU
ret.extend(self.curse_add_stat('dpc', width=15))
# Steal CPU usage
ret.extend(self.curse_add_stat('steal', width=14, header=' '))
# syscalls: number of system calls since boot. Always set to 0 on Linux. (do not display)

View File

@ -106,7 +106,7 @@ class PluginModel(GlancesPluginModel):
# Loop over fs
for fs in fs_stat:
# Shall we display the stats ?
# Hide the stats if the mount point is in the exclude list
if not self.is_display(fs.mountpoint):
continue
@ -128,6 +128,12 @@ class PluginModel(GlancesPluginModel):
'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
stats.append(fs_current)
elif self.input_method == 'snmp':

View File

@ -60,6 +60,16 @@ items_history_list = [{'name': 'cpu_percent', 'description': 'Container CPU cons
# List of key to remove before export
export_exclude_list = ['cpu', 'io', 'memory', 'network']
# Sort dictionary for human
sort_for_human = {
'io_counters': 'disk IO',
'cpu_percent': 'CPU consumption',
'memory_usage': 'memory consumption',
'cpu_times': 'uptime',
'name': 'container name',
None: 'None',
}
class PluginModel(GlancesPluginModel):
"""Glances Docker plugin.
@ -98,6 +108,9 @@ class PluginModel(GlancesPluginModel):
# value: network stats dict
self.io_old = {}
# Sort key
self.sort_key = None
# Force a first update because we need two update to have the first stat
self.update()
self.refresh_timer.set(0)
@ -208,7 +221,7 @@ class PluginModel(GlancesPluginModel):
for container in containers:
if container.id not in self.thread_list:
# Thread did not exist in the internal dict
# Create it and add it to the internal dict
# Create it, add it to the internal dict and start it
logger.debug(
"{} plugin - Create thread for container {}".format(self.plugin_name, container.id[:12])
)
@ -236,10 +249,8 @@ class PluginModel(GlancesPluginModel):
container_stats = {}
# The key is the container name and not the Id
container_stats['key'] = self.get_key()
# Export name (first name in the Names list, without the /)
# Export name
container_stats['name'] = nativestr(container.name)
# Export global Names (used by the WebUI)
container_stats['Names'] = [nativestr(container.name)]
# Container Id
container_stats['Id'] = container.id
# Container Image
@ -307,7 +318,7 @@ class PluginModel(GlancesPluginModel):
pass
# Sort and update the stats
self.stats = sort_stats(stats)
self.sort_key, self.stats = sort_docker_stats(stats)
return self.stats
@ -537,8 +548,10 @@ class PluginModel(GlancesPluginModel):
ret.append(self.curse_add_line(msg, "TITLE"))
msg = ' {}'.format(len(self.stats['containers']))
ret.append(self.curse_add_line(msg))
msg = ' (served by Docker {})'.format(self.stats['version']["Version"])
msg = ' sorted by {}'.format(sort_for_human[self.sort_key])
ret.append(self.curse_add_line(msg))
# msg = ' (served by Docker {})'.format(self.stats['version']["Version"])
# ret.append(self.curse_add_line(msg))
ret.append(self.curse_new_line())
# Header
ret.append(self.curse_new_line())
@ -549,24 +562,24 @@ class PluginModel(GlancesPluginModel):
len(max(self.stats['containers'], key=lambda x: len(x['name']))['name']),
)
msg = ' {:{width}}'.format('Name', width=name_max_width)
ret.append(self.curse_add_line(msg))
ret.append(self.curse_add_line(msg, 'SORT' if self.sort_key == 'name' else 'DEFAULT'))
msg = '{:>10}'.format('Status')
ret.append(self.curse_add_line(msg))
msg = '{:>10}'.format('Uptime')
ret.append(self.curse_add_line(msg))
msg = '{:>6}'.format('CPU%')
ret.append(self.curse_add_line(msg))
ret.append(self.curse_add_line(msg, 'SORT' if self.sort_key == 'cpu_percent' else 'DEFAULT'))
msg = '{:>7}'.format('MEM')
ret.append(self.curse_add_line(msg))
msg = '{:>7}'.format('/MAX')
ret.append(self.curse_add_line(msg, 'SORT' if self.sort_key == 'memory_usage' else 'DEFAULT'))
msg = '/{:<7}'.format('MAX')
ret.append(self.curse_add_line(msg))
msg = '{:>7}'.format('IOR/s')
ret.append(self.curse_add_line(msg))
msg = '{:>7}'.format('IOW/s')
msg = ' {:<7}'.format('IOW/s')
ret.append(self.curse_add_line(msg))
msg = '{:>7}'.format('Rx/s')
ret.append(self.curse_add_line(msg))
msg = '{:>7}'.format('Tx/s')
msg = ' {:<7}'.format('Tx/s')
ret.append(self.curse_add_line(msg))
msg = ' {:8}'.format('Command')
ret.append(self.curse_add_line(msg))
@ -598,19 +611,24 @@ class PluginModel(GlancesPluginModel):
msg = '{:>7}'.format('_')
ret.append(self.curse_add_line(msg, self.get_views(item=container['name'], key='mem', option='decoration')))
try:
msg = '{:>7}'.format(self.auto_unit(container['memory']['limit']))
msg = '/{:<7}'.format(self.auto_unit(container['memory']['limit']))
except KeyError:
msg = '{:>7}'.format('_')
msg = '/{:<7}'.format('_')
ret.append(self.curse_add_line(msg))
# IO R/W
unit = 'B'
for r in ['ior', 'iow']:
try:
value = self.auto_unit(int(container['io'][r] // container['io']['time_since_update'])) + unit
msg = '{:>7}'.format(value)
except KeyError:
msg = '{:>7}'.format('_')
ret.append(self.curse_add_line(msg))
try:
value = self.auto_unit(int(container['io']['ior'] // container['io']['time_since_update'])) + unit
msg = '{:>7}'.format(value)
except KeyError:
msg = '{:>7}'.format('_')
ret.append(self.curse_add_line(msg))
try:
value = self.auto_unit(int(container['io']['iow'] // container['io']['time_since_update'])) + unit
msg = ' {:<7}'.format(value)
except KeyError:
msg = ' {:<7}'.format('_')
ret.append(self.curse_add_line(msg))
# NET RX/TX
if args.byte:
# Bytes per second (for dummy)
@ -620,18 +638,28 @@ class PluginModel(GlancesPluginModel):
# Bits per second (for real network administrator | Default)
to_bit = 8
unit = 'b'
for r in ['rx', 'tx']:
try:
value = (
self.auto_unit(
int(container['network'][r] // container['network']['time_since_update'] * to_bit)
)
+ unit
try:
value = (
self.auto_unit(
int(container['network']['rx'] // container['network']['time_since_update'] * to_bit)
)
msg = '{:>7}'.format(value)
except KeyError:
msg = '{:>7}'.format('_')
ret.append(self.curse_add_line(msg))
+ unit
)
msg = '{:>7}'.format(value)
except KeyError:
msg = '{:>7}'.format('_')
ret.append(self.curse_add_line(msg))
try:
value = (
self.auto_unit(
int(container['network']['tx'] // container['network']['time_since_update'] * to_bit)
)
+ unit
)
msg = ' {:<7}'.format(value)
except KeyError:
msg = ' {:<7}'.format('_')
ret.append(self.curse_add_line(msg))
# Command
if container['Command'] is not None:
msg = ' {}'.format(' '.join(container['Command']))
@ -643,11 +671,7 @@ class PluginModel(GlancesPluginModel):
def _msg_name(self, container, max_width):
"""Build the container name."""
name = container['name']
if len(name) > max_width:
name = '_' + name[-max_width + 1 :]
else:
name = name[:max_width]
name = container['name'][:max_width]
return ' {:{width}}'.format(name, width=max_width)
def container_alert(self, status):
@ -695,8 +719,8 @@ class ThreadDockerGrabber(threading.Thread):
time.sleep(0.1)
if self.stopped():
break
except:
logger.debug("docker plugin - Exception thrown during run")
except Exception as e:
logger.debug("docker plugin - Exception thrown during run ({})".format(e))
self.stop()
@property
@ -719,12 +743,24 @@ class ThreadDockerGrabber(threading.Thread):
return self._stopper.is_set()
def sort_stats(stats):
def sort_docker_stats(stats):
# Sort Docker stats using the same function than processes
sort_by = 'cpu_percent'
sort_by = glances_processes.sort_key
sort_by_secondary = 'memory_usage'
if glances_processes.sort_key.startswith('memory'):
if sort_by == 'memory_percent':
sort_by = 'memory_usage'
sort_by_secondary = 'cpu_percent'
sort_stats_processes(stats['containers'], sorted_by=sort_by, sorted_by_secondary=sort_by_secondary)
return stats
elif sort_by in ['username', 'io_counters', 'cpu_times']:
sort_by = 'cpu_percent'
# Sort docker stats
sort_stats_processes(
stats['containers'],
sorted_by=sort_by,
sorted_by_secondary=sort_by_secondary,
# Reverse for all but name
reverse=glances_processes.sort_key != 'name',
)
# Return the main sort key and the sorted stats
return sort_by, stats

View File

@ -12,9 +12,12 @@ Help plugin.
Just a stupid plugin to display the help screen.
"""
import sys
from glances.compat import iteritems
from collections import OrderedDict
from glances import __version__, psutil_version
from glances.plugins.plugin.model import GlancesPluginModel
from itertools import chain
class PluginModel(GlancesPluginModel):
@ -30,8 +33,13 @@ class PluginModel(GlancesPluginModel):
# We want to display the stat in the curse interface
self.display_curse = True
# init data dictionary
self.view_data = {}
# init data dictionary, to preserve insertion order
if sys.version_info < (3, 6):
from collections import OrderedDict
self.view_data = OrderedDict()
else:
self.view_data = {}
self.generate_view_data()
def reset(self):
@ -53,68 +61,69 @@ class PluginModel(GlancesPluginModel):
msg_col = ' {0:1} {1:34}'
msg_header = '{0:39}'
"""First column"""
self.view_data['header_sort'] = msg_header.format('SORT PROCESSES:')
self.view_data['sort_auto'] = msg_col.format('a', 'Automatically')
self.view_data['sort_cpu'] = msg_col.format('c', 'CPU%')
self.view_data['sort_io_rate'] = msg_col.format('i', 'I/O rate')
self.view_data['sort_mem'] = msg_col.format('m', 'MEM%')
self.view_data['sort_process_name'] = msg_col.format('p', 'Process name')
self.view_data['sort_cpu_times'] = msg_col.format('t', 'TIME')
self.view_data['sort_user'] = msg_col.format('u', 'USER')
self.view_data['header_show_hide'] = msg_header.format('SHOW/HIDE SECTION:')
self.view_data['show_hide_application_monitoring'] = msg_col.format('A', 'Application monitoring')
self.view_data['show_hide_diskio'] = msg_col.format('d', 'Disk I/O')
self.view_data['show_hide_docker'] = msg_col.format('D', 'Docker')
self.view_data['show_hide_top_extended_stats'] = msg_col.format('e', 'Top extended stats')
self.view_data['show_hide_filesystem'] = msg_col.format('f', 'Filesystem')
self.view_data['show_hide_gpu'] = msg_col.format('G', 'GPU')
self.view_data['show_hide_ip'] = msg_col.format('I', 'IP')
self.view_data['show_hide_tcp_connection'] = msg_col.format('K', 'TCP')
self.view_data['show_hide_alert'] = msg_col.format('l', 'Alert logs')
self.view_data['show_hide_network'] = msg_col.format('n', 'Network')
self.view_data['show_hide_current_time'] = msg_col.format('N', 'Time')
self.view_data['show_hide_irq'] = msg_col.format('Q', 'IRQ')
self.view_data['show_hide_raid_plugin'] = msg_col.format('R', 'RAID')
self.view_data['show_hide_sensors'] = msg_col.format('s', 'Sensors')
self.view_data['show_hide_wifi_module'] = msg_col.format('W', 'Wifi')
self.view_data['show_hide_processes'] = msg_col.format('z', 'Processes')
self.view_data['show_hide_left_sidebar'] = msg_col.format('2', 'Left sidebar')
"""Second column"""
self.view_data['show_hide_quick_look'] = msg_col.format('3', 'Quick Look')
self.view_data['show_hide_cpu_mem_swap'] = msg_col.format('4', 'CPU, MEM, and SWAP')
self.view_data['show_hide_all'] = msg_col.format('5', 'ALL')
self.view_data['header_toggle'] = msg_header.format('TOGGLE DATA TYPE:')
self.view_data['toggle_bits_bytes'] = msg_col.format('b', 'Network I/O: bits/bytes')
self.view_data['toggle_count_rate'] = msg_col.format('B', 'Disk I/O: count/rate')
self.view_data['toggle_used_free'] = msg_col.format('F', 'Filesystem space: used/free')
self.view_data['toggle_bar_sparkline'] = msg_col.format('S', 'Quick Look: bar/sparkline')
self.view_data['toggle_separate_combined'] = msg_col.format('T', 'Network I/O: separate/combined')
self.view_data['toggle_live_cumulative'] = msg_col.format('U', 'Network I/O: live/cumulative')
self.view_data['toggle_linux_percentage'] = msg_col.format('0', 'Load: Linux/percentage')
self.view_data['toggle_cpu_individual_combined'] = msg_col.format('1', 'CPU: individual/combined')
self.view_data['toggle_gpu_individual_combined'] = msg_col.format('6', 'GPU: individual/combined')
self.view_data['toggle_short_full'] = msg_col.format('/', 'Process names: short/full')
self.view_data['header_miscellaneous'] = msg_header.format('MISCELLANEOUS:')
self.view_data['misc_erase_process_filter'] = msg_col.format('E', 'Erase process filter')
self.view_data['misc_generate_history_graphs'] = msg_col.format('g', 'Generate history graphs')
self.view_data['misc_help'] = msg_col.format('h', 'HELP')
self.view_data['misc_accumulate_processes_by_program'] = msg_col.format('j', 'Accumulate processes by program')
self.view_data['misc_increase_nice_process'] = msg_col.format('+', 'Increase nice process (need admin rights)')
self.view_data['misc_decrease_nice_process'] = msg_col.format('-', 'Decrease nice process')
self.view_data['misc_kill_process'] = msg_col.format('k', 'Kill process')
self.view_data['misc_reset_processes_summary_min_max'] = msg_col.format('M', 'Reset processes summary min/max')
self.view_data['misc_quit'] = msg_col.format('q', 'QUIT (or Esc or Ctrl-C)')
self.view_data['misc_reset_history'] = msg_col.format('r', 'Reset history')
self.view_data['misc_delete_warning_alerts'] = msg_col.format('w', 'Delete warning alerts')
self.view_data['misc_delete_warning_and_critical_alerts'] = msg_col.format(
'x', 'Delete warning & critical alerts'
self.view_data.update(
[
## First column
#
('header_sort', msg_header.format('SORT PROCESSES:')),
('sort_auto', msg_col.format('a', 'Automatically')),
('sort_cpu', msg_col.format('c', 'CPU%')),
('sort_io_rate', msg_col.format('i', 'I/O rate')),
('sort_mem', msg_col.format('m', 'MEM%')),
('sort_process_name', msg_col.format('p', 'Process name')),
('sort_cpu_times', msg_col.format('t', 'TIME')),
('sort_user', msg_col.format('u', 'USER')),
('header_show_hide', msg_header.format('SHOW/HIDE SECTION:')),
('show_hide_application_monitoring', msg_col.format('A', 'Application monitoring')),
('show_hide_diskio', msg_col.format('d', 'Disk I/O')),
('show_hide_docker', msg_col.format('D', 'Docker')),
('show_hide_top_extended_stats', msg_col.format('e', 'Top extended stats')),
('show_hide_filesystem', msg_col.format('f', 'Filesystem')),
('show_hide_gpu', msg_col.format('G', 'GPU')),
('show_hide_ip', msg_col.format('I', 'IP')),
('show_hide_tcp_connection', msg_col.format('K', 'TCP')),
('show_hide_alert', msg_col.format('l', 'Alert logs')),
('show_hide_network', msg_col.format('n', 'Network')),
('show_hide_current_time', msg_col.format('N', 'Time')),
('show_hide_irq', msg_col.format('Q', 'IRQ')),
('show_hide_raid_plugin', msg_col.format('R', 'RAID')),
('show_hide_sensors', msg_col.format('s', 'Sensors')),
('show_hide_wifi_module', msg_col.format('W', 'Wifi')),
('show_hide_processes', msg_col.format('z', 'Processes')),
('show_hide_left_sidebar', msg_col.format('2', 'Left sidebar')),
## Second column
#
('show_hide_quick_look', msg_col.format('3', 'Quick Look')),
('show_hide_cpu_mem_swap', msg_col.format('4', 'CPU, MEM, and SWAP')),
('show_hide_all', msg_col.format('5', 'ALL')),
('header_toggle', msg_header.format('TOGGLE DATA TYPE:')),
('toggle_bits_bytes', msg_col.format('b', 'Network I/O, bits/bytes')),
('toggle_count_rate', msg_col.format('B', 'Disk I/O, count/rate')),
('toggle_used_free', msg_col.format('F', 'Filesystem space, used/free')),
('toggle_bar_sparkline', msg_col.format('S', 'Quick Look, bar/sparkline')),
('toggle_separate_combined', msg_col.format('T', 'Network I/O, separate/combined')),
('toggle_live_cumulative', msg_col.format('U', 'Network I/O, live/cumulative')),
('toggle_linux_percentage', msg_col.format('0', 'Load, Linux/percentage')),
('toggle_cpu_individual_combined', msg_col.format('1', 'CPU, individual/combined')),
('toggle_gpu_individual_combined', msg_col.format('6', 'GPU, individual/combined')),
('toggle_short_full', msg_col.format('/', 'Process names, short/full')),
('header_miscellaneous', msg_header.format('MISCELLANEOUS:')),
('misc_erase_process_filter', msg_col.format('E', 'Erase process filter')),
('misc_generate_history_graphs', msg_col.format('g', 'Generate history graphs')),
('misc_help', msg_col.format('h', 'HELP')),
('misc_accumulate_processes_by_program', msg_col.format('j', 'Accumulate processes by program')),
('misc_increase_nice_process', msg_col.format('+', 'Increase nice process')),
('misc_decrease_nice_process', msg_col.format('-', 'Decrease nice process (need admin rights)')),
('misc_kill_process', msg_col.format('k', 'Kill process')),
('misc_reset_processes_summary_min_max', msg_col.format('M', 'Reset processes summary min/max')),
('misc_quit', msg_col.format('q', 'QUIT (or Esc or Ctrl-C)')),
('misc_reset_history', msg_col.format('r', 'Reset history')),
('misc_delete_warning_alerts', msg_col.format('w', 'Delete warning alerts')),
('misc_delete_warning_and_critical_alerts', msg_col.format('x', 'Delete warning & critical alerts')),
('misc_theme_white', msg_col.format('9', 'Optimize colors for white background')),
('misc_edit_process_filter_pattern', ' ENTER: Edit process filter pattern'),
]
)
self.view_data['misc_edit_process_filter_pattern'] = ' ENTER: Edit process filter pattern'
def get_view_data(self, args=None):
"""Return the view."""
@ -137,86 +146,36 @@ class PluginModel(GlancesPluginModel):
ret.append(self.curse_new_line())
# Keys
ret.append(self.curse_add_line(self.view_data['header_sort']))
ret.append(self.curse_add_line(self.view_data['show_hide_quick_look']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['sort_auto']))
ret.append(self.curse_add_line(self.view_data['show_hide_cpu_mem_swap']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['sort_cpu']))
ret.append(self.curse_add_line(self.view_data['show_hide_all']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['sort_io_rate']))
ret.append(self.curse_add_line(self.view_data['header_toggle']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['sort_mem']))
ret.append(self.curse_add_line(self.view_data['toggle_bits_bytes']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['sort_process_name']))
ret.append(self.curse_add_line(self.view_data['toggle_count_rate']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['sort_cpu_times']))
ret.append(self.curse_add_line(self.view_data['toggle_used_free']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['sort_user']))
ret.append(self.curse_add_line(self.view_data['toggle_bar_sparkline']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['header_show_hide']))
ret.append(self.curse_add_line(self.view_data['toggle_separate_combined']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_application_monitoring']))
ret.append(self.curse_add_line(self.view_data['toggle_live_cumulative']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_diskio']))
ret.append(self.curse_add_line(self.view_data['toggle_linux_percentage']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_docker']))
ret.append(self.curse_add_line(self.view_data['toggle_cpu_individual_combined']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_top_extended_stats']))
ret.append(self.curse_add_line(self.view_data['toggle_gpu_individual_combined']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_filesystem']))
ret.append(self.curse_add_line(self.view_data['toggle_short_full']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_gpu']))
ret.append(self.curse_add_line(self.view_data['header_miscellaneous']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_ip']))
ret.append(self.curse_add_line(self.view_data['misc_erase_process_filter']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_tcp_connection']))
ret.append(self.curse_add_line(self.view_data['misc_generate_history_graphs']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_alert']))
ret.append(self.curse_add_line(self.view_data['misc_help']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_network']))
ret.append(self.curse_add_line(self.view_data['misc_accumulate_processes_by_program']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_current_time']))
ret.append(self.curse_add_line(self.view_data['misc_kill_process']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_irq']))
ret.append(self.curse_add_line(self.view_data['misc_reset_processes_summary_min_max']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_raid_plugin']))
ret.append(self.curse_add_line(self.view_data['misc_quit']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_sensors']))
ret.append(self.curse_add_line(self.view_data['misc_reset_history']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_wifi_module']))
ret.append(self.curse_add_line(self.view_data['misc_delete_warning_alerts']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_processes']))
ret.append(self.curse_add_line(self.view_data['misc_delete_warning_and_critical_alerts']))
ret.append(self.curse_new_line())
ret.append(self.curse_add_line(self.view_data['show_hide_left_sidebar']))
ret.append(self.curse_add_line(self.view_data['misc_edit_process_filter_pattern']))
## key-shortcuts
#
# Collect all values after the 1st key-msg
# in a list of curse-lines.
#
shortcuts = []
collecting = False
for k, v in iteritems(self.view_data):
if collecting:
pass
elif k == 'header_sort':
collecting = True
else:
continue
shortcuts.append(self.curse_add_line(v))
# Divide shortcuts into 2 columns
# and if number of schortcuts is even,
# make the 1st column taller (len+1).
#
nlines = (len(shortcuts) + 1) // 2
ret.extend(
msg
for triplet in zip(
iter(shortcuts[:nlines]),
chain(shortcuts[nlines:], iter(lambda: self.curse_add_line(''), None)),
iter(self.curse_new_line, None),
)
for msg in triplet
)
ret.append(self.curse_new_line())
ret.append(self.curse_new_line())
ret.append(self.curse_add_line('For an exhaustive list of key bindings:'))
ret.append(self.curse_new_line())

View File

@ -33,8 +33,6 @@ else:
# - json: service return a JSON (True) or string (False)
# - key: key of the IP address in the JSON structure
urls = [
# glances_ip.py plugin relies on low rating / malicious site domain #1975
# ('https://ip.42.pl/raw', False, None),
('https://httpbin.org/ip', True, 'origin'),
('https://api.ipify.org/?format=json', True, 'ip'),
('https://ipv4.jsonip.com', True, 'ip'),
@ -128,8 +126,10 @@ class PluginModel(GlancesPluginModel):
logger.debug("Cannot grab public IP information ({})".format(e))
else:
stats['public_address'] = self.public_address
stats['public_info'] = self.public_info
stats['public_info_human'] = self.public_info_for_human(stats['public_info'])
# Too much information provided in the public_info
# Limit it to public_info_for_human
# stats['public_info'] = self.public_info
stats['public_info_human'] = self.public_info_for_human(self.public_info)
elif self.input_method == 'snmp':
# Not implemented yet

View File

@ -134,7 +134,7 @@ class PluginModel(GlancesPluginModel):
# Call the father's method
super(PluginModel, self).update_views()
# Add specifics informations
# Add specifics information
try:
# Alert and log
self.views['min15']['decoration'] = self.get_alert_log(

View File

@ -515,7 +515,7 @@ class GlancesPluginModel(object):
If key is None, return all the view for the current plugin
else if option is None return the view for the specific key (all option)
else return the view fo the specific key/option
else return the view of the specific key/option
Specify item if the stats are stored in a dict of dict (ex: NETWORK, FS...)
"""
@ -830,7 +830,9 @@ class GlancesPluginModel(object):
show=sda.*
"""
# @TODO: possible optimisation: create a re.compile list
return any(j for j in [re.match(i.lower(), value.lower()) for i in self.get_conf_value('show', header=header)])
return any(
j for j in [re.fullmatch(i.lower(), value.lower()) for i in self.get_conf_value('show', header=header)]
)
def is_hide(self, value, header=""):
"""Return True if the value is in the hide configuration list.
@ -841,7 +843,9 @@ class GlancesPluginModel(object):
hide=sda2,sda5,loop.*
"""
# @TODO: possible optimisation: create a re.compile list
return any(j for j in [re.match(i.lower(), value.lower()) for i in self.get_conf_value('hide', header=header)])
return any(
j for j in [re.fullmatch(i.lower(), value.lower()) for i in self.get_conf_value('hide', header=header)]
)
def is_display(self, value, header=""):
"""Return True if the value should be displayed in the UI"""

View File

@ -9,8 +9,13 @@
"""Process count plugin."""
<<<<<<< HEAD:glances/plugins/processcount/model.py
from glances.processes import glances_processes
from glances.plugins.plugin.model import GlancesPluginModel
=======
from glances.processes import glances_processes, sort_for_human
from glances.plugins.glances_plugin import GlancesPlugin
>>>>>>> develop:glances/plugins/glances_processcount.py
# Define the history items list
items_history_list = [
@ -27,16 +32,6 @@ class PluginModel(GlancesPluginModel):
stats is a list
"""
sort_for_human = {
'io_counters': 'disk IO',
'cpu_percent': 'CPU consumption',
'memory_percent': 'memory consumption',
'cpu_times': 'process time',
'username': 'user name',
'name': 'process name',
None: 'None',
}
def __init__(self, args=None, config=None):
"""Init the plugin."""
super(PluginModel, self).__init__(args=args, config=config, items_history_list=items_history_list)
@ -70,7 +65,7 @@ class PluginModel(GlancesPluginModel):
stats = glances_processes.get_count()
elif self.input_method == 'snmp':
# Update stats using SNMP
# Not availaible
# Not available
pass
# Update the stats
@ -133,7 +128,7 @@ class PluginModel(GlancesPluginModel):
# Display sort information
msg = 'Programs' if self.args.programs else 'Threads'
try:
sort_human = self.sort_for_human[glances_processes.sort_key]
sort_human = sort_for_human[glances_processes.sort_key]
except KeyError:
sort_human = glances_processes.sort_key
if glances_processes.auto_sort:

View File

@ -372,7 +372,7 @@ class PluginModel(GlancesPluginModel):
msg = self.layout_stat['pid'].format(p['pid'], width=self.__max_pid_size())
else:
# Display programs, so the PID should not be displayed
# Instead displays the number of childrens
# Instead displays the number of children
msg = self.layout_stat['pid'].format(
len(p['childrens']) if 'childrens' in p else '_', width=self.__max_pid_size()
)
@ -512,6 +512,8 @@ class PluginModel(GlancesPluginModel):
# Process list
# Loop over processes (sorted by the sort key previously compute)
# This is a Glances bottleneck (see flame graph),
# get_process_curses_data should be optimzed
i = 0
for p in self.__sort_stats(process_sort_key):
ret.extend(self.get_process_curses_data(p, i == args.cursor_position, args))

View File

@ -19,6 +19,17 @@ import psutil
# This constant defines the list of available processes sort key
sort_processes_key_list = ['cpu_percent', 'memory_percent', 'username', 'cpu_times', 'io_counters', 'name']
# Sort dictionary for human
sort_for_human = {
'io_counters': 'disk IO',
'cpu_percent': 'CPU consumption',
'memory_percent': 'memory consumption',
'cpu_times': 'process time',
'username': 'user name',
'name': 'processs name',
None: 'None',
}
class GlancesProcesses(object):
"""Get processed stats using the psutil library."""
@ -252,6 +263,7 @@ class GlancesProcesses(object):
#####################
sorted_attrs = ['cpu_percent', 'cpu_times', 'memory_percent', 'name', 'status', 'num_threads']
displayed_attr = ['memory_info', 'nice', 'pid']
# 'name' can not be cached because it is used for filtering
cached_attrs = ['cmdline', 'username']
# Some stats are optional
@ -273,6 +285,7 @@ class GlancesProcesses(object):
is_cached = True
# Build the processes stats list (it is why we need psutil>=5.3.0)
# This is on of the main bottleneck of Glances (see flame graph)
self.processlist = [
p.info
for p in psutil.process_iter(attrs=sorted_attrs, ad_value=None)
@ -309,7 +322,7 @@ class GlancesProcesses(object):
top_process = psutil.Process(proc['pid'])
extended_stats = ['cpu_affinity', 'ionice', 'num_ctx_switches']
if LINUX:
# num_fds only avalable on Unix system (see issue #1351)
# num_fds only available on Unix system (see issue #1351)
extended_stats += ['num_fds']
if WINDOWS:
extended_stats += ['num_handles']

View File

@ -16,7 +16,7 @@ from subprocess import Popen, PIPE
def secure_popen(cmd):
"""A more or less secure way to execute system commands
Multiple command should be seperated with a &&
Multiple command should be separated with a &&
:return: the result of the commands
"""

View File

@ -67,7 +67,8 @@ class GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler, object):
if username in self.server.user_dict:
from glances.password import GlancesPassword
pwd = GlancesPassword()
pwd = GlancesPassword(username=username,
config=self.config)
return pwd.check_password(self.server.user_dict[username], password)
else:
return False
@ -93,10 +94,14 @@ class GlancesXMLRPCServer(SimpleXMLRPCServer, object):
finished = False
def __init__(self, bind_address, bind_port=61209, requestHandler=GlancesXMLRPCHandler):
def __init__(self, bind_address,
bind_port=61209,
requestHandler=GlancesXMLRPCHandler,
config=None):
self.bind_address = bind_address
self.bind_port = bind_port
self.config = config
try:
self.address_family = socket.getaddrinfo(bind_address, bind_port)[0][0]
except socket.error as e:
@ -191,7 +196,10 @@ class GlancesServer(object):
# Init the XML RPC server
try:
self.server = GlancesXMLRPCServer(args.bind_address, args.port, requestHandler)
self.server = GlancesXMLRPCServer(args.bind_address,
args.port,
requestHandler,
config=config)
except Exception as e:
logger.critical("Cannot start Glances server: {}".format(e))
sys.exit(2)

View File

@ -115,7 +115,7 @@ class GlancesStats(object):
# on the console but do not crash
logger.critical("Error while initializing the {} plugin ({})".format(name, e))
logger.error(traceback.format_exc())
# An error occure, disable the plugin
# An error occurred, disable the plugin
if args is not None:
setattr(args, 'disable_' + name, False)
else:

View File

@ -47,7 +47,7 @@ class GlancesStatsClientSNMP(GlancesStats):
self.load_modules(self.args)
def check_snmp(self):
"""Chek if SNMP is available on the server."""
"""Check if SNMP is available on the server."""
# Import the SNMP client class
from glances.snmp import GlancesSNMPClient

View File

@ -27,6 +27,9 @@ class GlancesStatsServer(GlancesStats):
# all_stats is a dict of dicts filled by the server
self.all_stats = collections.defaultdict(dict)
# In the update method, disable extended process stats
logger.info("Disable extended processes stats in server mode")
def update(self, input_stats=None):
"""Update the stats."""
input_stats = input_stats or {}
@ -35,7 +38,6 @@ class GlancesStatsServer(GlancesStats):
super(GlancesStatsServer, self).update()
# Disable the extended processes stats because it cause an high CPU load
logger.info("Disable extended processes stats in server mode")
self._plugins['processcount'].disable_extended()
# Build all_stats variable (concatenation of all the stats)

View File

@ -11,8 +11,8 @@ docker>=2.0.0
elasticsearch
graphitesender
hddtemp
influxdb>=1.0.0
influxdb-client; python_version >= "3.6"
influxdb>=1.0.0 # For InfluxDB < 1.8
influxdb-client; python_version >= "3.7" # For InfluxDB >= 1.8
kafka-python
netifaces
py3nvml; python_version >= "3.0"
@ -32,5 +32,5 @@ six
sparklines
statsd
wifi
zeroconf==0.19.1; python_version < "3.0"
zeroconf; python_version >= "3.0"
zeroconf==0.19.1; python_version < "3.7"
zeroconf; python_version >= "3.7"

6
renovate.json Normal file
View File

@ -0,0 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
]
}

View File

@ -65,7 +65,7 @@ def get_install_extras_require():
'sparklines': ['sparklines'],
'web': ['bottle', 'requests'],
'wifi': ['wifi']
# 'gpu' and 'sensors' ==> See bellow
# 'gpu' and 'sensors' ==> See below
}
if sys.platform.startswith('linux'):
extras_require['sensors'] = ['batinfo']

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
# This is the maintainence launcher for the snap, make necessary runtime
# This is the maintenance launcher for the snap, make necessary runtime
# environment changes to make the snap work here. You may also insert
# security confinement/deprecation/obsoletion notice of the snap here.
set \

View File

@ -13,7 +13,7 @@ confinement: strict
apps:
glances:
command: glances-launch $SNAP/bin/glances
command: bin/glances-launch $SNAP/bin/glances
plugs:
- network
- system-observe
@ -63,6 +63,7 @@ parts:
cp -r $SNAPCRAFT_PART_BUILD/dist $SNAPCRAFT_PART_INSTALL/bottle-dist
organize:
bottle-dist: bottle/dist
docker:
plugin: python
source: https://github.com/docker/docker-py.git
@ -73,11 +74,13 @@ parts:
cp -r $SNAPCRAFT_PART_BUILD/dist $SNAPCRAFT_PART_INSTALL/docker-dist
organize:
bottle-dist: docker/dist
launchers:
source: snap/local/launchers
plugin: dump
organize:
'*': bin/
selective-checkout:
plugin: nil
build-packages:

View File

@ -325,7 +325,7 @@ class TestGlances(unittest.TestCase):
msg='{} view is not a dict'.format(plugin))
def test_097_attribute(self):
"""Test GlancesAttribute classe"""
"""Test GlancesAttribute classes"""
print('INFO: [TEST_097] Test attribute')
# GlancesAttribute
from glances.attribute import GlancesAttribute
@ -348,7 +348,7 @@ class TestGlances(unittest.TestCase):
self.assertEqual(a.history_mean(nb=3), 4.5)
def test_098_history(self):
"""Test GlancesHistory classe"""
"""Test GlancesHistory classes"""
print('INFO: [TEST_098] Test history')
# GlancesHistory
from glances.history import GlancesHistory

4
webui-requirements.txt Normal file
View File

@ -0,0 +1,4 @@
# install with base requirements file
-r requirements.txt
bottle