diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index be17203f..f5e4565d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install pip install build tools run: >- @@ -44,16 +44,16 @@ jobs: --outdir dist/ - name: Publish distribution package to Test PyPI - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.TEST_PYPI_API_TOKEN }} - repository_url: https://test.pypi.org/legacy/ - skip_existing: true + repository-url: https://test.pypi.org/legacy/ + skip-existing: true - name: Publish distribution package to PyPI if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} @@ -101,11 +101,11 @@ jobs: tag: ${{ fromJson(needs.create_Docker_builds.outputs.tags) }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Retrieve Repository Docker metadata id: docker_meta - uses: crazy-max/ghaction-docker-meta@v4.6.0 + uses: crazy-max/ghaction-docker-meta@v5.0.0 with: images: ${{ env.DEFAULT_DOCKER_IMAGE }} labels: | @@ -119,25 +119,25 @@ jobs: restore-keys: ${{ runner.os }}-buildx-${{ env.NODE_ENV }}-${{ matrix.os }} - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 with: platforms: all - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 with: version: latest - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 if: ${{ env.PUSH_BRANCH == 'true' }} with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Build and push image - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: push: ${{ env.PUSH_BRANCH == 'true' }} tags: "${{ env.DEFAULT_DOCKER_IMAGE }}:${{ matrix.os != 'alpine' && format('{0}-', matrix.os) || '' }}${{ matrix.tag.tag }}" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d3237f44..143d5183 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3f770fb6..e7fa9c44 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,11 +10,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 @@ -64,11 +64,12 @@ jobs: runs-on: windows-latest strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] - + # Python version "3.12" introduce this issue: + # https://github.com/nicolargo/glances/actions/runs/6439648370/job/17487567454 + python-version: ["3.8", "3.9", "3.10", "3.11"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 diff --git a/Makefile b/Makefile index 4ffc82b9..4d809eba 100644 --- a/Makefile +++ b/Makefile @@ -80,8 +80,11 @@ test-min: ## Run unit tests in minimal environment test-min-with-upgrade: venv-min-upgrade ## Upgrade deps and run unit tests in minimal environment ./venv-min/bin/python ./unitest.py +test-restful-api: ## Run unit tests of the RESTful API + ./venv/bin/python ./unitest-restful.py + # =================================================================== -# Linters and profilers +# Linters, profilers and cyber security # =================================================================== format: ## Format the code @@ -99,7 +102,7 @@ codespell: ## Run codespell to fix common misspellings in text files ./venv-dev/bin/codespell -S .git,./docs/_build,./Glances.egg-info,./venv*,./glances/outputs,*.svg -L hart,bu,te,statics semgrep: ## Run semgrep to find bugs and enforce code standards - ./venv-dev/bin/semgrep --config=auto --lang python --use-git-ignore ./glances + ./venv-dev/bin/semgrep scan --config=auto profiling: ## How to start the profiling of the Glances software @echo "Please complete and run: sudo ./venv-dev/bin/py-spy record -o ./docs/_static/glances-flame.svg -d 60 -s --pid " @@ -123,6 +126,10 @@ memory-profiling: ## Profile memory usage ./venv-dev/bin/mprof plot --output ./docs/_static/glances-memory-profiling-without-history.png rm -f mprofile_*.dat +# Trivy installation: https://aquasecurity.github.io/trivy/latest/getting-started/installation/ +trivy: ## Run Trivy to find vulnerabilities in container images + trivy fs . + # =================================================================== # Docs # =================================================================== @@ -167,6 +174,12 @@ flatpak: venv-dev-upgrade ## Generate FlatPack JSON file rm -rf ./flatpak-builder-tools @echo "Now follow: https://github.com/flathub/flathub/wiki/App-Submission" +# Snap package is automaticaly build on the Snapcraft.io platform +# https://snapcraft.io/glances +# But you can try an offline build with the following command +snapcraft: + snapcraft + # =================================================================== # Docker # =================================================================== diff --git a/NEWS.rst b/NEWS.rst index e40a63c1..cc0c8394 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -8,6 +8,22 @@ Version 4.0.0 Under development: https://github.com/nicolargo/glances/issues?q=is%3Aopen+is%3Aissue+milestone%3A%22Glances+4.0.0%22 +**BREAKING CHANGES:** + + * The Glances API version 3 is replaced by the version 4. So Restfull API URL is now /api/4/ #2610 + * Alias definition change in the configuration file #1735 + + Glances version 3.x and lower: + + sda1_alias=InternalDisk + sdb1_alias=ExternalDisk + + Glances version 4.x and higher: + + alias=sda1:InternalDisk,sdb1:ExternalDisk + + * Alert data model change from a list of list to a list of dict #2633 + =============== Version 3.4.0.3 =============== @@ -899,7 +915,7 @@ Processes list Nice value: [processlist] # Nice priorities range from -20 to 19. - # Configure nice levels using a comma separated list. + # Configure nice levels using a comma-separated list. # # Nice: Example 1, non-zero is warning (default behavior) nice_warning=-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 diff --git a/README.rst b/README.rst index 98f4f70a..8ea0b903 100644 --- a/README.rst +++ b/README.rst @@ -92,19 +92,21 @@ Optional dependencies: - ``batinfo`` (for battery monitoring) - ``bernhard`` (for the Riemann export module) -- ``bottle`` (for Web server mode) - ``cassandra-driver`` (for the Cassandra export module) - ``chevron`` (for the action script feature) -- ``couchdb`` (for the CouchDB export module) - ``docker`` (for the Containers Docker monitoring support) - ``elasticsearch`` (for the Elastic Search export module) +- ``FastAPI`` and ``Uvicorn`` (for Web server mode) - ``graphitesender`` (For the Graphite export module) - ``hddtemp`` (for HDD temperature monitoring support) [Linux-only] - ``influxdb`` (for the InfluxDB version 1 export module) - ``influxdb-client`` (for the InfluxDB version 2 export module) +- ``jinja2`` (for templating, used under the hood by FastAPI) - ``kafka-python`` (for the Kafka export module) - ``netifaces`` (for the IP plugin) +- ``orjson`` (fast JSON library, used under the hood by FastAPI) - ``py3nvml`` (for the GPU plugin) +- ``pycouchdb`` (for the CouchDB export module) - ``pika`` (for the RabbitMQ/ActiveMQ export module) - ``podman`` (for the Containers Podman monitoring support) - ``potsdb`` (for the OpenTSDB export module) @@ -140,8 +142,8 @@ To install Glances, simply use ``pip``: pip install --user glances *Note*: Python headers are required to install `psutil`_, a Glances -dependency. For example, on Debian/Ubuntu you need to install first -the *python-dev* package (*python-devel* on Fedora/CentOS/RHEL). +dependency. For example, on Debian/Ubuntu **the simplest** is ``apt install python3-psutil`` or alternatively need to install first +the *python-dev* package and gcc (*python-devel* on Fedora/CentOS/RHEL). For Windows, just install psutil from the binary installation file. *Note 2 (for the Wifi plugin)*: If you want to use the Wifi plugin, you need @@ -207,10 +209,10 @@ Get the Glances container: The following tags are availables: - *latest-full* for a full Alpine Glances image (latest release) with all dependencies -- *latest* for a basic Alpine Glances (latest release) version with minimal dependencies (Bottle and Docker) +- *latest* for a basic Alpine Glances (latest release) version with minimal dependencies (FastAPI and Docker) - *dev* for a basic Alpine Glances image (based on development branch) with all dependencies (Warning: may be instable) - *ubuntu-latest-full* for a full Ubuntu Glances image (latest release) with all dependencies -- *ubuntu-latest* for a basic Ubuntu Glances (latest release) version with minimal dependencies (Bottle and Docker) +- *ubuntu-latest* for a basic Ubuntu Glances (latest release) version with minimal dependencies (FastAPI and Docker) - *ubuntu-dev* for a basic Ubuntu Glances image (based on development branch) with all dependencies (Warning: may be instable) Run last version of Glances container in *console mode*: @@ -219,14 +221,16 @@ Run last version of Glances container in *console mode*: docker run --rm -e TZ="${TZ}" -v /var/run/docker.sock:/var/run/docker.sock:ro -v /run/user/1000/podman/podman.sock:/run/user/1000/podman/podman.sock:ro --pid host --network host -it nicolargo/glances:latest-full +By default, the /etc/glances/glances.conf file is used (based on docker-compose/glances.conf). + Additionally, if you want to use your own glances.conf file, you can create your own Dockerfile: .. code-block:: console FROM nicolargo/glances:latest - COPY glances.conf /etc/glances.conf - CMD python -m glances -C /etc/glances.conf $GLANCES_OPT + COPY glances.conf /root/.config/glances/glances.conf + CMD python -m glances -C /root/.config/glances/glances.conf $GLANCES_OPT Alternatively, you can specify something along the same lines with docker run options (notice the `GLANCES_OPT` environment @@ -234,7 +238,7 @@ variable setting parameters for the glances startup command): .. code-block:: console - docker run -e TZ="${TZ}" -v `pwd`/glances.conf:/etc/glances.conf -v /var/run/docker.sock:/var/run/docker.sock:ro -v /run/user/1000/podman/podman.sock:/run/user/1000/podman/podman.sock:ro --pid host -e GLANCES_OPT="-C /etc/glances.conf" -it nicolargo/glances:latest-full + docker run -e TZ="${TZ}" -v `pwd`/glances.conf:/root/.config/glances/glances.conf -v /var/run/docker.sock:/var/run/docker.sock:ro -v /run/user/1000/podman/podman.sock:/run/user/1000/podman/podman.sock:ro --pid host -e GLANCES_OPT="-C /root/.config/glances/glances.conf" -it nicolargo/glances:latest-full Where \`pwd\`/glances.conf is a local directory containing your glances.conf file. @@ -252,7 +256,7 @@ GNU/Linux `Glances` is available on many Linux distributions, so you should be able to install it using your favorite package manager. Be aware that when you use this method the operating system `package`_ for `Glances` -may not be the latest version. +may not be the latest version and only basics plugins are enabled. Note: The Debian package (and all other Debian-based distributions) do not include anymore the JS statics files used by the Web interface @@ -319,7 +323,7 @@ Start Termux on your device and enter: $ apt update $ apt upgrade $ apt install clang python - $ pip install bottle + $ pip install fastapi uvicorn orjson jinja2 $ pip install glances And start Glances: diff --git a/conf/glances.conf b/conf/glances.conf index 0fdf4651..35122262 100644 --- a/conf/glances.conf +++ b/conf/glances.conf @@ -14,16 +14,23 @@ check_update=true history_size=1200 # Set the way Glances should display the date (default is %Y-%m-%d %H:%M:%S %Z) #strftime_format="%Y-%m-%d %H:%M:%S %Z" +# Define external directory for loading additional plugins +# The layout follows the glances standard for plugin definitions +#plugin_dir=/home/user/dev/plugins ############################################################################## # User interface ############################################################################## [outputs] -# Theme name for the Curses interface: black or white +# Theme name (for the moment only for the Curses interface: black or white) curse_theme=black +# Separator in the Curses and WebUI interface (between top and others plugins) +separator=True +# Set the the Curses and WebUI interface left menu plugin list (comma-separated) +#left_menu=network,wifi,connections,ports,diskio,fs,irq,folders,raid,smart,sensors,now # Limit the number of processes to display (for the WebUI) -max_processes_display=30 +max_processes_display=25 # Set the URL prefix (for the WebUI and the API) # Example: url_prefix=/glances/ => http://localhost/glances/ # The final / is mandatory @@ -38,8 +45,11 @@ max_processes_display=30 # Set to true to disable a plugin # Note: you can also disable it from the command line (see --disable-plugin ) disable=False -# Graphical percentage char used in the terminal user interface (default is |) -percentage_char=| +# Stats list (default is cpu,mem,load) +# Available stats are: cpu,mem,load,swap +list=cpu,mem,load +# Graphical bar char used in the terminal user interface (default is |) +bar_char=| # Define CPU, MEM and SWAP thresholds in % cpu_careful=50 cpu_warning=70 @@ -50,6 +60,11 @@ mem_critical=90 swap_careful=50 swap_warning=70 swap_critical=90 +# Source: http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages +# With 1 CPU core, the load should be lower than 1.00 ~ 100% +load_careful=70 +load_warning=100 +load_critical=500 [system] # This plugin display the first line in the Glances UI with: @@ -167,8 +182,6 @@ tx_critical=90 #hide=docker.*,lo # Define the list of wireless network interfaces to be show (comma-separated) #show=docker.* -# WLAN 0 alias -#wlan0_alias=Wireless # It is possible to overwrite the bitrate thresholds per interface # WLAN 0 Default limits (in bits per second aka bps) for interface bitrate #wlan0_rx_careful=4000000 @@ -179,6 +192,8 @@ tx_critical=90 #wlan0_tx_warning=900000 #wlan0_tx_critical=1000000 #wlan0_tx_log=True +# Alias for network interface name +alias=wlp2s0:WIFI [ip] disable=False @@ -218,8 +233,8 @@ disable=False hide=loop.*,/dev/loop.* # Define the list of disks to be show (comma-separated) #show=sda.* -# Alias for sda1 -#sda1_alias=InternalDisk +# Alias for sda1 and sdb1 +alias=sda1:InternalDisk,sdb1:ExternalDisk [fs] disable=False @@ -236,6 +251,8 @@ warning=70 critical=90 # Allow additional file system types (comma-separated FS type) #allow=shm +# Alias for root file system +alias=/:Root [irq] # Documentation: https://glances.readthedocs.io/en/latest/aoa/irq.html @@ -307,13 +324,7 @@ battery_careful=80 battery_warning=90 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 +#alias=core 0:CPU Core 0,core 1:CPU Core 1 [processcount] disable=False @@ -336,7 +347,7 @@ mem_warning=70 mem_critical=90 # # Nice priorities range from -20 to 19. -# Configure nice levels using a comma separated list. +# Configure nice levels using a comma-separated list. # # Nice: Example 1, non-zero is warning (default behavior) nice_warning=-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 @@ -394,37 +405,42 @@ port_default_gateway=True [containers] disable=False -# Only show specific containers (comma separated 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 separated list of container name or regular expression) +; show=telegraf +# Hide some containers (comma-separated list of container name or regular expression) # Comment this line to display all containers (default configuration) -#hide=telegraf +; hide=telegraf # Define the maximum docker size name (default is 20 chars) max_name_size=20 -#cpu_careful=50 +; cpu_careful=50 # Thresholds for CPU and MEM (in %) -#cpu_warning=70 -#cpu_critical=90 -#mem_careful=20 -#mem_warning=50 -#mem_critical=70 +; cpu_warning=70 +; cpu_critical=90 +; mem_careful=20 +; mem_warning=50 +; mem_critical=70 # # Per container thresholds -#containername_cpu_careful=10 -#containername_cpu_warning=20 -#containername_cpu_critical=30 +; containername_cpu_careful=10 +; containername_cpu_warning=20 +; containername_cpu_critical=30 # # By default, Glances only display running containers # Set the following key to True to display all containers all=False # Define Podman sock -#podman_sock=unix:///run/user/1000/podman/podman.sock +; podman_sock=unix:///run/user/1000/podman/podman.sock [amps] # AMPs configuration are defined in the bottom of this file disable=False +[alert] +disable=False +# Maximum number of alerts to display (default is 10) +;max_events=10 + ############################################################################## # Client/server ############################################################################## @@ -466,7 +482,7 @@ path=/tmp # It is possible to generate the graphs automatically by setting the # 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 +generate_every=0 # See following configuration keys definitions in the Pygal lib documentation # http://pygal.org/en/stable/documentation/index.html width=800 @@ -590,10 +606,8 @@ topic_structure=per-metric 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 +user=admin +password=admin [mongodb] # Configuration for the --export mongodb option diff --git a/dev-requirements.txt b/dev-requirements.txt index aaae71eb..a93efd06 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -11,4 +11,6 @@ memory-profiler matplotlib semgrep setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability -numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability \ No newline at end of file +numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability +pillow>=10.0.1 # not directly required, pinned by Snyk to avoid a vulnerability +fonttools>=4.43.0 # not directly required, pinned by Snyk to avoid a vulnerability \ No newline at end of file diff --git a/docker-compose/Dockerfile b/docker-compose/Dockerfile index 81caa69a..51cbff4f 100644 --- a/docker-compose/Dockerfile +++ b/docker-compose/Dockerfile @@ -1,3 +1,3 @@ -FROM nicolargo/glances:latest as glancesminimal +FROM glances:local-alpine-minimal as glancesminimal COPY glances.conf /glances/conf/glances.conf CMD python -m glances -C /glances/conf/glances.conf $GLANCES_OPT diff --git a/docker-compose/docker-compose-with-traefik.yml b/docker-compose/docker-compose-with-traefik.yml index 32e9ff96..1f98d07b 100644 --- a/docker-compose/docker-compose-with-traefik.yml +++ b/docker-compose/docker-compose-with-traefik.yml @@ -25,15 +25,16 @@ services: - "/run/user/1000/podman/podman.sock:/run/user/1000/podman/podman.sock:ro" - "./glances.conf:/glances/conf/glances.conf" environment: - - GLANCES_OPT: "-C /glances/conf/glances.conf -w" - - TZ: "${TZ}" - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] + - TZ=${TZ} + - "GLANCES_OPT=-C /glances/conf/glances.conf -w" + # Uncomment for GPU compatibilty (Nvidia) inside the container + # deploy: + # resources: + # reservations: + # devices: + # - driver: nvidia + # count: 1 + # capabilities: [gpu] labels: - "traefik.port=61208" - "traefik.frontend.rule=Host:glances.docker.localhost" diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml index d1e18794..84e4bcf7 100644 --- a/docker-compose/docker-compose.yml +++ b/docker-compose/docker-compose.yml @@ -13,12 +13,13 @@ services: - "/run/user/1000/podman/podman.sock:/run/user/1000/podman/podman.sock:ro" - "./glances.conf:/glances/conf/glances.conf" environment: - - GLANCES_OPT: "-C /glances/conf/glances.conf -w" - - TZ: "${TZ}" - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] \ No newline at end of file + - TZ=${TZ} + - "GLANCES_OPT=-C /glances/conf/glances.conf -w" + # Uncomment for GPU compatibilty (Nvidia) inside the container + # deploy: + # resources: + # reservations: + # devices: + # - driver: nvidia + # count: 1 + # capabilities: [gpu] diff --git a/docker-compose/glances.conf b/docker-compose/glances.conf index ad22d4ae..e3924ee3 100644 --- a/docker-compose/glances.conf +++ b/docker-compose/glances.conf @@ -22,8 +22,12 @@ history_size=1200 [outputs] # Theme name for the Curses interface: black or white curse_theme=black -# Limit the number of processes to display in the WebUI -max_processes_display=30 +# Separator in the Curses and WebUI interface (between top and others plugins) +separator=True +# Set the the Curses and WebUI interface left menu plugin list (comma-separated) +#left_menu=network,wifi,connections,ports,diskio,fs,irq,folders,raid,smart,sensors,now +# Limit the number of processes to display (for the WebUI) +max_processes_display=25 # Set the URL prefix (for the WebUI and the API) # Example: url_prefix=/glances/ => http://localhost/glances/ # The final / is mandatory @@ -93,6 +97,7 @@ steal_warning=70 steal_critical=90 #steal_log=True # + # Context switch limit (core / second) # Leave commented to just use the default config (critical is 50000*# (Logical CPU cores) #ctx_switches_careful=10000 @@ -340,7 +345,7 @@ mem_warning=70 mem_critical=90 # # Nice priorities range from -20 to 19. -# Configure nice levels using a comma separated list. +# Configure nice levels using a comma-separated list. # # Nice: Example 1, non-zero is warning (default behavior) nice_warning=-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 @@ -398,37 +403,42 @@ port_default_gateway=True [containers] disable=False -# Only show specific containers (comma separated 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 separated list of container name or regular expression) +; show=telegraf +# Hide some containers (comma-separated list of container name or regular expression) # Comment this line to display all containers (default configuration) -#hide=telegraf +; hide=telegraf # Define the maximum docker size name (default is 20 chars) max_name_size=20 -#cpu_careful=50 +; cpu_careful=50 # Thresholds for CPU and MEM (in %) -#cpu_warning=70 -#cpu_critical=90 -#mem_careful=20 -#mem_warning=50 -#mem_critical=70 +; cpu_warning=70 +; cpu_critical=90 +; mem_careful=20 +; mem_warning=50 +; mem_critical=70 # # Per container thresholds -#containername_cpu_careful=10 -#containername_cpu_warning=20 -#containername_cpu_critical=30 +; containername_cpu_careful=10 +; containername_cpu_warning=20 +; containername_cpu_critical=30 # # By default, Glances only display running containers # Set the following key to True to display all containers all=False # Define Podman sock -#podman_sock=unix:///run/user/1000/podman/podman.sock +; podman_sock=unix:///run/user/1000/podman/podman.sock [amps] # AMPs configuration are defined in the bottom of this file disable=False +[alert] +disable=False +# Maximum number of alerts to display (default is 10) +; max_events=10 + ############################################################################## # Client/server ############################################################################## @@ -470,7 +480,7 @@ path=/tmp # It is possible to generate the graphs automatically by setting the # 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 +generate_every=0 # See following configuration keys definitions in the Pygal lib documentation # http://pygal.org/en/stable/documentation/index.html width=800 diff --git a/docker-files/alpine.Dockerfile b/docker-files/alpine.Dockerfile index b2ce10d7..a7624b4b 100644 --- a/docker-files/alpine.Dockerfile +++ b/docker-files/alpine.Dockerfile @@ -4,11 +4,13 @@ # https://github.com/nicolargo/glances # -# WARNING: the versions should be set. -# Ex: Python 3.11 for Alpine 3.18 # Note: ENV is for future running containers. ARG for building your Docker image. -ARG IMAGE_VERSION=3.18.3 +# WARNING: the Alpine image version and Python version should be set. +# Alpine 3.18 tag is a link to the latest 3.18.x version. +# Be aware that if you change the Alpine version, you may have to change the Python version. + +ARG IMAGE_VERSION=3.19 ARG PYTHON_VERSION=3.11 ############################################################################## @@ -83,7 +85,7 @@ RUN python${PYTHON_VERSION} -m pip install --target="/venv/lib/python${PYTHON_VE FROM base as release # Copy source code and config file -COPY ./docker-compose/glances.conf /etc/glances.conf +COPY ./docker-compose/glances.conf /etc/glances/glances.conf COPY /glances /app/glances # Copy binary and update PATH @@ -96,7 +98,7 @@ EXPOSE 61209 61208 # Define default command. WORKDIR /app -CMD /venv/bin/python3 -m glances -C /etc/glances.conf $GLANCES_OPT +CMD /venv/bin/python3 -m glances $GLANCES_OPT ################################################################################ # RELEASE: minimal diff --git a/docker-files/ubuntu.Dockerfile b/docker-files/ubuntu.Dockerfile index 5313bf54..be5bc09d 100644 --- a/docker-files/ubuntu.Dockerfile +++ b/docker-files/ubuntu.Dockerfile @@ -77,7 +77,7 @@ RUN python${PYTHON_VERSION} -m pip install --target="/venv/lib/python${PYTHON_VE FROM base as release # Copy Glances source code and config file -COPY ./docker-compose/glances.conf /etc/glances.conf +COPY ./docker-compose/glances.conf /etc/glances/glances.conf COPY /glances /app/glances # Copy binary and update PATH @@ -90,7 +90,7 @@ EXPOSE 61209 61208 # Define default command. WORKDIR /app -CMD /venv/bin/python3 -m glances -C /etc/glances.conf $GLANCES_OPT +CMD /venv/bin/python3 -m glances $GLANCES_OPT ################################################################################ # RELEASE: minimal diff --git a/docker-requirements.txt b/docker-requirements.txt index 0792572a..c93beffe 100644 --- a/docker-requirements.txt +++ b/docker-requirements.txt @@ -6,5 +6,5 @@ podman; python_version >= "3.6" packaging; python_version >= "3.7" python-dateutil six -urllib3<2.0 # See issue https://github.com/nicolargo/glances/issues/2392 -requests # See issue - https://github.com/nicolargo/glances/issues/2233 +urllib3<2.0 # See issue https://github.com/nicolargo/glances/issues/2617 +requests diff --git a/docs/_static/glances-flame.svg b/docs/_static/glances-flame.svg index 5ab6b70a..7edff6f7 100644 --- a/docs/_static/glances-flame.svg +++ b/docs/_static/glances-flame.svg @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/docs/aoa/containers.rst b/docs/aoa/containers.rst index c969b1e8..3750d3cf 100644 --- a/docs/aoa/containers.rst +++ b/docs/aoa/containers.rst @@ -21,11 +21,11 @@ under the ``[containers]`` section: [containers] disable=False - # Only show specific containers (comma separated 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 separated 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 separated 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 containers size name (default is 20 chars) max_name_size=20 diff --git a/docs/aoa/cpu.rst b/docs/aoa/cpu.rst index 3cd138f4..0d221643 100644 --- a/docs/aoa/cpu.rst +++ b/docs/aoa/cpu.rst @@ -15,17 +15,6 @@ displayed. .. image:: ../_static/cpu-wide.png -A character is also displayed just after the CPU header and shows the -trend value: - -======== ============================================================== -Trend Status -======== ============================================================== -``-`` CPU value is equal to the mean of the six latests refreshes -``\`` CPU value is lower than the mean of the six latests refreshes -``/`` CPU value is higher than the mean of the six latests refreshes -======== ============================================================== - CPU stats description: - **user**: percent time spent in user space. User CPU time is the time @@ -46,6 +35,8 @@ CPU stats description: operations to complete. - **steal** *(Linux)*: percentage of time a virtual CPU waits for a real CPU while the hypervisor is servicing another virtual processor. +- **guest** *(Linux)*: percentage of time a virtual CPU spends + servicing another virtual CPU under the control of the Linux kernel. - **ctx_sw**: number of context switches (voluntary + involuntary) per second. A context switch is a procedure that a computer's CPU (central processing unit) follows to change from one task (or process) to diff --git a/docs/aoa/load.rst b/docs/aoa/load.rst index 08374abb..57b1fc00 100644 --- a/docs/aoa/load.rst +++ b/docs/aoa/load.rst @@ -31,6 +31,17 @@ percentage. .. image:: ../_static/loadpercent.png +A character is also displayed just after the LOAD header and shows the +trend value (for the 1 minute load stat): + +======== ============================================================== +Trend Status +======== ============================================================== +``-`` Mean 15 lasts values equal mean 15 previous values +``↓`` Mean 15 lasts values is lower mean 15 previous values +``↑`` Mean 15 lasts values is higher mean 15 previous valuess +======== ============================================================== + Legend: ============= ============ diff --git a/docs/aoa/memory.rst b/docs/aoa/memory.rst index 8d68250a..fa62764a 100644 --- a/docs/aoa/memory.rst +++ b/docs/aoa/memory.rst @@ -47,9 +47,9 @@ trend value: ======== ============================================================== Trend Status ======== ============================================================== -``-`` MEM value is equal to the mean of the six latests refreshes -``\`` MEM value is lower than the mean of the six latests refreshes -``/`` MEM value is higher than the mean of the six latests refreshes +``-`` Mean 15 lasts values equal mean 15 previous values +``↓`` Mean 15 lasts values is lower mean 15 previous values +``↑`` Mean 15 lasts values is higher mean 15 previous valuess ======== ============================================================== Alerts are only set for used memory and used swap. diff --git a/docs/aoa/ps.rst b/docs/aoa/ps.rst index 310c8cd5..7b5d8cf8 100644 --- a/docs/aoa/ps.rst +++ b/docs/aoa/ps.rst @@ -190,7 +190,7 @@ In curses/standalone mode, you can select a process using ``UP`` and ``DOWN`` an .. note:: Limit for CPU and MEM percent values can be overwritten in the configuration file under the ``[processlist]`` section. It is also - possible to define limit for Nice values (comma separated list). + possible to define limit for Nice values (comma-separated list). For example: nice_warning=-20,-19,-18 Accumulated per program — key 'j' diff --git a/docs/aoa/quicklook.rst b/docs/aoa/quicklook.rst index 093a7814..82fac3aa 100644 --- a/docs/aoa/quicklook.rst +++ b/docs/aoa/quicklook.rst @@ -4,7 +4,7 @@ Quick Look ========== The ``quicklook`` plugin is only displayed on wide screen and proposes a -bar view for CPU and memory (virtual and swap). +bar view for cpu, memory, swap and load (this list is configurable). In the terminal interface, click on ``3`` to enable/disable it. @@ -27,10 +27,14 @@ client/server mode (see issue ). Limit values can be overwritten in the configuration file under the ``[quicklook]`` section. -You can also configure the percentage char used in the terminal user interface. +You can also configure the stats list and the bat character used in the +user interface. .. code-block:: ini [quicklook] + # Stats list (default is cpu,mem,load) + # Available stats are: cpu,mem,load,swap + list=cpu,mem,load # Graphical percentage char used in the terminal user interface (default is |) - percentage_char=@ + bar_char=| diff --git a/docs/api.rst b/docs/api.rst index 04d51eb5..a73d9bfa 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -3,21 +3,33 @@ API (Restfull/JSON) documentation ================================= +This documentation describes the Glances API version 4 (Restfull/JSON) interface. + +For Glances version 3, please have a look on: +``https://github.com/nicolargo/glances/blob/support/glancesv3/docs/api.rst`` + +Run the Glances API server +-------------------------- + The Glances Restfull/API server could be ran using the following command line: .. code-block:: bash # glances -w --disable-webui +It is also ran automatically when Glances is started in Web server mode (-w). + API URL ------- -The default root API URL is ``http://localhost:61208/api/3``. +The default root API URL is ``http://localhost:61208/api/4``. The bind address and port could be changed using the ``--bind`` and ``--port`` command line options. It is also possible to define an URL prefix using the ``url_prefix`` option from the [outputs] section -of the Glances configuration file. The url_prefix should always end with a slash (``/``). +of the Glances configuration file. + +Note: The url_prefix should always end with a slash (``/``). For example: @@ -25,19 +37,31 @@ For example: [outputs] url_prefix = /glances/ -will change the root API URL to ``http://localhost:61208/glances/api/3`` and the Web UI URL to +will change the root API URL to ``http://localhost:61208/glances/api/4`` and the Web UI URL to ``http://localhost:61208/glances/`` +API documentation URL +--------------------- + +The API documentation is embeded in the server and available at the following URL: +``http://localhost:61208/docs#/``. + +WebUI refresh +------------- + +It is possible to change the Web UI refresh rate (default is 2 seconds) using the following option in the URL: +``http://localhost:61208/glances/?refresh=5`` + GET API status -------------- This entry point should be used to check the API status. -It will return nothing but a 200 return code if everything is OK. +It will the Glances version and a 200 return code if everything is OK. Get the Rest API status:: - # curl -I http://localhost:61208/api/3/status + # curl -I http://localhost:61208/api/4/status "HTTP/1.0 200 OK" GET plugins list @@ -45,7 +69,7 @@ GET plugins list Get the plugins list:: - # curl http://localhost:61208/api/3/pluginslist + # curl http://localhost:61208/api/4/pluginslist ["alert", "amps", "cloud", @@ -76,6 +100,7 @@ Get the plugins list:: "smart", "system", "uptime", + "version", "wifi"] GET alert @@ -83,26 +108,62 @@ GET alert Get plugin stats:: - # curl http://localhost:61208/api/3/alert - [[1690293736.0, - -1, - "WARNING", - "MEM", - 77.54053433873582, - 77.54053433873582, - 77.54053433873582, - 77.54053433873582, - 1, - [], - "", - "memory_percent"]] + # curl http://localhost:61208/api/4/alert + [{"avg": 81.2614296446961, + "begin": 1706975961.0, + "count": 1, + "desc": "", + "end": -1, + "max": 81.2614296446961, + "min": 81.2614296446961, + "sort": "memory_percent", + "state": "WARNING", + "sum": 81.2614296446961, + "top": [], + "type": "MEM"}] + +Fields descriptions: + +* **begin**: Begin timestamp of the event (unit is *timestamp*) +* **end**: End timestamp of the event (or -1 if ongoing) (unit is *timestamp*) +* **state**: State of the event (WARNING|CRITICAL) (unit is *string*) +* **type**: Type of the event (CPU|LOAD|MEM) (unit is *string*) +* **max**: Maximum value during the event period (unit is *float*) +* **avg**: Average value during the event period (unit is *float*) +* **min**: Minimum value during the event period (unit is *float*) +* **sum**: Sum of the values during the event period (unit is *float*) +* **count**: Number of values during the event period (unit is *int*) +* **top**: Top 3 processes name during the event period (unit is *list*) +* **desc**: Description of the event (unit is *string*) +* **sort**: Sort key of the top processes (unit is *string*) + +Get a specific field:: + + # curl http://localhost:61208/api/4/alert/begin + {"begin": [1706975961.0]} + +Get a specific item when field matches the given value:: + + # curl http://localhost:61208/api/4/alert/begin/1706975961.0 + {"1706975961.0": [{"avg": 81.2614296446961, + "begin": 1706975961.0, + "count": 1, + "desc": "", + "end": -1, + "max": 81.2614296446961, + "min": 81.2614296446961, + "sort": "memory_percent", + "state": "WARNING", + "sum": 81.2614296446961, + "top": [], + "type": "MEM"}]} GET amps -------- Get plugin stats:: - # curl http://localhost:61208/api/3/amps + # curl http://localhost:61208/api/4/amps [{"count": 0, "countmax": None, "countmin": 1.0, @@ -111,7 +172,7 @@ Get plugin stats:: "refresh": 3.0, "regex": True, "result": None, - "timer": 0.23587393760681152}, + "timer": 0.32085204124450684}, {"count": 0, "countmax": 20.0, "countmin": None, @@ -120,16 +181,26 @@ Get plugin stats:: "refresh": 3.0, "regex": True, "result": None, - "timer": 0.2357802391052246}] + "timer": 0.32070302963256836}] + +Fields descriptions: + +* **name**: AMP name (unit is *None*) +* **result**: AMP result (a string) (unit is *None*) +* **refresh**: AMP refresh interval (unit is *second*) +* **timer**: Time until next refresh (unit is *second*) +* **count**: Number of matching processes (unit is *number*) +* **countmin**: Minimum number of matching processes (unit is *number*) +* **countmax**: Maximum number of matching processes (unit is *number*) Get a specific field:: - # curl http://localhost:61208/api/3/amps/name + # curl http://localhost:61208/api/4/amps/name {"name": ["Dropbox", "Python", "Conntrack", "Nginx", "Systemd", "SystemV"]} Get a specific item when field matches the given value:: - # curl http://localhost:61208/api/3/amps/name/Dropbox + # curl http://localhost:61208/api/4/amps/name/Dropbox {"Dropbox": [{"count": 0, "countmax": None, "countmin": 1.0, @@ -138,19 +209,31 @@ Get a specific item when field matches the given value:: "refresh": 3.0, "regex": True, "result": None, - "timer": 0.23587393760681152}]} + "timer": 0.32085204124450684}]} GET connections --------------- Get plugin stats:: - # curl http://localhost:61208/api/3/connections + # curl http://localhost:61208/api/4/connections {"net_connections_enabled": True, "nf_conntrack_enabled": True} +Fields descriptions: + +* **LISTEN**: Number of TCP connections in LISTEN state (unit is *number*) +* **ESTABLISHED**: Number of TCP connections in ESTABLISHED state (unit is *number*) +* **SYN_SENT**: Number of TCP connections in SYN_SENT state (unit is *number*) +* **SYN_RECV**: Number of TCP connections in SYN_RECV state (unit is *number*) +* **initiated**: Number of TCP connections initiated (unit is *number*) +* **terminated**: Number of TCP connections terminated (unit is *number*) +* **nf_conntrack_count**: Number of tracked connections (unit is *number*) +* **nf_conntrack_max**: Maximum number of tracked connections (unit is *number*) +* **nf_conntrack_percent**: Percentage of tracked connections (unit is *percent*) + Get a specific field:: - # curl http://localhost:61208/api/3/connections/net_connections_enabled + # curl http://localhost:61208/api/4/connections/net_connections_enabled {"net_connections_enabled": True} GET containers @@ -158,81 +241,101 @@ GET containers Get plugin stats:: - # curl http://localhost:61208/api/3/containers - {"containers": [{"Command": ["/portainer"], - "Created": "2022-10-29T14:59:10.266701439Z", - "Id": "3abd51c615968482d9ccff5afc629f267f6dda113ed68b75b432615fae3b49fb", - "Image": ["portainer/portainer-ce:2.9.3"], - "Status": "running", - "Uptime": "an hour", - "cpu": {"total": 0.0}, - "cpu_percent": 0.0, - "engine": "docker", - "io": {"cumulative_ior": 29429760, "cumulative_iow": 2326528}, - "io_r": None, - "io_w": None, - "key": "name", - "memory": {"cache": None, - "limit": 7836184576, - "max_usage": None, - "rss": None, - "usage": 21876736}, - "memory_usage": 21876736, - "name": "portainer", - "network": {"cumulative_rx": 401604, "cumulative_tx": 0}, - "network_rx": None, - "network_tx": None}, - {"Command": ["top"], - "Created": "2023-05-08T15:29:34.918692365+02:00", - "Id": "4b7f732d43e4bc5d92fe5298cba025b550e6a608754c1c38f9a90aaecd46b8f9", - "Image": "["docker.io/library/ubuntu:latest"]", - "Status": "running", - "Uptime": "2 months", - "cpu": {"total": 6.7650116939635326e-06}, - "cpu_percent": 6.7650116939635326e-06, - "engine": "podman", - "io": {"ior": 0.0, "iow": 0.0, "time_since_update": 1}, - "io_r": 0.0, - "io_w": 0.0, - "key": "name", - "memory": {"limit": 7836184576.0, "usage": 1093632.0}, - "memory_usage": 1093632.0, - "name": "frosty_bouman", - "network": {"rx": 0.0, "time_since_update": 1, "tx": 0.0}, - "network_rx": 0.0, - "network_tx": 0.0, - "pod_id": "8d0f1c783def", - "pod_name": "frosty_bouman"}, - {"Command": [], - "Created": "2022-10-22T14:23:03.120912374+02:00", - "Id": "9491515251edcd5bb5dc17205d7ee573c0be96fe0b08b0a12a7e2cea874565ea", - "Image": "["k8s.gcr.io/pause:3.5"]", - "Status": "running", - "Uptime": "2 months", - "cpu": {"total": 3.177554220933258e-10}, - "cpu_percent": 3.177554220933258e-10, - "engine": "podman", - "io": {"ior": 0.0, "iow": 0.0, "time_since_update": 1}, - "io_r": 0.0, - "io_w": 0.0, - "key": "name", - "memory": {"limit": 7836184576.0, "usage": 204800.0}, - "memory_usage": 204800.0, - "name": "8d0f1c783def-infra", - "network": {"rx": 0.0, "time_since_update": 1, "tx": 0.0}, - "network_rx": 0.0, - "network_tx": 0.0, - "pod_id": "8d0f1c783def", - "pod_name": "8d0f1c783def-infra"}], - "version": {}, - "version_podman": {}} + # curl http://localhost:61208/api/4/containers + [{"command": "/portainer", + "cpu": {"total": 0.0}, + "cpu_percent": 0.0, + "created": "2022-10-29T14:59:10.266701439Z", + "engine": "docker", + "id": "3abd51c615968482d9ccff5afc629f267f6dda113ed68b75b432615fae3b49fb", + "image": ["portainer/portainer-ce:2.9.3"], + "io": {"cumulative_ior": 1187840, "cumulative_iow": 2011136}, + "key": "name", + "memory": {"cache": None, + "limit": 7823585280, + "max_usage": None, + "rss": None, + "usage": 17010688}, + "memory_usage": 17010688, + "name": "portainer", + "network": {"cumulative_rx": 2966333, "cumulative_tx": 0}, + "status": "running", + "uptime": "1 weeks"}, + {"command": "top", + "cpu": {"total": 2.918210864825478e-06}, + "cpu_percent": 2.918210864825478e-06, + "created": "2023-12-09T10:45:34.339489876+01:00", + "engine": "podman", + "id": "481d6ffb7eef284d062628cf350bdd9ce0a803db8a2a505d75565ed24322b714", + "image": "docker.io/library/ubuntu:latest", + "io": {"ior": 0.0, "iow": 0.0, "time_since_update": 1}, + "io_rx": 0.0, + "io_wx": 0.0, + "key": "name", + "memory": {"limit": 7823585280.0, "usage": 1236992.0}, + "memory_usage": 1236992.0, + "name": "sad_darwin", + "network": {"rx": 0.0, "time_since_update": 1, "tx": 0.0}, + "network_rx": 0.0, + "network_tx": 0.0, + "pod_id": "8d0f1c783def", + "pod_name": "sad_darwin", + "status": "running", + "uptime": "1 months"}] + +Fields descriptions: + +* **name**: Container name (unit is *None*) +* **id**: Container ID (unit is *None*) +* **image**: Container image (unit is *None*) +* **status**: Container status (unit is *None*) +* **created**: Container creation date (unit is *None*) +* **command**: Container command (unit is *None*) +* **cpu_percent**: Container CPU consumption (unit is *percent*) +* **memory_usage**: Container memory usage (unit is *byte*) +* **io_rx**: Container IO bytes read rate (unit is *bytepersecond*) +* **io_wx**: Container IO bytes write rate (unit is *bytepersecond*) +* **network_rx**: Container network RX bitrate (unit is *bitpersecond*) +* **network_tx**: Container network TX bitrate (unit is *bitpersecond*) +* **uptime**: Container uptime (unit is *None*) +* **engine**: Container engine (Docker and Podman are currently supported) (unit is *None*) +* **pod_name**: Pod name (only with Podman) (unit is *None*) +* **pod_id**: Pod ID (only with Podman) (unit is *None*) + +Get a specific field:: + + # curl http://localhost:61208/api/4/containers/name + {"name": ["portainer", "sad_darwin", "8d0f1c783def-infra"]} + +Get a specific item when field matches the given value:: + + # curl http://localhost:61208/api/4/containers/name/portainer + {"portainer": [{"command": "/portainer", + "cpu": {"total": 0.0}, + "cpu_percent": 0.0, + "created": "2022-10-29T14:59:10.266701439Z", + "engine": "docker", + "id": "3abd51c615968482d9ccff5afc629f267f6dda113ed68b75b432615fae3b49fb", + "image": ["portainer/portainer-ce:2.9.3"], + "io": {"cumulative_ior": 1187840, "cumulative_iow": 2011136}, + "key": "name", + "memory": {"cache": None, + "limit": 7823585280, + "max_usage": None, + "rss": None, + "usage": 17010688}, + "memory_usage": 17010688, + "name": "portainer", + "network": {"cumulative_rx": 2966333, "cumulative_tx": 0}, + "status": "running", + "uptime": "1 weeks"}]} GET core -------- Get plugin stats:: - # curl http://localhost:61208/api/3/core + # curl http://localhost:61208/api/4/core {"log": 4, "phys": 2} Fields descriptions: @@ -242,7 +345,7 @@ Fields descriptions: Get a specific field:: - # curl http://localhost:61208/api/3/core/phys + # curl http://localhost:61208/api/4/core/phys {"phys": 2} GET cpu @@ -250,29 +353,28 @@ GET cpu Get plugin stats:: - # curl http://localhost:61208/api/3/cpu + # curl http://localhost:61208/api/4/cpu {"cpucore": 4, - "ctx_switches": 0, + "ctx_switches": 1565209189, "guest": 0.0, "guest_nice": 0.0, - "idle": 70.8, - "interrupts": 0, - "iowait": 0.0, + "idle": 69.3, + "interrupts": 673172772, + "iowait": 0.5, "irq": 0.0, "nice": 0.0, - "soft_interrupts": 0, - "softirq": 0.7, + "soft_interrupts": 382231833, + "softirq": 0.0, "steal": 0.0, "syscalls": 0, - "system": 4.4, - "time_since_update": 1, - "total": 29.2, - "user": 24.1} + "system": 3.5, + "total": 30.2, + "user": 26.6} Fields descriptions: * **total**: Sum of all CPU percentages (except idle) (unit is *percent*) -* **system**: percent time spent in kernel space. System CPU time is the time spent running code in the Operating System kernel (unit is *percent*) +* **system**: Percent time spent in kernel space. System CPU time is the time spent running code in the Operating System kernel (unit is *percent*) * **user**: CPU percent time spent in user space. User CPU time is the time spent on the processor running your program's code (or code in libraries) (unit is *percent*) * **iowait**: *(Linux)*: percent time spent by the CPU waiting for I/O operations to complete (unit is *percent*) * **dpc**: *(Windows)*: time spent servicing deferred procedure calls (DPCs) (unit is *percent*) @@ -280,123 +382,167 @@ Fields descriptions: * **irq**: *(Linux and BSD)*: percent time spent servicing/handling hardware/software interrupts. Time servicing interrupts (hardware + software) (unit is *percent*) * **nice**: *(Unix)*: percent time occupied by user level processes with a positive nice value. The time the CPU has spent running users' processes that have been *niced* (unit is *percent*) * **steal**: *(Linux)*: percentage of time a virtual CPU waits for a real CPU while the hypervisor is servicing another virtual processor (unit is *percent*) +* **guest**: *(Linux)*: time spent running a virtual CPU for guest operating systems under the control of the Linux kernel (unit is *percent*) * **ctx_switches**: number of context switches (voluntary + involuntary) per second. A context switch is a procedure that a computer's CPU (central processing unit) follows to change from one task (or process) to another while ensuring that the tasks do not conflict (unit is *number*) +* **ctx_switches_rate_per_sec**: number of context switches (voluntary + involuntary) per second. A context switch is a procedure that a computer's CPU (central processing unit) follows to change from one task (or process) to another while ensuring that the tasks do not conflict per second (unit is *number* per second) +* **ctx_switches_gauge**: number of context switches (voluntary + involuntary) per second. A context switch is a procedure that a computer's CPU (central processing unit) follows to change from one task (or process) to another while ensuring that the tasks do not conflict (cumulative) (unit is *number*) * **interrupts**: number of interrupts per second (unit is *number*) +* **interrupts_rate_per_sec**: number of interrupts per second per second (unit is *number* per second) +* **interrupts_gauge**: number of interrupts per second (cumulative) (unit is *number*) * **soft_interrupts**: number of software interrupts per second. Always set to 0 on Windows and SunOS (unit is *number*) +* **soft_interrupts_rate_per_sec**: number of software interrupts per second. Always set to 0 on Windows and SunOS per second (unit is *number* per second) +* **soft_interrupts_gauge**: number of software interrupts per second. Always set to 0 on Windows and SunOS (cumulative) (unit is *number*) * **syscalls**: number of system calls per second. Always 0 on Linux OS (unit is *number*) +* **syscalls_rate_per_sec**: number of system calls per second. Always 0 on Linux OS per second (unit is *number* per second) +* **syscalls_gauge**: number of system calls per second. Always 0 on Linux OS (cumulative) (unit is *number*) * **cpucore**: Total number of CPU core (unit is *number*) * **time_since_update**: Number of seconds since last update (unit is *seconds*) Get a specific field:: - # curl http://localhost:61208/api/3/cpu/total - {"total": 29.2} + # curl http://localhost:61208/api/4/cpu/total + {"total": 30.2} GET diskio ---------- Get plugin stats:: - # curl http://localhost:61208/api/3/diskio + # curl http://localhost:61208/api/4/diskio [{"disk_name": "sda", "key": "disk_name", - "read_bytes": 0, - "read_count": 0, - "time_since_update": 1, - "write_bytes": 0, - "write_count": 0}, - {"disk_name": "sda1", + "read_bytes": 157324110848, + "read_count": 11374333, + "write_bytes": 201555001344, + "write_count": 6582750}, + {"alias": "InternalDisk", + "disk_name": "sda1", "key": "disk_name", - "read_bytes": 0, - "read_count": 0, - "time_since_update": 1, + "read_bytes": 22958080, + "read_count": 713, "write_bytes": 0, - "write_count": 0}] + "write_count": 78}] + +Fields descriptions: + +* **disk_name**: Disk name (unit is *None*) +* **read_count**: Number of reads (unit is *number*) +* **read_count_rate_per_sec**: Number of reads per second (unit is *number* per second) +* **read_count_gauge**: Number of reads (cumulative) (unit is *number*) +* **write_count**: Number of writes (unit is *number*) +* **write_count_rate_per_sec**: Number of writes per second (unit is *number* per second) +* **write_count_gauge**: Number of writes (cumulative) (unit is *number*) +* **read_bytes**: Number of bytes read (unit is *byte*) +* **read_bytes_rate_per_sec**: Number of bytes read per second (unit is *byte* per second) +* **read_bytes_gauge**: Number of bytes read (cumulative) (unit is *byte*) +* **write_bytes**: Number of bytes written (unit is *byte*) +* **write_bytes_rate_per_sec**: Number of bytes written per second (unit is *byte* per second) +* **write_bytes_gauge**: Number of bytes written (cumulative) (unit is *byte*) Get a specific field:: - # curl http://localhost:61208/api/3/diskio/disk_name + # curl http://localhost:61208/api/4/diskio/disk_name {"disk_name": ["sda", "sda1", "sda2", "sda5", "dm-0", "dm-1"]} Get a specific item when field matches the given value:: - # curl http://localhost:61208/api/3/diskio/disk_name/sda + # curl http://localhost:61208/api/4/diskio/disk_name/sda {"sda": [{"disk_name": "sda", "key": "disk_name", - "read_bytes": 0, - "read_count": 0, - "time_since_update": 1, - "write_bytes": 0, - "write_count": 0}]} + "read_bytes": 157324110848, + "read_count": 11374333, + "write_bytes": 201555001344, + "write_count": 6582750}]} GET fs ------ Get plugin stats:: - # curl http://localhost:61208/api/3/fs - [{"device_name": "/dev/mapper/ubuntu--gnome--vg-root", - "free": 25133506560, + # curl http://localhost:61208/api/4/fs + [{"alias": "Root", + "device_name": "/dev/mapper/ubuntu--gnome--vg-root", + "free": 11921264640, "fs_type": "ext4", "key": "mnt_point", "mnt_point": "/", - "percent": 89.1, + "percent": 94.8, "size": 243334156288, - "used": 205813194752}, + "used": 219025436672}, {"device_name": "zsfpool", - "free": 41811968, + "free": 31195136, "fs_type": "zfs", "key": "mnt_point", "mnt_point": "/zsfpool", - "percent": 0.3, - "size": 41943040, - "used": 131072}] + "percent": 25.4, + "size": 41811968, + "used": 10616832}] + +Fields descriptions: + +* **device_name**: Device name (unit is *None*) +* **fs_type**: File system type (unit is *None*) +* **mnt_point**: Mount point (unit is *None*) +* **size**: Total size (unit is *byte*) +* **used**: Used size (unit is *byte*) +* **free**: Free size (unit is *byte*) +* **percent**: File system usage in percent (unit is *percent*) Get a specific field:: - # curl http://localhost:61208/api/3/fs/mnt_point + # curl http://localhost:61208/api/4/fs/mnt_point {"mnt_point": ["/", "/zsfpool", "/var/snap/firefox/common/host-hunspell"]} Get a specific item when field matches the given value:: - # curl http://localhost:61208/api/3/fs/mnt_point// - {"/": [{"device_name": "/dev/mapper/ubuntu--gnome--vg-root", - "free": 25133506560, + # curl http://localhost:61208/api/4/fs/mnt_point// + {"/": [{"alias": "Root", + "device_name": "/dev/mapper/ubuntu--gnome--vg-root", + "free": 11921264640, "fs_type": "ext4", "key": "mnt_point", "mnt_point": "/", - "percent": 89.1, + "percent": 94.8, "size": 243334156288, - "used": 205813194752}]} + "used": 219025436672}]} GET ip ------ Get plugin stats:: - # curl http://localhost:61208/api/3/ip - {"address": "192.168.1.14", - "gateway": "192.168.1.1", + # curl http://localhost:61208/api/4/ip + {"address": "192.168.0.32", + "gateway": "192.168.0.254", "mask": "255.255.255.0", "mask_cidr": 24, - "public_address": "92.151.148.66", + "public_address": "91.166.228.228", "public_info_human": ""} +Fields descriptions: + +* **address**: Private IP address (unit is *None*) +* **mask**: Private IP mask (unit is *None*) +* **mask_cidr**: Private IP mask in CIDR format (unit is *number*) +* **gateway**: Private IP gateway (unit is *None*) +* **public_address**: Public IP address (unit is *None*) +* **public_info_human**: Public IP information (unit is *None*) + Get a specific field:: - # curl http://localhost:61208/api/3/ip/gateway - {"gateway": "192.168.1.1"} + # curl http://localhost:61208/api/4/ip/gateway + {"gateway": "192.168.0.254"} GET load -------- Get plugin stats:: - # curl http://localhost:61208/api/3/load + # curl http://localhost:61208/api/4/load {"cpucore": 4, - "min1": 1.18505859375, - "min15": 1.17724609375, - "min5": 1.23779296875} + "min1": 1.7509765625, + "min15": 1.4345703125, + "min5": 1.2666015625} Fields descriptions: @@ -407,25 +553,25 @@ Fields descriptions: Get a specific field:: - # curl http://localhost:61208/api/3/load/min1 - {"min1": 1.18505859375} + # curl http://localhost:61208/api/4/load/min1 + {"min1": 1.7509765625} GET mem ------- Get plugin stats:: - # curl http://localhost:61208/api/3/mem - {"active": 3179450368, - "available": 1759965184, - "buffers": 139554816, - "cached": 2369826816, - "free": 1759965184, - "inactive": 3354943488, - "percent": 77.5, - "shared": 580452352, - "total": 7836184576, - "used": 6076219392} + # curl http://localhost:61208/api/4/mem + {"active": 2068942848, + "available": 1466028032, + "buffers": 165359616, + "cached": 1911681024, + "free": 1466028032, + "inactive": 4365434880, + "percent": 81.3, + "shared": 562696192, + "total": 7823585280, + "used": 6357557248} Fields descriptions: @@ -443,22 +589,22 @@ Fields descriptions: Get a specific field:: - # curl http://localhost:61208/api/3/mem/total - {"total": 7836184576} + # curl http://localhost:61208/api/4/mem/total + {"total": 7823585280} GET memswap ----------- Get plugin stats:: - # curl http://localhost:61208/api/3/memswap - {"free": 5171486720, - "percent": 36.0, - "sin": 30833557504, - "sout": 44998725632, + # curl http://localhost:61208/api/4/memswap + {"free": 6025789440, + "percent": 25.4, + "sin": 26750087168, + "sout": 36382937088, "time_since_update": 1, "total": 8082419712, - "used": 2910932992} + "used": 2056630272} Fields descriptions: @@ -472,7 +618,7 @@ Fields descriptions: Get a specific field:: - # curl http://localhost:61208/api/3/memswap/total + # curl http://localhost:61208/api/4/memswap/total {"total": 8082419712} GET network @@ -480,104 +626,107 @@ GET network Get plugin stats:: - # curl http://localhost:61208/api/3/network + # curl http://localhost:61208/api/4/network [{"alias": None, - "cumulative_cx": 1271814348, - "cumulative_rx": 635907174, - "cumulative_tx": 635907174, - "cx": 1070, + "cumulative_cx": 2849154006, + "cumulative_rx": 1424577003, + "cumulative_tx": 1424577003, + "cx": 0, "interface_name": "lo", "is_up": True, "key": "interface_name", - "rx": 535, + "rx": 0, "speed": 0, "time_since_update": 1, - "tx": 535}, - {"alias": None, - "cumulative_cx": 43280474609, - "cumulative_rx": 41602144558, - "cumulative_tx": 1678330051, - "cx": 4727, + "tx": 0}, + {"alias": "WIFI", + "cumulative_cx": 18617767483, + "cumulative_rx": 15193537585, + "cumulative_tx": 3424229898, + "cx": 224, "interface_name": "wlp2s0", "is_up": True, "key": "interface_name", - "rx": 663, + "rx": 98, "speed": 0, "time_since_update": 1, - "tx": 4064}] + "tx": 126}] Fields descriptions: * **interface_name**: Interface name (unit is *string*) * **alias**: Interface alias name (optional) (unit is *string*) -* **rx**: The received/input rate (in bit per second) (unit is *bps*) -* **tx**: The sent/output rate (in bit per second) (unit is *bps*) -* **cx**: The cumulative received+sent rate (in bit per second) (unit is *bps*) -* **cumulative_rx**: The number of bytes received through the interface (cumulative) (unit is *bytes*) -* **cumulative_tx**: The number of bytes sent through the interface (cumulative) (unit is *bytes*) -* **cumulative_cx**: The cumulative number of bytes reveived and sent through the interface (cumulative) (unit is *bytes*) -* **speed**: Maximum interface speed (in bit per second). Can return 0 on some operating-system (unit is *bps*) +* **rx**: The received/input rate (unit is *bitpersecond*) +* **tx**: The sent/output rate (unit is *bitpersecond*) +* **cx**: The cumulative received+sent rate (unit is *bitpersecond*) +* **cumulative_rx**: The number of bytes received through the interface (cumulative) (unit is *byte*) +* **cumulative_tx**: The number of bytes sent through the interface (cumulative) (unit is *byte*) +* **cumulative_cx**: The cumulative number of bytes reveived and sent through the interface (cumulative) (unit is *byte*) +* **speed**: Maximum interface speed (in bit per second). Can return 0 on some operating-system (unit is *bitpersecond*) * **is_up**: Is the interface up ? (unit is *bool*) * **time_since_update**: Number of seconds since last update (unit is *seconds*) Get a specific field:: - # curl http://localhost:61208/api/3/network/interface_name + # curl http://localhost:61208/api/4/network/interface_name {"interface_name": ["lo", "wlp2s0", + "br-40875d2e2716", "docker0", "br_grafana", "mpqemubr0", - "veth0868fe1", - "vboxnet0"]} + "vethbeef843", + "tap-838a195875f", + "lxdbr0", + "veth4cbf8f0a"]} Get a specific item when field matches the given value:: - # curl http://localhost:61208/api/3/network/interface_name/lo + # curl http://localhost:61208/api/4/network/interface_name/lo {"lo": [{"alias": None, - "cumulative_cx": 1271814348, - "cumulative_rx": 635907174, - "cumulative_tx": 635907174, - "cx": 1070, + "cumulative_cx": 2849154006, + "cumulative_rx": 1424577003, + "cumulative_tx": 1424577003, + "cx": 0, "interface_name": "lo", "is_up": True, "key": "interface_name", - "rx": 535, + "rx": 0, "speed": 0, "time_since_update": 1, - "tx": 535}]} + "tx": 0}]} GET now ------- Get plugin stats:: - # curl http://localhost:61208/api/3/now - "2023-07-25 16:02:16 CEST" + # curl http://localhost:61208/api/4/now + "2024-02-03 16:59:21 CET" GET percpu ---------- Get plugin stats:: - # curl http://localhost:61208/api/3/percpu + # curl http://localhost:61208/api/4/percpu [{"cpu_number": 0, "guest": 0.0, "guest_nice": 0.0, - "idle": 30.0, + "idle": 47.0, "iowait": 0.0, "irq": 0.0, "key": "cpu_number", "nice": 0.0, "softirq": 0.0, "steal": 0.0, - "system": 2.0, - "total": 70.0, + "system": 1.0, + "total": 53.0, "user": 4.0}, {"cpu_number": 1, "guest": 0.0, "guest_nice": 0.0, - "idle": 30.0, + "idle": 45.0, "iowait": 0.0, "irq": 0.0, "key": "cpu_number", @@ -585,12 +734,27 @@ Get plugin stats:: "softirq": 0.0, "steal": 0.0, "system": 0.0, - "total": 70.0, - "user": 4.0}] + "total": 55.0, + "user": 7.0}] + +Fields descriptions: + +* **cpu_number**: CPU number (unit is *None*) +* **total**: Sum of CPU percentages (except idle) for current CPU number (unit is *percent*) +* **system**: Percent time spent in kernel space. System CPU time is the time spent running code in the Operating System kernel (unit is *percent*) +* **user**: CPU percent time spent in user space. User CPU time is the time spent on the processor running your program's code (or code in libraries) (unit is *percent*) +* **iowait**: *(Linux)*: percent time spent by the CPU waiting for I/O operations to complete (unit is *percent*) +* **idle**: percent of CPU used by any program. Every program or task that runs on a computer system occupies a certain amount of processing time on the CPU. If the CPU has completed all tasks it is idle (unit is *percent*) +* **irq**: *(Linux and BSD)*: percent time spent servicing/handling hardware/software interrupts. Time servicing interrupts (hardware + software) (unit is *percent*) +* **nice**: *(Unix)*: percent time occupied by user level processes with a positive nice value. The time the CPU has spent running users' processes that have been *niced* (unit is *percent*) +* **steal**: *(Linux)*: percentage of time a virtual CPU waits for a real CPU while the hypervisor is servicing another virtual processor (unit is *percent*) +* **guest**: *(Linux)*: percent of time spent running a virtual CPU for guest operating systems under the control of the Linux kernel (unit is *percent*) +* **guest_nice**: *(Linux)*: percent of time spent running a niced guest (virtual CPU) (unit is *percent*) +* **softirq**: *(Linux)*: percent of time spent handling software interrupts (unit is *percent*) Get a specific field:: - # curl http://localhost:61208/api/3/percpu/cpu_number + # curl http://localhost:61208/api/4/percpu/cpu_number {"cpu_number": [0, 1, 2, 3]} GET ports @@ -598,82 +762,103 @@ GET ports Get plugin stats:: - # curl http://localhost:61208/api/3/ports + # curl http://localhost:61208/api/4/ports [{"description": "DefaultGateway", - "host": "192.168.1.1", + "host": "192.168.0.254", "indice": "port_0", "port": 0, "refresh": 30, "rtt_warning": None, - "status": 0.005154, + "status": 0.003976, "timeout": 3}] +Fields descriptions: + +* **host**: Measurement is be done on this host (or IP address) (unit is *None*) +* **port**: Measurement is be done on this port (0 for ICMP) (unit is *None*) +* **description**: Human readable description for the host/port (unit is *None*) +* **refresh**: Refresh time (in seconds) for this host/port (unit is *None*) +* **timeout**: Timeout (in seconds) for the measurement (unit is *None*) +* **status**: Measurement result (in seconds) (unit is *second*) +* **rtt_warning**: Warning threshold (in seconds) for the measurement (unit is *second*) +* **indice**: Unique indice for the host/port (unit is *None*) + Get a specific field:: - # curl http://localhost:61208/api/3/ports/host - {"host": ["192.168.1.1"]} + # curl http://localhost:61208/api/4/ports/host + {"host": ["192.168.0.254"]} Get a specific item when field matches the given value:: - # curl http://localhost:61208/api/3/ports/host/192.168.1.1 - {"192.168.1.1": [{"description": "DefaultGateway", - "host": "192.168.1.1", - "indice": "port_0", - "port": 0, - "refresh": 30, - "rtt_warning": None, - "status": 0.005154, - "timeout": 3}]} + # curl http://localhost:61208/api/4/ports/host/192.168.0.254 + {"192.168.0.254": [{"description": "DefaultGateway", + "host": "192.168.0.254", + "indice": "port_0", + "port": 0, + "refresh": 30, + "rtt_warning": None, + "status": 0.003976, + "timeout": 3}]} GET processcount ---------------- Get plugin stats:: - # curl http://localhost:61208/api/3/processcount - {"pid_max": 0, "running": 1, "sleeping": 323, "thread": 1643, "total": 391} + # curl http://localhost:61208/api/4/processcount + {"pid_max": 0, "running": 1, "sleeping": 337, "thread": 1652, "total": 405} + +Fields descriptions: + +* **total**: Total number of processes (unit is *number*) +* **running**: Total number of running processes (unit is *number*) +* **sleeping**: Total number of sleeping processes (unit is *number*) +* **thread**: Total number of threads (unit is *number*) +* **pid_max**: Maximum number of processes (unit is *number*) Get a specific field:: - # curl http://localhost:61208/api/3/processcount/total - {"total": 391} + # curl http://localhost:61208/api/4/processcount/total + {"total": 405} GET psutilversion ----------------- Get plugin stats:: - # curl http://localhost:61208/api/3/psutilversion - [5, 9, 5] + # curl http://localhost:61208/api/4/psutilversion + "5.9.7" GET quicklook ------------- Get plugin stats:: - # curl http://localhost:61208/api/3/quicklook - {"cpu": 29.2, - "cpu_hz": 3000000000.0, - "cpu_hz_current": 2649443250.0, + # curl http://localhost:61208/api/4/quicklook + {"cpu": 30.2, + "cpu_hz": 2025000000.0, + "cpu_hz_current": 1873965500.0, "cpu_name": "Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz", - "mem": 77.5, + "cpucore": 4, + "load": 35.9, + "mem": 81.3, "percpu": [{"cpu_number": 0, "guest": 0.0, "guest_nice": 0.0, - "idle": 30.0, + "idle": 47.0, "iowait": 0.0, "irq": 0.0, "key": "cpu_number", "nice": 0.0, "softirq": 0.0, "steal": 0.0, - "system": 2.0, - "total": 70.0, + "system": 1.0, + "total": 53.0, "user": 4.0}, {"cpu_number": 1, "guest": 0.0, "guest_nice": 0.0, - "idle": 30.0, + "idle": 45.0, "iowait": 0.0, "irq": 0.0, "key": "cpu_number", @@ -681,47 +866,57 @@ Get plugin stats:: "softirq": 0.0, "steal": 0.0, "system": 0.0, - "total": 70.0, - "user": 4.0}, + "total": 55.0, + "user": 7.0}, {"cpu_number": 2, "guest": 0.0, "guest_nice": 0.0, - "idle": 14.0, + "idle": 10.0, + "iowait": 1.0, + "irq": 0.0, + "key": "cpu_number", + "nice": 0.0, + "softirq": 0.0, + "steal": 0.0, + "system": 4.0, + "total": 90.0, + "user": 37.0}, + {"cpu_number": 3, + "guest": 0.0, + "guest_nice": 0.0, + "idle": 44.0, "iowait": 0.0, "irq": 0.0, "key": "cpu_number", "nice": 0.0, "softirq": 0.0, "steal": 0.0, - "system": 3.0, - "total": 86.0, - "user": 17.0}, - {"cpu_number": 3, - "guest": 0.0, - "guest_nice": 0.0, - "idle": 24.0, - "iowait": 0.0, - "irq": 0.0, - "key": "cpu_number", - "nice": 0.0, - "softirq": 1.0, - "steal": 0.0, "system": 2.0, - "total": 76.0, - "user": 9.0}], - "swap": 36.0} + "total": 56.0, + "user": 6.0}], + "swap": 25.4} + +Fields descriptions: + +* **cpu**: CPU percent usage (unit is *percent*) +* **mem**: MEM percent usage (unit is *percent*) +* **swap**: SWAP percent usage (unit is *percent*) +* **load**: LOAD percent usage (unit is *percent*) +* **cpu_name**: CPU name (unit is *None*) +* **cpu_hz_current**: CPU current frequency (unit is *hertz*) +* **cpu_hz**: CPU max frequency (unit is *hertz*) Get a specific field:: - # curl http://localhost:61208/api/3/quicklook/cpu - {"cpu": 29.2} + # curl http://localhost:61208/api/4/quicklook/cpu_name + {"cpu_name": "Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz"} GET sensors ----------- Get plugin stats:: - # curl http://localhost:61208/api/3/sensors + # curl http://localhost:61208/api/4/sensors [{"critical": 105, "key": "label", "label": "acpitz 0", @@ -737,9 +932,18 @@ Get plugin stats:: "value": 29, "warning": 105}] +Fields descriptions: + +* **label**: Sensor label (unit is *None*) +* **unit**: Sensor unit (unit is *None*) +* **value**: Sensor value (unit is *number*) +* **warning**: Warning threshold (unit is *number*) +* **critical**: Critical threshold (unit is *number*) +* **type**: Sensor type (one of battery, temperature_core, fan_speed) (unit is *None*) + Get a specific field:: - # curl http://localhost:61208/api/3/sensors/label + # curl http://localhost:61208/api/4/sensors/label {"label": ["acpitz 0", "acpitz 1", "Package id 0", @@ -752,7 +956,7 @@ Get a specific field:: Get a specific item when field matches the given value:: - # curl http://localhost:61208/api/3/sensors/label/acpitz 0 + # curl http://localhost:61208/api/4/sensors/label/acpitz 0 {"acpitz 0": [{"critical": 105, "key": "label", "label": "acpitz 0", @@ -766,17 +970,26 @@ GET system Get plugin stats:: - # curl http://localhost:61208/api/3/system + # curl http://localhost:61208/api/4/system {"hostname": "XPS13-9333", "hr_name": "Ubuntu 22.04 64bit", "linux_distro": "Ubuntu 22.04", "os_name": "Linux", - "os_version": "5.15.0-71-generic", + "os_version": "5.15.0-88-generic", "platform": "64bit"} +Fields descriptions: + +* **os_name**: Operating system name (unit is *None*) +* **hostname**: Hostname (unit is *None*) +* **platform**: Platform (32 or 64 bits) (unit is *None*) +* **linux_distro**: Linux distribution (unit is *None*) +* **os_version**: Operating system version (unit is *None*) +* **hr_name**: Human readable operating sytem name (unit is *None*) + Get a specific field:: - # curl http://localhost:61208/api/3/system/os_name + # curl http://localhost:61208/api/4/system/os_name {"os_name": "Linux"} GET uptime @@ -784,58 +997,169 @@ GET uptime Get plugin stats:: - # curl http://localhost:61208/api/3/uptime - "78 days, 3:00:11" + # curl http://localhost:61208/api/4/uptime + "70 days, 8:01:20" + +GET version +----------- + +Get plugin stats:: + + # curl http://localhost:61208/api/4/version + "4.0.0_beta01" GET all stats ------------- Get all Glances stats:: - # curl http://localhost:61208/api/3/all + # curl http://localhost:61208/api/4/all Return a very big dictionary (avoid using this request, performances will be poor)... +GET top n items of a specific plugin +------------------------------------ + +Get top 2 processes of the processlist plugin:: + + # curl http://localhost:61208/api/4/processlist/top/2 + [{"cmdline": ["/usr/share/code/code", + "--ms-enable-electron-run-as-node", + "/home/nicolargo/.vscode/extensions/ms-python.vscode-pylance-2023.12.1/dist/server.bundle.js", + "--cancellationReceive=file:ccbec6d233aa604f3844cb603c03b1e30b9e3ec684", + "--node-ipc", + "--clientProcessId=1559267"], + "cpu_percent": 0.0, + "cpu_times": {"children_system": 0.35, + "children_user": 2.54, + "iowait": 0.0, + "system": 138.29, + "user": 2149.01}, + "gids": {"effective": 1000, "real": 1000, "saved": 1000}, + "io_counters": [56303616, 675840, 0, 0, 0], + "key": "pid", + "memory_info": {"data": 701427712, + "dirty": 0, + "lib": 0, + "rss": 525553664, + "shared": 47415296, + "text": 120561664, + "vms": 1207768666112}, + "memory_percent": 6.717555253644529, + "name": "code", + "nice": 0, + "num_threads": 13, + "pid": 1560380, + "status": "S", + "time_since_update": 1, + "username": "nicolargo"}, + {"cmdline": ["/usr/share/code/code", + "--type=utility", + "--utility-sub-type=node.mojom.NodeService", + "--lang=en-US", + "--service-sandbox-type=none", + "--dns-result-order=ipv4first", + "--inspect-port=0", + "--crashpad-handler-pid=1559145", + "--enable-crash-reporter=721e05a9-6035-4dcb-bd58-68097aa48dd0,no_channel", + "--user-data-dir=/home/nicolargo/.config/Code", + "--standard-schemes=vscode-webview,vscode-file", + "--enable-sandbox", + "--secure-schemes=vscode-webview,vscode-file", + "--bypasscsp-schemes", + "--cors-schemes=vscode-webview,vscode-file", + "--fetch-schemes=vscode-webview,vscode-file", + "--service-worker-schemes=vscode-webview", + "--streaming-schemes", + "--shared-files=v8_context_snapshot_data:100", + "--field-trial-handle=0,i,8087816725710096048,13663223481033463053,262144", + "--disable-features=CalculateNativeWinOcclusion,SpareRendererForSitePerProcess"], + "cpu_percent": 0.0, + "cpu_times": {"children_system": 101.84, + "children_user": 111.74, + "iowait": 0.0, + "system": 139.35, + "user": 778.06}, + "gids": {"effective": 1000, "real": 1000, "saved": 1000}, + "io_counters": [141422592, 72794112, 0, 0, 0], + "key": "pid", + "memory_info": {"data": 759570432, + "dirty": 0, + "lib": 0, + "rss": 440238080, + "shared": 57569280, + "text": 120561664, + "vms": 1212085194752}, + "memory_percent": 5.627063095041765, + "name": "code", + "nice": 0, + "num_threads": 19, + "pid": 1559267, + "status": "S", + "time_since_update": 1, + "username": "nicolargo"}] + +Note: Only work for plugin with a list of items + +GET item description +-------------------- +Get item description (human readable) for a specific plugin/item:: + + # curl http://localhost:61208/api/4/diskio/read_bytes/description + "Number of bytes read." + +Note: the description is defined in the fields_description variable of the plugin. + +GET item unit +------------- +Get item unit for a specific plugin/item:: + + # curl http://localhost:61208/api/4/diskio/read_bytes/unit + "byte" + +Note: the description is defined in the fields_description variable of the plugin. + GET stats history ----------------- History of a plugin:: - # curl http://localhost:61208/api/3/cpu/history - {"system": [["2023-07-25T16:02:16.701846", 4.4], - ["2023-07-25T16:02:18.501052", 4.4], - ["2023-07-25T16:02:19.527073", 3.0]], - "user": [["2023-07-25T16:02:16.701836", 24.1], - ["2023-07-25T16:02:18.501045", 24.1], - ["2023-07-25T16:02:19.527068", 16.6]]} + # curl http://localhost:61208/api/4/cpu/history + {"system": [["2024-02-03T16:59:23.661692", 3.5], + ["2024-02-03T16:59:24.687718", 2.6], + ["2024-02-03T16:59:25.914949", 2.6]], + "user": [["2024-02-03T16:59:23.661678", 26.6], + ["2024-02-03T16:59:24.687708", 12.1], + ["2024-02-03T16:59:25.914934", 12.1]]} Limit history to last 2 values:: - # curl http://localhost:61208/api/3/cpu/history/2 - {"system": [["2023-07-25T16:02:18.501052", 4.4], - ["2023-07-25T16:02:19.527073", 3.0]], - "user": [["2023-07-25T16:02:18.501045", 24.1], - ["2023-07-25T16:02:19.527068", 16.6]]} + # curl http://localhost:61208/api/4/cpu/history/2 + {"system": [["2024-02-03T16:59:24.687718", 2.6], + ["2024-02-03T16:59:25.914949", 2.6]], + "user": [["2024-02-03T16:59:24.687708", 12.1], + ["2024-02-03T16:59:25.914934", 12.1]]} History for a specific field:: - # curl http://localhost:61208/api/3/cpu/system/history - {"system": [["2023-07-25T16:02:16.701846", 4.4], - ["2023-07-25T16:02:18.501052", 4.4], - ["2023-07-25T16:02:19.527073", 3.0]]} + # curl http://localhost:61208/api/4/cpu/system/history + {"system": [["2024-02-03T16:59:21.961184", 3.5], + ["2024-02-03T16:59:23.661692", 3.5], + ["2024-02-03T16:59:24.687718", 2.6], + ["2024-02-03T16:59:25.914949", 2.6]]} Limit history for a specific field to last 2 values:: - # curl http://localhost:61208/api/3/cpu/system/history - {"system": [["2023-07-25T16:02:18.501052", 4.4], - ["2023-07-25T16:02:19.527073", 3.0]]} + # curl http://localhost:61208/api/4/cpu/system/history + {"system": [["2024-02-03T16:59:24.687718", 2.6], + ["2024-02-03T16:59:25.914949", 2.6]]} GET limits (used for thresholds) -------------------------------- All limits/thresholds:: - # curl http://localhost:61208/api/3/all/limits - {"alert": {"history_size": 1200.0}, + # curl http://localhost:61208/api/4/all/limits + {"alert": {"alert_disable": ["False"], "history_size": 1200.0}, "amps": {"amps_disable": ["False"], "history_size": 1200.0}, "containers": {"containers_all": ["False"], "containers_disable": ["False"], @@ -865,11 +1189,13 @@ All limits/thresholds:: "cpu_user_log": ["False"], "cpu_user_warning": 70.0, "history_size": 1200.0}, - "diskio": {"diskio_disable": ["False"], + "diskio": {"diskio_alias": ["sda1:InternalDisk", "sdb1:ExternalDisk"], + "diskio_disable": ["False"], "diskio_hide": ["loop.*", "/dev/loop.*"], "history_size": 1200.0}, "folders": {"folders_disable": ["False"], "history_size": 1200.0}, - "fs": {"fs_careful": 50.0, + "fs": {"fs_alias": ["/:Root"], + "fs_careful": 50.0, "fs_critical": 90.0, "fs_disable": ["False"], "fs_hide": ["/boot.*", "/snap.*"], @@ -908,6 +1234,7 @@ All limits/thresholds:: "memswap_disable": ["False"], "memswap_warning": 70.0}, "network": {"history_size": 1200.0, + "network_alias": ["wlp2s0:WIFI"], "network_disable": ["False"], "network_rx_careful": 70.0, "network_rx_critical": 90.0, @@ -982,14 +1309,18 @@ All limits/thresholds:: "19"]}, "psutilversion": {"history_size": 1200.0}, "quicklook": {"history_size": 1200.0, + "quicklook_bar_char": ["|"], "quicklook_cpu_careful": 50.0, "quicklook_cpu_critical": 90.0, "quicklook_cpu_warning": 70.0, "quicklook_disable": ["False"], + "quicklook_list": ["cpu", "mem", "load"], + "quicklook_load_careful": 70.0, + "quicklook_load_critical": 500.0, + "quicklook_load_warning": 100.0, "quicklook_mem_careful": 50.0, "quicklook_mem_critical": 90.0, "quicklook_mem_warning": 70.0, - "quicklook_percentage_char": ["|"], "quicklook_swap_careful": 50.0, "quicklook_swap_critical": 90.0, "quicklook_swap_warning": 70.0}, @@ -1009,6 +1340,7 @@ All limits/thresholds:: "system_disable": ["False"], "system_refresh": 60}, "uptime": {"history_size": 1200.0}, + "version": {"history_size": 1200.0}, "wifi": {"history_size": 1200.0, "wifi_careful": -65.0, "wifi_critical": -85.0, @@ -1017,7 +1349,7 @@ All limits/thresholds:: Limits/thresholds for the cpu plugin:: - # curl http://localhost:61208/api/3/cpu/limits + # curl http://localhost:61208/api/4/cpu/limits {"cpu_ctx_switches_careful": 160000.0, "cpu_ctx_switches_critical": 200000.0, "cpu_ctx_switches_warning": 180000.0, diff --git a/docs/cmds.rst b/docs/cmds.rst index 7ab1ef49..c23670f5 100644 --- a/docs/cmds.rst +++ b/docs/cmds.rst @@ -12,7 +12,7 @@ Command-Line Options .. option:: -V, --version - show program's version number and exit + show the program's version number and exit .. option:: -d, --debug @@ -22,25 +22,29 @@ Command-Line Options path to the configuration file +.. option:: -P PLUGIN_DIRECTORY, --plugins PLUGIN_DIRECTORY + + path to a directory containing additional plugins + .. option:: --modules-list display modules (plugins & exports) list and exit .. option:: --disable-plugin PLUGIN - disable PLUGIN (comma separated list) + disable PLUGIN (comma-separated list) .. option:: --enable-plugin PLUGIN - enable PLUGIN (comma separated list) + enable PLUGIN (comma-separated list) .. option:: --stdout PLUGINS_STATS - display stats to stdout (comma separated list of plugins/plugins.attribute) + display stats to stdout (comma-separated list of plugins/plugins.attribute) .. option:: --export EXPORT - enable EXPORT module (comma separated list) + enable EXPORT module (comma-separated list) .. option:: --export-csv-file EXPORT_CSV_FILE @@ -60,7 +64,7 @@ Command-Line Options .. option:: --light, --enable-light - light mode for Curses UI (disable all but top menu) + light mode for Curses UI (disable all but the top menu) .. option:: -0, --disable-irix @@ -84,7 +88,7 @@ Command-Line Options .. option:: -5, --disable-top - disable top menu (QuickLook, CPU, MEM, SWAP and LOAD) + disable top menu (QuickLook, CPU, MEM, SWAP, and LOAD) .. option:: -6, --meangpu @@ -168,7 +172,7 @@ Command-Line Options .. option:: -w, --webserver - run Glances in web server mode (bottle lib needed) + run Glances in web server mode (FastAPI lib needed) .. option:: --cached-time CACHED_TIME @@ -192,11 +196,11 @@ Command-Line Options .. option:: --hide-kernel-threads - hide kernel threads in process list (not available on Windows) + hide kernel threads in the process list (not available on Windows) .. option:: -b, --byte - display network rate in byte per second + display network rate in bytes per second .. option:: --diskio-show-ramfs @@ -216,11 +220,11 @@ Command-Line Options .. option:: --theme-white - optimize display colors for white background + optimize display colors for a white background .. option:: --disable-check-update - disable online Glances version ckeck + disable online Glances version check Interactive Commands -------------------- @@ -232,7 +236,7 @@ The following commands (key pressed) are supported while in Glances: .. note:: On macOS please use ``CTRL-H`` to delete filter. - Filter is a regular expression pattern: + The filter is a regular expression pattern: - ``gnome``: matches all processes starting with the ``gnome`` string @@ -250,7 +254,7 @@ The following commands (key pressed) are supported while in Glances: - If CPU iowait ``>60%``, sort processes by I/O read and write ``A`` - Enable/disable Application Monitoring Process + Enable/disable the Application Monitoring Process ``b`` Switch between bit/s or Byte/s for network I/O @@ -274,7 +278,7 @@ The following commands (key pressed) are supported while in Glances: Enable/disable top extended stats ``E`` - Erase current process filter + Erase the current process filter ``f`` Show/hide file system and folder monitoring stats @@ -301,7 +305,7 @@ The following commands (key pressed) are supported while in Glances: Increase selected process nice level / Lower the priority (need right) - Only in standalone mode. ``-`` - Decrease selected process nice level / Higher the priority (need right) - Only in standalone mode. + Decrease selected process nice level / Higher the priority (need right) - Only in standalone mode. ``k`` Kill selected process (need right) - Only in standalone mode. @@ -352,7 +356,7 @@ The following commands (key pressed) are supported while in Glances: Sort process by CPU times (TIME+) ``T`` - View network I/O as combination + View network I/O as a combination ``u`` Sort processes by USER @@ -375,13 +379,13 @@ The following commands (key pressed) are supported while in Glances: ``0`` Enable/disable Irix/Solaris mode - Task's CPU usage will be divided by the total number of CPUs + The task's CPU usage will be divided by the total number of CPUs ``1`` Switch between global CPU and per-CPU stats ``2`` - Enable/disable left sidebar + Enable/disable the left sidebar ``3`` Enable/disable the quick look module @@ -390,7 +394,7 @@ The following commands (key pressed) are supported while in Glances: Enable/disable all but quick look and load module ``5`` - Enable/disable top menu (QuickLook, CPU, MEM, SWAP and LOAD) + Enable/disable the top menu (QuickLook, CPU, MEM, SWAP, and LOAD) ``6`` Enable/disable mean GPU mode @@ -405,10 +409,10 @@ The following commands (key pressed) are supported while in Glances: Refresh user interface ``LEFT`` - Navigation left through process sort + Navigation left through the process sort ``RIGHT`` - Navigation right through process sort + Navigation right through the process sort ``UP`` Up in the processes list diff --git a/docs/config.rst b/docs/config.rst index 38c0cd18..f99dcc77 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -5,7 +5,7 @@ Configuration No configuration file is mandatory to use Glances. -Furthermore a configuration file is needed to access more settings. +Furthermore, a configuration file is needed to access more settings. Location -------- @@ -14,25 +14,25 @@ Location A template is available in the ``/usr{,/local}/share/doc/glances`` (Unix-like) directory or directly on `GitHub`_. -You can put your own ``glances.conf`` file in the following locations: +You can place your ``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/ +``macOS`` ~/.config/glances/, ~/Library/Application Support/glances/, /usr/local/etc/glances/, /usr/share/docs/glances/ ``Windows`` %APPDATA%\\glances\\glances.conf ==================== ============================================================= - On Windows XP, ``%APPDATA%`` is: ``C:\Documents and Settings\\Application Data``. - On Windows Vista and later: ``C:\Users\\AppData\Roaming``. -User-specific options override system-wide options and options given on -the command line override either. +User-specific options override system-wide options, and options given on +the command line overrides both. Syntax ------ -Glances reads configuration files in the *ini* syntax. +Glances read configuration files in the *ini* syntax. A first section (called global) is available: @@ -40,17 +40,41 @@ A first section (called global) is available: [global] # Refresh rate (default is a minimum of 2 seconds) - # Can be overwrite by the -t option - # It is also possible to overwrite it in each plugin sections + # Can be overwritten by the -t option + # It is also possible to overwrite it in each plugin section refresh=2 - # Does Glances should check if a newer version is available on PyPI ? + # Should Glances check if a newer version is available on PyPI ? check_update=false # History size (maximum number of values) # Default is 28800: 1 day with 1 point every 3 seconds history_size=28800 + # Set the way Glances should display the date (default is %Y-%m-%d %H:%M:%S %Z) + #strftime_format="%Y-%m-%d %H:%M:%S %Z" + # Define external directory for loading additional plugins + # The layout follows the glances standard for plugin definitions + #plugin_dir=/home/user/dev/plugins -Each plugin, export module and application monitoring process (AMP) can -have a section. Below an example for the CPU plugin: +than a second one concerning the user interface: + +.. code-block:: ini + + [outputs] + # Theme name (for the moment only for the Curses interface: black or white) + curse_theme=black + # Separator in the Curses and WebUI interface (between top and others plugins) + separator=True + # Set the the Curses and WebUI interface left menu plugin list (comma-separated) + #left_menu=network,wifi,connections,ports,diskio,fs,irq,folders,raid,smart,sensors,now + # Limit the number of processes to display (for the WebUI) + max_processes_display=25 + # Set the URL prefix (for the WebUI and the API) + # Example: url_prefix=/glances/ => http://localhost/glances/ + # The final / is mandatory + # Default is no prefix (/) + #url_prefix=/glances/ + +Each plugin, export module, and application monitoring process (AMP) can +have a section. Below is an example for the CPU plugin: .. code-block:: ini @@ -90,16 +114,16 @@ or a Nginx AMP: .. code-block:: ini [amp_nginx] - # Nginx status page should be enable (https://easyengine.io/tutorials/nginx/status-page/) + # Nginx status page should be enabled (https://easyengine.io/tutorials/nginx/status-page/) enable=true regex=\/usr\/sbin\/nginx refresh=60 one_line=false status_url=http://localhost/nginx_status -With Glances 3.0 or higher it is also possible to use dynamic configuration -value using system command. For example, if you to set the prefix of an -InfluxDB export to the current hostname, use: +With Glances 3.0 or higher, you can use dynamic configuration values +by utilizing system commands. For example, if you want to set the prefix +of an InfluxDB export to the current hostname, use: .. code-block:: ini @@ -120,16 +144,17 @@ Logging Glances logs all of its internal messages to a log file. -``DEBUG`` messages can been logged using the ``-d`` option on the command +``DEBUG`` messages can be logged using the ``-d`` option on the command line. -The location of the Glances depends of your operating system. You could -displayed the Glances log file full path using the``glances -V`` command line. +The location of the Glances log file depends on your operating system. You can +display the full path of the Glances log file using the ``glances -V`` +command line. -The file is automatically rotate when the size is higher than 1 MB. +The file is automatically rotated when its size exceeds 1 MB. If you want to use another system path or change the log message, you -can use your own logger configuration. First of all, you have to create +can use your logger configuration. First of all, you have to create a ``glances.json`` file with, for example, the following content (JSON format): @@ -201,7 +226,7 @@ and start Glances using the following command line: LOG_CFG=/glances.json glances .. note:: - Replace ```` by the folder where your ``glances.json`` file + Replace ```` with the directory where your ``glances.json`` file is hosted. .. _GitHub: https://raw.githubusercontent.com/nicolargo/glances/master/conf/glances.conf diff --git a/docs/docker.rst b/docs/docker.rst index 9983dc45..76620807 100644 --- a/docs/docker.rst +++ b/docs/docker.rst @@ -3,7 +3,9 @@ Docker ====== -Glances can be installed through Docker, allowing you to run it without installing all the python dependencies directly on your system. Once you have `docker installed `_, you can +Glances can be installed through Docker, allowing you to run it without +installing all the Python dependencies directly on your system. Once you +have `docker installed `_, you can Get the Glances container: @@ -11,7 +13,7 @@ Get the Glances container: docker pull nicolargo/glances: -Available tags (all images are based on both Alpine and Ubuntu Operating System): +Available tags (all images are based on both Alpine and Ubuntu Operating Systems): .. list-table:: :widths: 25 15 25 35 @@ -28,7 +30,7 @@ Available tags (all images are based on both Alpine and Ubuntu Operating System) * - `latest` - Alpine - Latest Release - - Minimal + (Bottle & Docker) + - Minimal + (FastAPI & Docker) * - `dev` - Alpine - develop @@ -40,20 +42,20 @@ Available tags (all images are based on both Alpine and Ubuntu Operating System) * - `ubuntu-latest` - Ubuntu - Latest Release - - Minimal + (Bottle & Docker) + - Minimal + (FastAPI & Docker) * - `ubuntu-dev` - Ubuntu - develop - Full .. warning:: - Tags containing `dev` target the `develop` branch directly and could be unstable. + Tags containing `dev` directly target the `develop` branch and could be unstable. For example, if you want a full Alpine Glances image (latest release) with all dependencies, go for `latest-full`. You can also specify a version (example: 3.4.0). All available versions can be found on `DockerHub`_. -An Example to pull the `latest` tag: +An example of how to pull the `latest` tag: .. code-block:: console @@ -81,7 +83,7 @@ Alternatively, you can specify something along the same lines with docker run op Where \`pwd\`/glances.conf is a local directory containing your glances.conf file. -Glances by default, uses the container's OS information in the UI. If you want to display the host's OS info, you can do that by mounting `/etc/os-release` into the container. +Glances by default uses the container's OS information in the UI. If you want to display the host's OS info, you can do that by mounting `/etc/os-release` into the container. Here is a simple docker run example for that: @@ -97,7 +99,7 @@ Run the container in *Web server mode* (notice the `GLANCES_OPT` environment var Note: if you want to see the network interface stats within the container, add --net=host --privileged -You can also include Glances container in you own `docker-compose.yml`. Here's a realistic example including a "traefik" reverse proxy serving an "whoami" app container plus a Glances container, providing a simple and efficient monitoring webui. +You can also include Glances container in you own `docker-compose.yml`. A realistic example includes a "traefik" reverse proxy serving an "whoami" app container plus a Glances container, providing a simple and efficient monitoring webui. .. code-block:: console @@ -119,7 +121,7 @@ You can also include Glances container in you own `docker-compose.yml`. Here's a - "traefik.frontend.rule=Host:whoami.docker.localhost" monitoring: - image: nicolargo/glances:latest-alpine + image: nicolargo/glances:latest restart: always pid: host volumes: diff --git a/docs/glances.rst b/docs/glances.rst index 0d1bde4e..3f3a8a5b 100644 --- a/docs/glances.rst +++ b/docs/glances.rst @@ -11,12 +11,12 @@ SYNOPSIS DESCRIPTION ----------- -**glances** is a cross-platform curses-based monitoring tool which aims -to present a maximum of information in a minimum of space, ideally to -fit in a classical 80x24 terminal or higher to have additional -information. It can adapt dynamically the displayed information -depending on the terminal size. It can also work in client/server mode. -Remote monitoring could be done via terminal or web interface. +**glances** is a cross-platform curses-based monitoring tool that aims +to present a maximum of information in a minimum of space, ideally fitting +in a classic 80x24 terminal or larger for more details. It can adapt +dynamically to the displayed information depending on the terminal size. +It can also work in client/server mode. +Remote monitoring can be performed via a terminal or web interface. **glances** is written in Python and uses the *psutil* library to get information from your system. @@ -38,19 +38,20 @@ Monitor local machine (standalone mode): $ glances -Monitor local machine with the web interface (Web UI), run the following command line: +To monitor the local machine with the web interface (Web UI), +, run the following command line: $ glances -w -and open a Web browser with the returned URL +then, open a web browser to the provided URL. Monitor local machine and export stats to a CSV file: $ glances --export csv --export-csv-file /tmp/glances.csv -Monitor local machine and export stats to a InfluxDB server with 5s +Monitor local machine and export stats to an InfluxDB server with 5s refresh time (also possible to export to OpenTSDB, Cassandra, Statsd, -ElasticSearch, RabbitMQ and Riemann): +ElasticSearch, RabbitMQ, and Riemann): $ glances -t 5 --export influxdb diff --git a/docs/gw/couchdb.rst b/docs/gw/couchdb.rst index 3e4d92bd..5916ba8f 100644 --- a/docs/gw/couchdb.rst +++ b/docs/gw/couchdb.rst @@ -9,9 +9,9 @@ following: .. code-block:: ini - [mongodb] + [couchdb] host=localhost - port=27017 + port=5984 db=glances user=root password=example @@ -20,24 +20,31 @@ and run Glances with: .. code-block:: console - $ glances --export mongodb + $ glances --export couchdb -Documents are stored in native the configured database (glances by default) -with one collection per plugin. +Documents are stored in native ``JSON`` format. Glances adds ``"type"`` +and ``"time"`` entries: -Example of MongoDB Document for the load stats: +- ``type``: plugin name +- ``time``: timestamp (format: "2016-09-24T16:39:08.524Z") + +Example of Couch Document for the load stats: .. code-block:: json { - _id: ObjectId('63d78ffee5528e543ce5af3a'), - min1: 1.46337890625, - min5: 1.09619140625, - min15: 1.07275390625, - cpucore: 4, - history_size: 1200, - load_disable: 'False', - load_careful: 0.7, - load_warning: 1, - load_critical: 5 + "_id": "36cbbad81453c53ef08804cb2612d5b6", + "_rev": "1-382400899bec5615cabb99aa34df49fb", + "min15": 0.33, + "time": "2016-09-24T16:39:08.524Z", + "min5": 0.4, + "cpucore": 4, + "load_warning": 1, + "min1": 0.5, + "history_size": 28800, + "load_critical": 5, + "type": "load", + "load_careful": 0.7 } + +You can view the result using the CouchDB utils URL: http://127.0.0.1:5984/_utils/database.html?glances. diff --git a/docs/gw/mongodb.rst b/docs/gw/mongodb.rst index 4ef71692..431c2dd9 100644 --- a/docs/gw/mongodb.rst +++ b/docs/gw/mongodb.rst @@ -9,42 +9,35 @@ following: .. code-block:: ini - [couchdb] + [mongodb] host=localhost - port= + port=27017 + db=glances user=root password=example - db=glances and run Glances with: .. code-block:: console - $ glances --export couchdb + $ glances --export mongodb -Documents are stored in native ``JSON`` format. Glances adds ``"type"`` -and ``"time"`` entries: +Documents are stored in native the configured database (glances by default) +with one collection per plugin. -- ``type``: plugin name -- ``time``: timestamp (format: "2016-09-24T16:39:08.524828Z") - -Example of Couch Document for the load stats: +Example of MongoDB Document for the load stats: .. code-block:: json { - "_id": "36cbbad81453c53ef08804cb2612d5b6", - "_rev": "1-382400899bec5615cabb99aa34df49fb", - "min15": 0.33, - "time": "2016-09-24T16:39:08.524828Z", - "min5": 0.4, - "cpucore": 4, - "load_warning": 1, - "min1": 0.5, - "history_size": 28800, - "load_critical": 5, - "type": "load", - "load_careful": 0.7 + _id: ObjectId('63d78ffee5528e543ce5af3a'), + min1: 1.46337890625, + min5: 1.09619140625, + min15: 1.07275390625, + cpucore: 4, + history_size: 1200, + load_disable: 'False', + load_careful: 0.7, + load_warning: 1, + load_critical: 5 } - -You can view the result using the CouchDB utils URL: http://127.0.0.1:5984/_utils/database.html?glances. diff --git a/docs/gw/prometheus.rst b/docs/gw/prometheus.rst index 52b953d5..d33d8d73 100644 --- a/docs/gw/prometheus.rst +++ b/docs/gw/prometheus.rst @@ -4,8 +4,8 @@ Prometheus ========== You can export statistics to a ``Prometheus`` server through an exporter. -When the *--export-prometheus* is used, Glances creates a Prometheus exporter -listening on (define in the Glances configuration file). +When the *--export prometheus* is used, Glances creates a Prometheus exporter +listening on (defined in the Glances configuration file). .. code-block:: ini diff --git a/docs/index.rst b/docs/index.rst index f0fcfeb8..61e92a65 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,13 +3,13 @@ Glances .. image:: _static/screenshot-wide.png -Glances is a cross-platform monitoring tool which aims to present a -maximum of information in a minimum of space through a curses or Web -based interface. It can adapt dynamically the displayed information -depending on the terminal size. +Glances is a cross-platform monitoring tool that aims to present +maximum information in minimal space through either a curses-based +or Web-based interface. It can dynamically adapt the displayed +information depending on the terminal size. -It can also work in client/server mode. Remote monitoring could be -done via terminal, Web interface or API (XMLRPC and RESTful). +It can also work in client/server mode. Remote monitoring can be +done via terminal, Web interface, or API (XMLRPC and RESTful). Glances is written in Python and uses the `psutil`_ library to get information from your system. diff --git a/docs/install.rst b/docs/install.rst index 5306db31..a56d69e2 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -3,8 +3,8 @@ Install ======= -Glances is on ``PyPI``. By using PyPI, you are sure to have the latest -stable version. +Glances is available on ``PyPI``. By using PyPI, you are sure to have the +latest stable version. To install, simply use ``pip``: @@ -12,13 +12,13 @@ To install, simply use ``pip``: pip install glances -*Note*: Python headers are required to install `psutil`_. For example, -on Debian/Ubuntu you need to install first the *python-dev* package. -For Fedora/CentOS/RHEL install first *python-devel* package. For Windows, -just install psutil from the binary installation file. +*Note*: Python headers are required to install `psutil`_. For instance, +on Debian/Ubuntu, you must first install the *python-dev* package. +On Fedora/CentOS/RHEL, first, install the *python-devel* package. For Windows, +psutil can be installed from the binary installation file. -You can also install the following libraries in order to use optional -features (like the Web interface, export modules...): +You can also install the following libraries to use the optional +features (such as the web interface, export modules, etc.): .. code-block:: console diff --git a/docs/man/glances.1 b/docs/man/glances.1 index 6e90746c..77ca1e52 100644 --- a/docs/man/glances.1 +++ b/docs/man/glances.1 @@ -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" "Jul 25, 2023" "4.0.0_beta01" "Glances" +.TH "GLANCES" "1" "Feb 03, 2024" "4.0.0_beta01" "Glances" .SH NAME glances \- An eye on your system .SH SYNOPSIS @@ -35,12 +35,12 @@ glances \- An eye on your system \fBglances\fP [OPTIONS] .SH DESCRIPTION .sp -\fBglances\fP is a cross\-platform curses\-based monitoring tool which aims -to present a maximum of information in a minimum of space, ideally to -fit in a classical 80x24 terminal or higher to have additional -information. It can adapt dynamically the displayed information -depending on the terminal size. It can also work in client/server mode. -Remote monitoring could be done via terminal or web interface. +\fBglances\fP is a cross\-platform curses\-based monitoring tool that aims +to present a maximum of information in a minimum of space, ideally fitting +in a classic 80x24 terminal or larger for more details. It can adapt +dynamically to the displayed information depending on the terminal size. +It can also work in client/server mode. +Remote monitoring can be performed via a terminal or web interface. .sp \fBglances\fP is written in Python and uses the \fIpsutil\fP library to get information from your system. @@ -54,7 +54,7 @@ show this help message and exit .INDENT 0.0 .TP .B \-V, \-\-version -show program’s version number and exit +show the program’s version number and exit .UNINDENT .INDENT 0.0 .TP @@ -68,28 +68,33 @@ path to the configuration file .UNINDENT .INDENT 0.0 .TP +.B \-P PLUGIN_DIRECTORY, \-\-plugins PLUGIN_DIRECTORY +path to a directory containing additional plugins +.UNINDENT +.INDENT 0.0 +.TP .B \-\-modules\-list display modules (plugins & exports) list and exit .UNINDENT .INDENT 0.0 .TP .B \-\-disable\-plugin PLUGIN -disable PLUGIN (comma separated list) +disable PLUGIN (comma\-separated list) .UNINDENT .INDENT 0.0 .TP .B \-\-enable\-plugin PLUGIN -enable PLUGIN (comma separated list) +enable PLUGIN (comma\-separated list) .UNINDENT .INDENT 0.0 .TP .B \-\-stdout PLUGINS_STATS -display stats to stdout (comma separated list of plugins/plugins.attribute) +display stats to stdout (comma\-separated list of plugins/plugins.attribute) .UNINDENT .INDENT 0.0 .TP .B \-\-export EXPORT -enable EXPORT module (comma separated list) +enable EXPORT module (comma\-separated list) .UNINDENT .INDENT 0.0 .TP @@ -114,7 +119,7 @@ disable the Web UI (only the RESTful API will respond) .INDENT 0.0 .TP .B \-\-light, \-\-enable\-light -light mode for Curses UI (disable all but top menu) +light mode for Curses UI (disable all but the top menu) .UNINDENT .INDENT 0.0 .TP @@ -144,7 +149,7 @@ disable all but quick look and load .INDENT 0.0 .TP .B \-5, \-\-disable\-top -disable top menu (QuickLook, CPU, MEM, SWAP and LOAD) +disable top menu (QuickLook, CPU, MEM, SWAP, and LOAD) .UNINDENT .INDENT 0.0 .TP @@ -249,7 +254,7 @@ set refresh time in seconds [default: 3 sec] .INDENT 0.0 .TP .B \-w, \-\-webserver -run Glances in web server mode (bottle lib needed) +run Glances in web server mode (FastAPI lib needed) .UNINDENT .INDENT 0.0 .TP @@ -279,12 +284,12 @@ force short name for processes name .INDENT 0.0 .TP .B \-\-hide\-kernel\-threads -hide kernel threads in process list (not available on Windows) +hide kernel threads in the process list (not available on Windows) .UNINDENT .INDENT 0.0 .TP .B \-b, \-\-byte -display network rate in byte per second +display network rate in bytes per second .UNINDENT .INDENT 0.0 .TP @@ -309,12 +314,12 @@ display FS free space instead of used .INDENT 0.0 .TP .B \-\-theme\-white -optimize display colors for white background +optimize display colors for a white background .UNINDENT .INDENT 0.0 .TP .B \-\-disable\-check\-update -disable online Glances version ckeck +disable online Glances version check .UNINDENT .SH INTERACTIVE COMMANDS .sp @@ -331,7 +336,7 @@ On macOS please use \fBCTRL\-H\fP to delete filter. .UNINDENT .UNINDENT .sp -Filter is a regular expression pattern: +The filter is a regular expression pattern: .INDENT 7.0 .IP \(bu 2 \fBgnome\fP: matches all processes starting with the \fBgnome\fP @@ -353,7 +358,7 @@ If CPU iowait \fB>60%\fP, sort processes by I/O read and write .UNINDENT .TP .B \fBA\fP -Enable/disable Application Monitoring Process +Enable/disable the Application Monitoring Process .TP .B \fBb\fP Switch between bit/s or Byte/s for network I/O @@ -377,7 +382,7 @@ Enable/disable Docker stats Enable/disable top extended stats .TP .B \fBE\fP -Erase current process filter +Erase the current process filter .TP .B \fBf\fP Show/hide file system and folder monitoring stats @@ -404,7 +409,7 @@ Show/hide IP module Increase selected process nice level / Lower the priority (need right) \- Only in standalone mode. .TP .B \fB\-\fP -Decrease selected process nice level / Higher the priority (need right) \- Only in standalone mode. +Decrease selected process nice level / Higher the priority (need right) \- Only in standalone mode. .TP .B \fBk\fP Kill selected process (need right) \- Only in standalone mode. @@ -455,7 +460,7 @@ Enable/disable spark lines Sort process by CPU times (TIME+) .TP .B \fBT\fP -View network I/O as combination +View network I/O as a combination .TP .B \fBu\fP Sort processes by USER @@ -478,13 +483,13 @@ Show/hide processes stats .B \fB0\fP Enable/disable Irix/Solaris mode .sp -Task’s CPU usage will be divided by the total number of CPUs +The task’s CPU usage will be divided by the total number of CPUs .TP .B \fB1\fP Switch between global CPU and per\-CPU stats .TP .B \fB2\fP -Enable/disable left sidebar +Enable/disable the left sidebar .TP .B \fB3\fP Enable/disable the quick look module @@ -493,7 +498,7 @@ Enable/disable the quick look module Enable/disable all but quick look and load module .TP .B \fB5\fP -Enable/disable top menu (QuickLook, CPU, MEM, SWAP and LOAD) +Enable/disable the top menu (QuickLook, CPU, MEM, SWAP, and LOAD) .TP .B \fB6\fP Enable/disable mean GPU mode @@ -508,10 +513,10 @@ Switch between process command line or command name Refresh user interface .TP .B \fBLEFT\fP -Navigation left through process sort +Navigation left through the process sort .TP .B \fBRIGHT\fP -Navigation right through process sort +Navigation right through the process sort .TP .B \fBUP\fP Up in the processes list @@ -540,7 +545,7 @@ Quit Glances .sp No configuration file is mandatory to use Glances. .sp -Furthermore a configuration file is needed to access more settings. +Furthermore, a configuration file is needed to access more settings. .SH LOCATION .sp \fBNOTE:\fP @@ -551,7 +556,7 @@ A template is available in the \fB/usr{,/local}/share/doc/glances\fP .UNINDENT .UNINDENT .sp -You can put your own \fBglances.conf\fP file in the following locations: +You can place your \fBglances.conf\fP file in the following locations: .TS center; |l|l|. @@ -571,7 +576,7 @@ _ T{ \fBmacOS\fP T} T{ -~/Library/Application Support/glances/, /usr/local/etc/glances/, /usr/share/docs/glances/ +~/.config/glances/, ~/Library/Application Support/glances/, /usr/local/etc/glances/, /usr/share/docs/glances/ T} _ T{ @@ -588,11 +593,11 @@ On Windows XP, \fB%APPDATA%\fP is: \fBC:\eDocuments and Settings\e\eAp On Windows Vista and later: \fBC:\eUsers\e\eAppData\eRoaming\fP\&. .UNINDENT .sp -User\-specific options override system\-wide options and options given on -the command line override either. +User\-specific options override system\-wide options, and options given on +the command line overrides both. .SH SYNTAX .sp -Glances reads configuration files in the \fIini\fP syntax. +Glances read configuration files in the \fIini\fP syntax. .sp A first section (called global) is available: .INDENT 0.0 @@ -602,21 +607,51 @@ A first section (called global) is available: .ft C [global] # Refresh rate (default is a minimum of 2 seconds) -# Can be overwrite by the \-t option -# It is also possible to overwrite it in each plugin sections +# Can be overwritten by the \-t option +# It is also possible to overwrite it in each plugin section refresh=2 -# Does Glances should check if a newer version is available on PyPI ? +# Should Glances check if a newer version is available on PyPI ? check_update=false # History size (maximum number of values) # Default is 28800: 1 day with 1 point every 3 seconds history_size=28800 +# Set the way Glances should display the date (default is %Y\-%m\-%d %H:%M:%S %Z) +#strftime_format=\(dq%Y\-%m\-%d %H:%M:%S %Z\(dq +# Define external directory for loading additional plugins +# The layout follows the glances standard for plugin definitions +#plugin_dir=/home/user/dev/plugins .ft P .fi .UNINDENT .UNINDENT .sp -Each plugin, export module and application monitoring process (AMP) can -have a section. Below an example for the CPU plugin: +than a second one concerning the user interface: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +[outputs] +# Theme name (for the moment only for the Curses interface: black or white) +curse_theme=black +# Separator in the Curses and WebUI interface (between top and others plugins) +separator=True +# Set the the Curses and WebUI interface left menu plugin list (comma\-separated) +#left_menu=network,wifi,connections,ports,diskio,fs,irq,folders,raid,smart,sensors,now +# Limit the number of processes to display (for the WebUI) +max_processes_display=25 +# Set the URL prefix (for the WebUI and the API) +# Example: url_prefix=/glances/ => http://localhost/glances/ +# The final / is mandatory +# Default is no prefix (/) +#url_prefix=/glances/ +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Each plugin, export module, and application monitoring process (AMP) can +have a section. Below is an example for the CPU plugin: .INDENT 0.0 .INDENT 3.5 .sp @@ -670,7 +705,7 @@ or a Nginx AMP: .nf .ft C [amp_nginx] -# Nginx status page should be enable (https://easyengine.io/tutorials/nginx/status\-page/) +# Nginx status page should be enabled (https://easyengine.io/tutorials/nginx/status\-page/) enable=true regex=\e/usr\e/sbin\e/nginx refresh=60 @@ -681,9 +716,9 @@ status_url=http://localhost/nginx_status .UNINDENT .UNINDENT .sp -With Glances 3.0 or higher it is also possible to use dynamic configuration -value using system command. For example, if you to set the prefix of an -InfluxDB export to the current hostname, use: +With Glances 3.0 or higher, you can use dynamic configuration values +by utilizing system commands. For example, if you want to set the prefix +of an InfluxDB export to the current hostname, use: .INDENT 0.0 .INDENT 3.5 .sp @@ -714,16 +749,17 @@ tags=system:\(gauname \-a\(ga .sp Glances logs all of its internal messages to a log file. .sp -\fBDEBUG\fP messages can been logged using the \fB\-d\fP option on the command +\fBDEBUG\fP messages can be logged using the \fB\-d\fP option on the command line. .sp -The location of the Glances depends of your operating system. You could -displayed the Glances log file full path using the\(ga\(gaglances \-V\(ga\(ga command line. +The location of the Glances log file depends on your operating system. You can +display the full path of the Glances log file using the \fBglances \-V\fP +command line. .sp -The file is automatically rotate when the size is higher than 1 MB. +The file is automatically rotated when its size exceeds 1 MB. .sp If you want to use another system path or change the log message, you -can use your own logger configuration. First of all, you have to create +can use your logger configuration. First of all, you have to create a \fBglances.json\fP file with, for example, the following content (JSON format): .INDENT 0.0 @@ -809,7 +845,7 @@ LOG_CFG=/glances.json glances \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 -Replace \fB\fP by the folder where your \fBglances.json\fP file +Replace \fB\fP with the directory where your \fBglances.json\fP file is hosted. .UNINDENT .UNINDENT @@ -822,14 +858,15 @@ $ glances .UNINDENT .UNINDENT .sp -Monitor local machine with the web interface (Web UI), run the following command line: +To monitor the local machine with the web interface (Web UI), +, run the following command line: .INDENT 0.0 .INDENT 3.5 $ glances \-w .UNINDENT .UNINDENT .sp -and open a Web browser with the returned URL +then, open a web browser to the provided URL. .sp Monitor local machine and export stats to a CSV file: .INDENT 0.0 @@ -838,9 +875,9 @@ $ glances –export csv –export\-csv\-file /tmp/glances.csv .UNINDENT .UNINDENT .sp -Monitor local machine and export stats to a InfluxDB server with 5s +Monitor local machine and export stats to an InfluxDB server with 5s refresh time (also possible to export to OpenTSDB, Cassandra, Statsd, -ElasticSearch, RabbitMQ and Riemann): +ElasticSearch, RabbitMQ, and Riemann): .INDENT 0.0 .INDENT 3.5 $ glances \-t 5 –export influxdb @@ -885,6 +922,6 @@ $ glances –browser .sp Nicolas Hennion aka Nicolargo <\fI\%contact@nicolargo.com\fP> .SH COPYRIGHT -2023, Nicolas Hennion +2024, Nicolas Hennion .\" Generated by docutils manpage writer. . diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 1d4ec024..70b047a9 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -3,8 +3,8 @@ Quickstart ========== -This page gives a good introduction in how to get started with Glances. -Glances offers 3 modes: +This page gives a good introduction to how to get started with Glances. +Glances offers three modes: - Standalone - Client/Server @@ -61,7 +61,7 @@ Note: It will display one line per stat per refresh. Client/Server Mode ------------------ -If you want to remotely monitor a machine, called ``server``, from +If you want to remotely monitor a machine called ``server``, from another one, called ``client``, just run on the server: .. code-block:: console @@ -118,7 +118,7 @@ To start the central client, use the following option: .. note:: - Use ``--disable-autodiscover`` to disable the auto discovery mode. + Use ``--disable-autodiscover`` to disable the auto-discovery mode. 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: @@ -137,7 +137,7 @@ client, the latter will try to grab stats using the ``SNMP`` protocol: client$ glances -c @snmpserver .. note:: - Stats grabbed by SNMP request are limited and OS dependent. + Stats grabbed by SNMP request are limited and OS-dependent. A SNMP server should be installed and configured... @@ -152,14 +152,14 @@ Web Server Mode .. image:: _static/screenshot-web.png -If you want to remotely monitor a machine, called ``server``, from any +If you want to remotely monitor a machine called ``server``, from any device with a web browser, just run the server with the ``-w`` option: .. code-block:: console server$ glances -w -then on the client enter the following URL in your favorite web browser: +then, on the client, enter the following URL in your favorite web browser: :: @@ -167,7 +167,7 @@ then on the client enter the following URL in your favorite web browser: where ``@server`` is the IP address or hostname of the server. -To change the refresh rate of the page, just add the period in seconds +To change the refresh rate of the page, add the period in seconds at the end of the URL. For example, to refresh the page every ``10`` seconds: @@ -181,10 +181,10 @@ Here's a screenshot from Chrome on Android: .. image:: _static/screenshot-web2.png -How to protect your server (or Web server) with a login/password ? +How do you protect your server (or Web server) with a login/password ? ------------------------------------------------------------------ -You can set a password to access to the server using the ``--password``. +You can set a password to access the server using the ``--password``. By default, the login is ``glances`` but you can change it with ``--username``. @@ -192,8 +192,8 @@ If you want, the SHA password will be stored in ``.pwd`` file (in the same folder where the Glances configuration file is stored, so ~/.config/glances/ on GNU Linux operating system). -Next time your run the server/client, password will not be asked. To set a -specific username you can use the -u option. +Next time you run the server/client, password will not be asked. To set a +specific username, you can use the -u option. It is also possible to set the default password in the Glances configuration file: diff --git a/docs/support.rst b/docs/support.rst index 086951a0..4de5e4bb 100644 --- a/docs/support.rst +++ b/docs/support.rst @@ -7,7 +7,7 @@ To post a question about Glances use cases, please post it to the official Q&A `forum `_. -To report a bug or a feature request use the GitHub `issue +To report a bug or a feature request, use the GitHub `issue `_ tracker. Feel free to contribute! diff --git a/glances/README.txt b/glances/README.txt index c5fd13eb..3e6de7eb 100644 --- a/glances/README.txt +++ b/glances/README.txt @@ -12,7 +12,7 @@ globals.py Share variables upon modules main.py Main script to rule them up... client.py Glances client server.py Glances server -webserver.py Glances web server (Bottle-based) +webserver.py Glances web server (Based on FastAPI) autodiscover.py Glances autodiscover module (via zeroconf) standalone.py Glances standalone (curses interface) password.py Manage password for Glances client/server @@ -27,7 +27,7 @@ plugins outputs => Glances UI glances_curses.py The curses interface - glances_bottle.py The web interface + glances_restful-api.py The HTTP/API & Web based interface ... exports => Glances exports diff --git a/glances/__init__.py b/glances/__init__.py index 652f8f84..23bbd18c 100644 --- a/glances/__init__.py +++ b/glances/__init__.py @@ -20,7 +20,8 @@ import sys # Global name # Version should start and end with a numerical char # See https://packaging.python.org/specifications/core-metadata/#version -__version__ = '4.0.0b01' +__version__ = '4.0.0_beta01' +__apiversion__ = '4' __author__ = 'Nicolas Hennion ' __license__ = 'LGPLv3' @@ -108,7 +109,7 @@ def start(config, args): # Start the main loop logger.debug("Glances started in {} seconds".format(start_duration.get())) if args.stop_after: - logger.info('Glances will be stopped in ~{} seconds'.format(args.stop_after * args.time * args.memory_leak * 2)) + logger.info('Glances will be stopped in ~{} seconds'.format(args.stop_after * args.time)) if args.memory_leak: print( diff --git a/glances/amps/glances_amp.py b/glances/amps/amp.py similarity index 98% rename from glances/amps/glances_amp.py rename to glances/amps/amp.py index 078e08a9..41881ea8 100644 --- a/glances/amps/glances_amp.py +++ b/glances/amps/amp.py @@ -42,7 +42,7 @@ class GlancesAmp(object): # AMP name (= module name without glances_) if name is None: - self.amp_name = self.__class__.__module__[len('glances_') :] + self.amp_name = self.__class__.__module__ else: self.amp_name = name diff --git a/glances/amps/glances_default.py b/glances/amps/default/__init__.py similarity index 97% rename from glances/amps/glances_default.py rename to glances/amps/default/__init__.py index dac41b38..886f0c8a 100644 --- a/glances/amps/glances_default.py +++ b/glances/amps/default/__init__.py @@ -29,7 +29,7 @@ from subprocess import check_output, STDOUT, CalledProcessError from glances.globals import u, to_ascii from glances.logger import logger -from glances.amps.glances_amp import GlancesAmp +from glances.amps.amp import GlancesAmp class Amp(GlancesAmp): diff --git a/glances/amps/glances_nginx.py b/glances/amps/nginx/__init__.py similarity index 98% rename from glances/amps/glances_nginx.py rename to glances/amps/nginx/__init__.py index 04ff5236..770c4aca 100644 --- a/glances/amps/glances_nginx.py +++ b/glances/amps/nginx/__init__.py @@ -47,7 +47,7 @@ status_url=http://localhost/nginx_status import requests from glances.logger import logger -from glances.amps.glances_amp import GlancesAmp +from glances.amps.amp import GlancesAmp class Amp(GlancesAmp): diff --git a/glances/amps/glances_systemd.py b/glances/amps/systemd/__init__.py similarity index 98% rename from glances/amps/glances_systemd.py rename to glances/amps/systemd/__init__.py index 736666a5..3df7a8ae 100644 --- a/glances/amps/glances_systemd.py +++ b/glances/amps/systemd/__init__.py @@ -39,7 +39,7 @@ from subprocess import check_output, CalledProcessError from glances.logger import logger from glances.globals import iteritems, to_ascii -from glances.amps.glances_amp import GlancesAmp +from glances.amps.amp import GlancesAmp class Amp(GlancesAmp): diff --git a/glances/amps/glances_systemv.py b/glances/amps/systemv/__init__.py similarity index 98% rename from glances/amps/glances_systemv.py rename to glances/amps/systemv/__init__.py index afd8abe0..78df6795 100644 --- a/glances/amps/glances_systemv.py +++ b/glances/amps/systemv/__init__.py @@ -38,7 +38,7 @@ from subprocess import check_output, STDOUT from glances.logger import logger from glances.globals import iteritems -from glances.amps.glances_amp import GlancesAmp +from glances.amps.amp import GlancesAmp class Amp(GlancesAmp): diff --git a/glances/amps_list.py b/glances/amps_list.py index c3c63627..41f82c37 100644 --- a/glances/amps_list.py +++ b/glances/amps_list.py @@ -45,41 +45,30 @@ class AmpsList(object): if self.config is None: return False - # Display a warning (deprecated) message if the monitor section exist - if "monitor" in self.config.sections(): - logger.warning( - "A deprecated [monitor] section exists in the Glances configuration file. You should use the new \ - Applications Monitoring Process module instead \ - (http://glances.readthedocs.io/en/develop/aoa/amps.html)." - ) - - # 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 script, call the load_config method for s in self.config.sections(): if s.startswith("amp_"): # An AMP section exists in the configuration file - # If an AMP script exist in the glances/amps folder, use it - amp_conf_name = s[4:] - amp_script = os.path.join(amps_path, header + s[4:] + ".py") - if not os.path.exists(amp_script): + # If an AMP module exist in amps_path (glances/amps) folder then use it + amp_name = s[4:] + amp_module = os.path.join(amps_path, amp_name) + if not os.path.exists(amp_module): # If not, use the default script - amp_script = os.path.join(amps_path, "glances_default.py") + amp_module = os.path.join(amps_path, "default") try: - amp = __import__(os.path.basename(amp_script)[:-3]) + amp = __import__(os.path.basename(amp_module)) except ImportError as e: - logger.warning("Missing Python Lib ({}), cannot load {} AMP".format(e, amp_conf_name)) + logger.warning("Missing Python Lib ({}), cannot load AMP {}".format(e, amp_name)) except Exception as e: - logger.warning("Cannot load {} AMP ({})".format(amp_conf_name, e)) + logger.warning("Cannot load AMP {} ({})".format(amp_name, e)) else: # Add the AMP to the dictionary # The key is the AMP name # for example, the file glances_xxx.py # generate self._amps_list["xxx"] = ... - self.__amps_dict[amp_conf_name] = amp.Amp(name=amp_conf_name, args=self.args) + self.__amps_dict[amp_name] = amp.Amp(name=amp_name, args=self.args) # Load the AMP configuration - self.__amps_dict[amp_conf_name].load_config(self.config) + self.__amps_dict[amp_name].load_config(self.config) # Log AMPs list logger.debug("AMPs list: {}".format(self.getList())) diff --git a/glances/config.py b/glances/config.py index 7138e48c..ece17c9b 100644 --- a/glances/config.py +++ b/glances/config.py @@ -20,28 +20,26 @@ from glances.logger import logger def user_config_dir(): - r"""Return the per-user config dir (full path). + r"""Return a list of per-user config dir (full path). - Linux, *BSD, SunOS: ~/.config/glances - macOS: ~/Library/Application Support/glances - Windows: %APPDATA%\glances """ + paths = [] if WINDOWS: - path = os.environ.get('APPDATA') + paths.append(os.environ.get('APPDATA')) elif MACOS: - path = os.path.expanduser('~/Library/Application Support') + paths.append(os.environ.get('XDG_CONFIG_HOME') or os.path.expanduser('~/.config')) + paths.append(os.path.expanduser('~/Library/Application Support')) else: - path = os.environ.get('XDG_CONFIG_HOME') or os.path.expanduser('~/.config') - if path is None: - path = '' - else: - path = os.path.join(path, 'glances') + paths.append(os.environ.get('XDG_CONFIG_HOME') or os.path.expanduser('~/.config')) - return path + return [os.path.join(path, 'glances') if path is not None else '' for path in paths] def user_cache_dir(): - r"""Return the per-user cache dir (full path). + r"""Return a list of per-user cache dir (full path). - Linux, *BSD, SunOS: ~/.cache/glances - macOS: ~/Library/Caches/glances @@ -54,11 +52,11 @@ def user_cache_dir(): else: path = os.path.join(os.environ.get('XDG_CACHE_HOME') or os.path.expanduser('~/.cache'), 'glances') - return path + return [path] def system_config_dir(): - r"""Return the system-wide config dir (full path). + r"""Return a list of system-wide config dir (full path). - Linux, SunOS: /etc/glances - *BSD, macOS: /usr/local/etc/glances @@ -75,11 +73,11 @@ def system_config_dir(): else: path = os.path.join(path, 'glances') - return path + return [path] def default_config_dir(): - r"""Return the system-wide config dir (full path). + r"""Return a list of system-wide config dir (full path). - Linux, SunOS, *BSD, macOS: /usr/share/doc (as defined in the setup.py files) - Windows: %APPDATA%\glances @@ -93,7 +91,7 @@ def default_config_dir(): else: path = os.path.join(path, 'glances') - return path + return [path] class Config(object): @@ -127,7 +125,7 @@ class Config(object): * custom path: /path/to/glances * Linux, SunOS: ~/.config/glances, /etc/glances * *BSD: ~/.config/glances, /usr/local/etc/glances - * macOS: ~/Library/Application Support/glances, /usr/local/etc/glances + * macOS: ~/.config/glances, ~/Library/Application Support/glances, /usr/local/etc/glances * Windows: %APPDATA%\glances The config file will be searched in the following order of priority: @@ -138,12 +136,18 @@ class Config(object): """ paths = [] + # self.config_dir is the path to the config file (via -C flag) if self.config_dir: paths.append(self.config_dir) - paths.append(os.path.join(user_config_dir(), self.config_filename)) - paths.append(os.path.join(system_config_dir(), self.config_filename)) - paths.append(os.path.join(default_config_dir(), self.config_filename)) + # user_config_dir() returns a list of paths + paths.extend([os.path.join(path, self.config_filename) for path in user_config_dir()]) + + # system_config_dir() returns a list of paths + paths.extend([os.path.join(path, self.config_filename) for path in system_config_dir()]) + + # default_config_dir() returns a list of paths + paths.extend([os.path.join(path, self.config_filename) for path in default_config_dir()]) return paths @@ -321,6 +325,13 @@ class Config(object): pass return ret + def get_list_value(self, section, option, default=None, separator=','): + """Get the list value of an option, if it exists.""" + try: + return self.parser.get(section, option).split(separator) + except (NoOptionError, NoSectionError): + return default + def get_int_value(self, section, option, default=0): """Get the int value of an option, if it exists.""" try: diff --git a/glances/events.py b/glances/events.py index b107afa6..46938433 100644 --- a/glances/events.py +++ b/glances/events.py @@ -25,24 +25,34 @@ class GlancesEvents(object): event_value = value Item (or event) is defined by: - ["begin", - "end", - "WARNING|CRITICAL", - "CPU|LOAD|MEM", - MAX, AVG, MIN, SUM, COUNT, - [top3 process list], - "Processes description", - "top sort key"] + { + "begin": "begin", + "end": "end", + "state": "WARNING|CRITICAL", + "type": "CPU|LOAD|MEM", + "max": MAX, + "avg": AVG, + "min": MIN, + "sum": SUM, + "count": COUNT, + "top": [top 3 process name], + "desc": "Processes description", + "sort": "top sort key" + } """ - def __init__(self): + def __init__(self, max_events=10): """Init the events class.""" # Maximum size of the events list - self.events_max = 10 + self.set_max_events(max_events) # Init the logs list self.events_list = [] + def set_max_events(self, max_events): + """Set the maximum size of the events list.""" + self.max_events = max_events + def get(self): """Return the raw events list.""" return self.events_list @@ -56,11 +66,11 @@ class GlancesEvents(object): An event exist if: * end is < 0 - * event_type is matching + * type is matching Return -1 if the item is not found. """ for i in range(self.len()): - if self.events_list[i][1] < 0 and self.events_list[i][3] == event_type: + if self.events_list[i]['end'] < 0 and self.events_list[i]['type'] == event_type: return i return -1 @@ -101,14 +111,14 @@ class GlancesEvents(object): event_index = self.__event_exist(event_type) if event_index < 0: # Event did not exist, add it - self._create_event(event_state, event_type, event_value, proc_list, proc_desc, peak_time) + self._create_event(event_state, event_type, event_value, proc_desc) else: # Event exist, update it self._update_event(event_index, event_state, event_type, event_value, proc_list, proc_desc, peak_time) return self.len() - def _create_event(self, event_state, event_type, event_value, proc_list, proc_desc, peak_time): + def _create_event(self, event_state, event_type, event_value, proc_desc): """Add a new item in the log list. Item is added only if the criticality (event_state) is WARNING or CRITICAL. @@ -120,28 +130,27 @@ class GlancesEvents(object): # Create the new log item # Time is stored in Epoch format # Epoch -> DMYHMS = datetime.fromtimestamp(epoch) - item = [ - time.mktime(datetime.now().timetuple()), # START DATE - -1, # END DATE - event_state, # STATE: WARNING|CRITICAL - event_type, # TYPE: CPU, LOAD, MEM... - event_value, # MAX - event_value, # AVG - event_value, # MIN - event_value, # SUM - 1, # COUNT - [], # TOP 3 PROCESS LIST - proc_desc, # MONITORED PROCESSES DESC - glances_processes.sort_key, - ] # TOP PROCESS SORT KEY + item = { + "begin": time.mktime(datetime.now().timetuple()), + "end": -1, + "state": event_state, + "type": event_type, + "max": event_value, + "avg": event_value, + "min": event_value, + "sum": event_value, + "count": 1, + "top": [], + "desc": proc_desc, + "sort": glances_processes.sort_key, + } # Add the item to the list self.events_list.insert(0, item) - # Limit the list to 'events_max' items - if self.len() > self.events_max: + # Limit the list to 'max_events' items + if self.len() > self.max_events: self.events_list.pop() - return True else: return False @@ -154,9 +163,9 @@ class GlancesEvents(object): # Set the end of the events end_time = time.mktime(datetime.now().timetuple()) - if end_time - self.events_list[event_index][0] > peak_time: + if end_time - self.events_list[event_index]['begin'] > peak_time: # If event is > peak_time seconds - self.events_list[event_index][1] = end_time + self.events_list[event_index]['end'] = end_time else: # If event <= peak_time seconds, ignore self.events_list.remove(self.events_list[event_index]) @@ -166,25 +175,25 @@ class GlancesEvents(object): # State if event_state == "CRITICAL": - self.events_list[event_index][2] = event_state + self.events_list[event_index]['state'] = event_state # Min value - self.events_list[event_index][6] = min(self.events_list[event_index][6], event_value) + self.events_list[event_index]['min'] = min(self.events_list[event_index]['min'], event_value) # Max value - self.events_list[event_index][4] = max(self.events_list[event_index][4], event_value) + self.events_list[event_index]['max'] = max(self.events_list[event_index]['max'], event_value) # Average value - self.events_list[event_index][7] += event_value - self.events_list[event_index][8] += 1 - self.events_list[event_index][5] = self.events_list[event_index][7] / self.events_list[event_index][8] + self.events_list[event_index]['sum'] += event_value + self.events_list[event_index]['count'] += 1 + self.events_list[event_index]['avg'] = self.events_list[event_index]['sum'] / self.events_list[event_index]['count'] # TOP PROCESS LIST (only for CRITICAL ALERT) if event_state == "CRITICAL": events_sort_key = self.get_event_sort_key(event_type) # Sort the current process list to retrieve the TOP 3 processes - self.events_list[event_index][9] = sort_stats(proc_list, events_sort_key)[0:3] - self.events_list[event_index][11] = events_sort_key + self.events_list[event_index]['top'] = [p['name'] for p in sort_stats(proc_list, events_sort_key)[0:3]] + self.events_list[event_index]['sort'] = events_sort_key # MONITORED PROCESSES DESC - self.events_list[event_index][10] = proc_desc + self.events_list[event_index]['desc'] = proc_desc return True @@ -198,7 +207,7 @@ class GlancesEvents(object): clean_events_list = [] while self.len() > 0: item = self.events_list.pop() - if item[1] < 0 or (not critical and item[2].startswith("CRITICAL")): + if item['end'] < 0 or (not critical and item['state'].startswith("CRITICAL")): clean_events_list.insert(0, item) # The list is now the clean one self.events_list = clean_events_list diff --git a/glances/exports/couchdb/__init__.py b/glances/exports/couchdb/__init__.py index 4c50000c..5cc65529 100644 --- a/glances/exports/couchdb/__init__.py +++ b/glances/exports/couchdb/__init__.py @@ -9,14 +9,21 @@ """CouchDB interface class.""" +# +# How to test ? +# +# 1) docker run -d -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=admin -p 5984:5984 --name my-couchdb couchdb +# 2) ./venv/bin/python -m glances -C ./conf/glances.conf --export couchdb --quiet +# 3) Result can be seen at: http://127.0.0.1:5984/_utils +# + import sys from datetime import datetime from glances.logger import logger from glances.exports.export import GlancesExport -import couchdb -import couchdb.mapping +import pycouchdb class Export(GlancesExport): @@ -27,15 +34,9 @@ class Export(GlancesExport): """Init the CouchDB export IF.""" super(Export, self).__init__(config=config, args=args) - # Mandatory configuration keys (additional to host and port) - self.db = None - - # Optional configuration keys - self.user = None - self.password = None - - # Load the Cassandra configuration file section - self.export_enable = self.load_conf('couchdb', mandatories=['host', 'port', 'db'], options=['user', 'password']) + # Load the CouchDB configuration file section + # User and Password are mandatory with CouchDB 3.0 and higher + self.export_enable = self.load_conf('couchdb', mandatories=['host', 'port', 'db', 'user', 'password']) if not self.export_enable: sys.exit(2) @@ -47,35 +48,28 @@ class Export(GlancesExport): if not self.export_enable: return None - if self.user is None: - server_uri = 'http://{}:{}/'.format(self.host, self.port) - else: - # 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) + # @TODO: https + server_uri = 'http://{}:{}@{}:{}/'.format(self.user, self.password, self.host, self.port) try: - s = couchdb.Server(server_uri) + s = pycouchdb.Server(server_uri) except Exception as e: logger.critical("Cannot connect to CouchDB server (%s)" % e) sys.exit(2) else: - logger.info("Connected to the CouchDB server") + logger.info("Connected to the CouchDB server version %s" % s.info()['version']) try: - s[self.db] + s.database(self.db) except Exception: # Database did not exist # Create it... s.create(self.db) + logger.info("Create CouchDB database %s" % self.db) else: - logger.info("There is already a %s database" % self.db) + logger.info("CouchDB database %s already exist" % self.db) - return s - - def database(self): - """Return the CouchDB database object""" - return self.client[self.db] + return s.database(self.db) def export(self, name, columns, points): """Write the points to the CouchDB server.""" @@ -84,13 +78,12 @@ class Export(GlancesExport): # Create DB input data = dict(zip(columns, points)) - # Set the type to the current stat name + # Add the type and the timestamp in ISO format data['type'] = name - data['time'] = couchdb.mapping.DateTimeField()._to_json(datetime.now()) + data['time'] = datetime.now().isoformat()[:-3] + 'Z' # Write data to the CouchDB database - # Result can be seen at: http://127.0.0.1:5984/_utils try: - self.client[self.db].save(data) + self.client.save(data) except Exception as e: logger.error("Cannot export {} stats to CouchDB ({})".format(name, e)) diff --git a/glances/exports/export.py b/glances/exports/export.py index b4db4790..45a08c77 100644 --- a/glances/exports/export.py +++ b/glances/exports/export.py @@ -36,12 +36,13 @@ class GlancesExport(object): 'processlist', 'psutilversion', 'quicklook', + 'version', ] def __init__(self, config=None, args=None): """Init the export class.""" # Export name (= module name without glances_) - self.export_name = self.__class__.__module__[len('glances_') :] + self.export_name = self.__class__.__module__ logger.debug("Init export module %s" % self.export_name) # Init the config & args @@ -115,7 +116,7 @@ class GlancesExport(object): def parse_tags(self, tags): """Parse tags into a dict. - :param tags: a comma separated list of 'key:value' pairs. Example: foo:bar,spam:eggs + :param tags: a comma-separated list of 'key:value' pairs. Example: foo:bar,spam:eggs :return: a dict of tags. Example: {'foo': 'bar', 'spam': 'eggs'} """ d_tags = {} diff --git a/glances/exports/glances_mongodb.py b/glances/exports/mongodb/__init__.py similarity index 100% rename from glances/exports/glances_mongodb.py rename to glances/exports/mongodb/__init__.py diff --git a/glances/exports/prometheus/__init__.py b/glances/exports/prometheus/__init__.py index 9e90e129..919aeabb 100644 --- a/glances/exports/prometheus/__init__.py +++ b/glances/exports/prometheus/__init__.py @@ -71,7 +71,7 @@ class Export(GlancesExport): metric_name = self.prefix + self.METRIC_SEPARATOR + str(name) + self.METRIC_SEPARATOR + str(k) # Prometheus is very sensible to the metric name # See: https://prometheus.io/docs/practices/naming/ - for c in ['.', '-', '/', ' ']: + for c in ' .-/:[]': metric_name = metric_name.replace(c, self.METRIC_SEPARATOR) # Get the labels labels = self.parse_tags(self.labels) diff --git a/glances/folder_list.py b/glances/folder_list.py index 135531d2..595c536f 100644 --- a/glances/folder_list.py +++ b/glances/folder_list.py @@ -10,25 +10,11 @@ """Manage the folder list.""" from __future__ import unicode_literals -import os from glances.timer import Timer -from glances.globals import nativestr +from glances.globals import nativestr, folder_size from glances.logger import logger -# Use the built-in version of scandir/walk if possible, otherwise -# use the scandir module version -scandir_tag = True -try: - # For Python 3.5 or higher - from os import scandir -except ImportError: - # For others... - try: - from scandir import scandir - except ImportError: - scandir_tag = False - class FolderList(object): @@ -62,12 +48,9 @@ class FolderList(object): self.first_grab = True if self.config is not None and self.config.has_section('folders'): - if scandir_tag: - # Process monitoring list - logger.debug("Folder list configuration detected") - self.__set_folder_list('folders') - else: - logger.error('Scandir not found. Please use Python 3.5+ or install the scandir lib') + # Process monitoring list + logger.debug("Folder list configuration detected") + self.__set_folder_list('folders') else: self.__folder_list = [] @@ -132,23 +115,6 @@ class FolderList(object): else: return None - def __folder_size(self, path): - """Return the size of the directory given by path - - path: """ - - ret = 0 - for f in scandir(path): - if f.is_dir(follow_symlinks=False) and (f.name != '.' or f.name != '..'): - ret += self.__folder_size(os.path.join(path, f.name)) - else: - try: - ret += f.stat().st_size - except OSError: - pass - - return ret - def update(self, key='path'): """Update the command result attributed.""" # Only continue if monitor list is not empty @@ -163,15 +129,13 @@ class FolderList(object): # Set the key (see issue #2327) self.__folder_list[i]['key'] = key # Get folder size - try: - self.__folder_list[i]['size'] = self.__folder_size(self.path(i)) - except OSError as e: - logger.debug('Cannot get folder size ({}). Error: {}'.format(self.path(i), e)) - if e.errno == 13: - # Permission denied - self.__folder_list[i]['size'] = '!' - else: - self.__folder_list[i]['size'] = '?' + self.__folder_list[i]['size'], self.__folder_list[i]['errno'] = folder_size(self.path(i)) + if self.__folder_list[i]['errno'] != 0: + logger.debug( + 'Folder size ({} ~ {}) may not be correct. Error: {}'.format( + self.path(i), self.__folder_list[i]['size'], self.__folder_list[i]['errno'] + ) + ) # Reset the timer self.timer_folders[i].reset() diff --git a/glances/globals.py b/glances/globals.py index c539c9b5..9e7e20a1 100644 --- a/glances/globals.py +++ b/glances/globals.py @@ -25,6 +25,8 @@ import subprocess from datetime import datetime import re import base64 +import functools +import weakref import queue from configparser import ConfigParser, NoOptionError, NoSectionError @@ -258,7 +260,7 @@ def pretty_date(time=False): Source: https://stackoverflow.com/questions/1551382/user-friendly-time-format-in-python """ now = datetime.now() - if type(time) is int: + if isinstance(time, int): diff = now - datetime.fromtimestamp(time) elif isinstance(time, datetime): diff = now - time @@ -315,10 +317,10 @@ def json_dumps(data): return ujson.dumps(data, ensure_ascii=False) -def json_dumps_dictlist(data, item): +def dictlist(data, item): if isinstance(data, dict): try: - return json_dumps({item: data[item]}) + return {item: data[item]} except (TypeError, IndexError, KeyError): return None elif isinstance(data, list): @@ -326,13 +328,21 @@ def json_dumps_dictlist(data, item): # Source: # http://stackoverflow.com/questions/4573875/python-get-index-of-dictionary-item-in-list # But https://github.com/nicolargo/glances/issues/1401 - return json_dumps({item: list(map(itemgetter(item), data))}) + return {item: list(map(itemgetter(item), data))} except (TypeError, IndexError, KeyError): return None else: return None +def json_dumps_dictlist(data, item): + dl = dictlist(data, item) + if dl is None: + return None + else: + return json_dumps(dl) + + def string_value_to_float(s): """Convert a string with a value and an unit to a float. Example: @@ -372,3 +382,57 @@ def string_value_to_float(s): def file_exists(filename): """Return True if the file exists and is readable.""" return os.path.isfile(filename) and os.access(filename, os.R_OK) + + +def folder_size(path, errno=0): + """Return a tuple with the size of the directory given by path and the errno. + If an error occurs (for example one file or subfolder is not accessible), + errno is set to the error number. + + path: + errno: Should always be 0 when calling the function""" + ret_size = 0 + ret_err = errno + try: + for f in os.scandir(path): + if f.is_dir(follow_symlinks=False) and (f.name != '.' or f.name != '..'): + ret = folder_size(os.path.join(path, f.name), ret_err) + ret_size += ret[0] + ret_err = ret[1] + else: + try: + ret_size += f.stat().st_size + except OSError as e: + ret_err = e.errno + except OSError as e: + return 0, e.errno + else: + return ret_size, ret_err + + +def weak_lru_cache(maxsize=128, typed=False): + """LRU Cache decorator that keeps a weak reference to self + Source: https://stackoverflow.com/a/55990799""" + + def wrapper(func): + @functools.lru_cache(maxsize, typed) + def _func(_self, *args, **kwargs): + return func(_self(), *args, **kwargs) + + @functools.wraps(func) + def inner(self, *args, **kwargs): + return _func(weakref.ref(self), *args, **kwargs) + + return inner + + return wrapper + + +def namedtuple_to_dict(data): + """Convert a namedtuple to a dict, using the _asdict() method embeded in PsUtil stats.""" + return {k: (v._asdict() if hasattr(v, '_asdict') else v) for k, v in data.items()} + + +def list_of_namedtuple_to_list_of_dict(data): + """Convert a list of namedtuples to a dict, using the _asdict() method embeded in PsUtil stats.""" + return [namedtuple_to_dict(d) for d in data] diff --git a/glances/main.py b/glances/main.py index ead588d1..a2bf4933 100644 --- a/glances/main.py +++ b/glances/main.py @@ -12,8 +12,10 @@ import argparse import sys import tempfile +from logging import DEBUG +from warnings import simplefilter -from glances import __version__, psutil_version +from glances import __version__, psutil_version, __apiversion__ from glances.globals import WINDOWS, disable, enable from glances.config import Config from glances.processes import sort_processes_key_list @@ -81,13 +83,13 @@ Examples of use: Display CSV stats to stdout (all stats in one line): $ glances --stdout-csv now,cpu.user,mem.used,load - Enable some plugins disabled by default (comma separated list): + Enable some plugins disabled by default (comma-separated list): $ glances --enable-plugin sensors - Disable some plugins (comma separated list): + Disable some plugins (comma-separated list): $ glances --disable-plugin network,ports - Disable all plugins except some (comma separated list): + Disable all plugins except some (comma-separated list): $ glances --disable-plugin all --enable-plugin cpu,mem,load """ @@ -97,18 +99,26 @@ Examples of use: # Read the command line arguments self.args = self.parse_args() + def version_msg(self): + """Return the version message.""" + version = 'Glances version:\t{}\n'.format(__version__) + version += 'Glances API version:\t{}\n'.format(__apiversion__) + version += 'PsUtil version:\t\t{}\n'.format(psutil_version) + version += 'Log file:\t\t{}\n'.format(LOG_FILENAME) + return version + def init_args(self): """Init all the command line arguments.""" - version = 'Glances v{} with PsUtil v{}\nLog file: {}'.format(__version__, psutil_version, LOG_FILENAME) parser = argparse.ArgumentParser( prog='glances', conflict_handler='resolve', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=self.example_of_use, ) - parser.add_argument('-V', '--version', action='version', version=version) + parser.add_argument('-V', '--version', action='version', version=self.version_msg()) parser.add_argument('-d', '--debug', action='store_true', default=False, dest='debug', help='enable debug mode') parser.add_argument('-C', '--config', dest='conf_file', help='path to the configuration file') + parser.add_argument('-P', '--plugins', dest='plugin_dir', help='path to additional plugin directory') # Disable plugin parser.add_argument( '--modules-list', @@ -121,12 +131,17 @@ Examples of use: parser.add_argument( '--disable-plugin', '--disable-plugins', + '--disable', dest='disable_plugin', - help='disable plugin (comma separated list or all). If all is used, \ + 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 separated list)' + '--enable-plugin', + '--enable-plugins', + '--enable', + dest='enable_plugin', + help='enable plugin (comma-separated list)', ) parser.add_argument( '--disable-process', @@ -149,7 +164,7 @@ Examples of use: action='store_true', default=False, dest='enable_light', - help='light mode for Curses UI (disable all but top menu)', + help='light mode for Curses UI (disable all but the top menu)', ) parser.add_argument( '-0', @@ -229,12 +244,11 @@ Examples of use: help='enable extended stats on top process', ) parser.add_argument( - '--separator', - '--enable-separator', - action='store_true', - default=False, + '--disable-separator', + action='store_false', + default=True, dest='enable_separator', - help='enable separator in the UI', + help='disable separator in the UI (between top and others modules)', ), parser.add_argument( '--disable-cursor', @@ -260,7 +274,7 @@ Examples of use: help='Accumulate processes by program', ) # Export modules feature - parser.add_argument('--export', dest='export', help='enable export module (comma separated 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' ) @@ -355,7 +369,7 @@ Examples of use: action='store_true', default=False, dest='webserver', - help='run Glances in web server mode (bottle needed)', + help='run Glances in web server mode (FastAPI, Uvicorn, Jinja2 and OrJsonLib needed)', ) parser.add_argument( '--cached-time', @@ -413,19 +427,19 @@ Examples of use: '--stdout', default=None, dest='stdout', - help='display stats to stdout, one stat per line (comma separated list of plugins/plugins.attribute)', + help='display stats to stdout, one stat per line (comma-separated list of plugins/plugins.attribute)', ) parser.add_argument( '--stdout-json', default=None, dest='stdout_json', - help='display stats to stdout, JSON format (comma separated list of plugins/plugins.attribute)', + help='display stats to stdout, JSON format (comma-separated list of plugins/plugins.attribute)', ) parser.add_argument( '--stdout-csv', default=None, dest='stdout_csv', - help='display stats to stdout, CSV format (comma separated list of plugins/plugins.attribute)', + help='display stats to stdout, CSV format (comma-separated list of plugins/plugins.attribute)', ) parser.add_argument( '--issue', @@ -457,7 +471,7 @@ Examples of use: action='store_true', default=False, dest='no_kernel_threads', - help='hide kernel threads in process list (not available on Windows)', + help='hide kernel threads in the process list (not available on Windows)', ) parser.add_argument( '-b', @@ -465,7 +479,7 @@ Examples of use: action='store_true', default=False, dest='byte', - help='display network rate in byte per second', + help='display network rate in bytes per second', ) parser.add_argument( '--diskio-show-ramfs', @@ -514,7 +528,7 @@ Examples of use: action='store_true', default=False, dest='theme_white', - help='optimize display colors for white background', + help='optimize display colors for a white background', ) # Globals options parser.add_argument( @@ -533,36 +547,28 @@ Examples of use: return parser - def parse_args(self): - """Parse command line arguments.""" - args = self.init_args().parse_args() - - # Load the configuration file, if it exists - # This function should be called after the parse_args - # because the configuration file path can be defined - self.config = Config(args.conf_file) - - # Debug mode + def init_debug(self, args): + """Init Glances debug mode.""" if args.debug: - from logging import DEBUG - logger.setLevel(DEBUG) else: - from warnings import simplefilter - simplefilter("ignore") - # Plugins refresh rate + def init_refresh_rate(self, args): + """Init Glances refresh rate""" if self.config.has_section('global'): global_refresh = self.config.get_float_value('global', 'refresh', default=self.DEFAULT_REFRESH_TIME) else: global_refresh = self.DEFAULT_REFRESH_TIME - # The configuration key can be overwrite from the command line + + # The configuration key can be overwrite from the command line (-t