mirror of https://github.com/nicolargo/glances.git
version 3.1.6
This commit is contained in:
commit
0d35d5477b
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Start Glances with the followings options '...'
|
||||
2. Press the key '....'
|
||||
3. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. GNU/Linux Ubuntu 20.04]
|
||||
- Glances Version [output of glances -V]
|
||||
- Glances logs file [output of tail -10 <glances logs file>]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
name: CI
|
||||
|
||||
env:
|
||||
DEFAULT_DOCKER_IMAGE: nicolargo/glances
|
||||
NODE_ENV: ${{ (contains('refs/heads/master', github.ref) || startsWith(github.ref, 'refs/tags/v')) && 'prod' || 'dev' }}
|
||||
PUSH_BRANCH: ${{ 'refs/heads/develop' == github.ref || 'refs/heads/master' == github.ref || startsWith(github.ref, 'refs/tags/v') }}
|
||||
DOCKER_PLATFORMS: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ develop ]
|
||||
push:
|
||||
branches: [ master, develop ]
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
buildx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ env.NODE_ENV }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-${{ env.NODE_ENV }}
|
||||
|
||||
- name: Configure ENVs
|
||||
env:
|
||||
DOCKER_IMAGE: ${{ secrets.DOCKER_IMAGE || env.DEFAULT_DOCKER_IMAGE }}
|
||||
DOCKERFILE: ${{ env.NODE_ENV == 'prod' && './docker-files/Dockerfile' || './docker-files/dev.Dockerfile' }}
|
||||
run: |
|
||||
ls -la /tmp/.buildx-cache || true
|
||||
VERSION=latest
|
||||
|
||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
VERSION=${GITHUB_REF#refs/tags/v}
|
||||
fi
|
||||
|
||||
if [[ $GITHUB_REF == refs/heads/develop ]]; then
|
||||
VERSION=dev
|
||||
fi
|
||||
|
||||
echo "DOCKERFILE=${DOCKERFILE}" >> $GITHUB_ENV
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_ENV
|
||||
echo "TAGS=${DOCKER_IMAGE}:${VERSION}" >> $GITHUB_ENV
|
||||
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
|
||||
echo "VCS_REF=${GITHUB_SHA::8}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
if: ${{ env.PUSH_BRANCH == 'true' }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: ${{ env.PUSH_BRANCH == 'true' }}
|
||||
tags: ${{env.TAGS}}
|
||||
build-args: |
|
||||
VERSION=${{env.VERSION}}
|
||||
BUILD_DATE=${{env.BUILD_DATE}}
|
||||
VCS_REF=${{env.VCS_REF}}
|
||||
context: .
|
||||
file: ${{env.DOCKERFILE}}
|
||||
platforms: ${{env.DOCKER_PLATFORMS}}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
|
||||
28
.travis.yml
28
.travis.yml
|
|
@ -23,12 +23,22 @@ after_success:
|
|||
- coveralls
|
||||
|
||||
deploy:
|
||||
provider: pypi
|
||||
user: nicolargo
|
||||
password:
|
||||
secure: Fms23jiiKKq6qJMsZYrmBz5mC753VGrjCxzVrsioENfH3KaFf6kUc9fTYntaLvjLPTNBkU3R2IORfVOikJKmNWqWVZOdJ/nq8zPl6o9MgdNcX7qWTvY8Fi9MW7tIZHrehhm0LvWFVq8ZSc8iYzw3/741lvBh8vpJZSQs3sq/1QI=
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
distributions: sdist bdist_wheel
|
||||
repo: nicolargo/glances
|
||||
- provider: pypi
|
||||
user: nicolargo
|
||||
password:
|
||||
secure: Fms23jiiKKq6qJMsZYrmBz5mC753VGrjCxzVrsioENfH3KaFf6kUc9fTYntaLvjLPTNBkU3R2IORfVOikJKmNWqWVZOdJ/nq8zPl6o9MgdNcX7qWTvY8Fi9MW7tIZHrehhm0LvWFVq8ZSc8iYzw3/741lvBh8vpJZSQs3sq/1QI=
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
distributions: sdist bdist_wheel
|
||||
repo: nicolargo/glances
|
||||
- provider: pypi
|
||||
server: https://test.pypi.org/legacy/
|
||||
user: nicolargo
|
||||
password:
|
||||
secure: kxchYP3VJWe74jun0rJjuEFFpnO2sF3WHsK5Axlz4flJ6dtX0OPeZd9SlqgMX7cv9FHcXxyukVKrw4PHVqUNcWoaKM8TNeddKkGeSjcVY5C7NIExXh5es4SguozdT4cckoJUyN2xXc7cUAM68CHWfxijR6NiDMXIuMJrZumye6c=
|
||||
on:
|
||||
tags: false
|
||||
branch: develop
|
||||
distributions: sdist bdist_wheel
|
||||
repo: nicolargo/glances
|
||||
|
|
|
|||
48
NEWS.rst
48
NEWS.rst
|
|
@ -2,6 +2,54 @@
|
|||
Glances Version 3
|
||||
==============================================================================
|
||||
|
||||
Version 3.1.6
|
||||
=============
|
||||
|
||||
Enhancements and new features:
|
||||
|
||||
* Kill a process from the Curses interface #1444
|
||||
* Manual refresh on F5 in the Curses interface #1753
|
||||
* Hide function in sensors section #1590
|
||||
* Enhancement Request: .conf parameter for AMP #1690
|
||||
* Password for Web/Browser mode #1674
|
||||
* Unable to connect to Influxdb 2.0 #1776
|
||||
* ci: fix release process and improve build speeds #1782
|
||||
* Cache cpuinfo output #1700
|
||||
* sort by clicking improvements and bug #1578
|
||||
* Allow embedded AMP python script to be placed in a configurable location #1734
|
||||
* Add attributes to stdout/stdout-csv plugins #1733
|
||||
* Do not shorten container names #1723
|
||||
|
||||
Bugs corrected:
|
||||
|
||||
* Version tag for docker image packaging #1754
|
||||
* Unusual characters in cmdline cause lines to disappear and corrupt the display #1692
|
||||
* UnicodeDecodeError on any command with a utf8 character in its name #1676
|
||||
* Docker image is not up to date install #1662
|
||||
* Add option to set the strftime format #1785
|
||||
* fix: docker dev build contains all optional requirements #1779
|
||||
* GPU information is incomplete via web #1697
|
||||
* [WebUI] Fix display of null values for GPU plugin #1773
|
||||
* crash on startup on Illumos when no swap is configured #1767
|
||||
* Glances crashes with 2 GPUS bug #1683
|
||||
* [Feature Request] Filter Docker containers#1748
|
||||
* Error with IP Plugin : object has no attribute #1528
|
||||
* docker-compose #1760
|
||||
* [WebUI] Fix sort by disk io #1759
|
||||
* Connection to MQTT server failst #1705
|
||||
* Misleading image tag latest-arm needs contributor packaging #1419
|
||||
* Docker nicolargo/glances:latest missing arm builds? #1746
|
||||
* Alpine image is broken packaging #1744
|
||||
* RIP Alpine? needs contributor packaging #1741
|
||||
* Manpage improvement documentation #1743
|
||||
* Make build reproducible packaging #1740
|
||||
* Automated multiarch builds for docker #1716
|
||||
* web ui of glances is not coming #1721
|
||||
* fixing command in json.rst #1724
|
||||
* Fix container rss value #1722
|
||||
* Alpine Image is broken needs test packaging #1720
|
||||
* Fix gpu plugin to handle multiple gpus with different reporting capabilities bug #1634
|
||||
|
||||
Version 3.1.5
|
||||
=============
|
||||
|
||||
|
|
|
|||
42
README.rst
42
README.rst
|
|
@ -9,9 +9,13 @@ Glances - An eye on your system
|
|||
:target: https://github.com/nicolargo/glances/
|
||||
:alt: Github stars
|
||||
|
||||
.. image:: https://img.shields.io/docker/pulls/nicolargo/glances
|
||||
:target: https://hub.docker.com/r/nicolargo/glances/
|
||||
:alt: Docker pull
|
||||
|
||||
.. image:: https://pepy.tech/badge/glances/month
|
||||
:target: https://pepy.tech/project/glances
|
||||
:alt: Downloads
|
||||
:alt: Pypi downloads
|
||||
|
||||
.. image:: https://img.shields.io/travis/nicolargo/glances/master.svg?maxAge=3600&label=Linux%20/%20BSD%20/%20macOS
|
||||
:target: https://travis-ci.org/nicolargo/glances
|
||||
|
|
@ -24,8 +28,8 @@ Glances - An eye on your system
|
|||
.. image:: https://scrutinizer-ci.com/g/nicolargo/glances/badges/quality-score.png?b=develop
|
||||
:target: https://scrutinizer-ci.com/g/nicolargo/glances/?branch=develop
|
||||
|
||||
.. image:: https://img.shields.io/badge/Donate-PayPal-green.svg
|
||||
:target: https://www.paypal.me/nicolargo
|
||||
.. image:: https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&link=https://github.com/sponsors/nicolargo
|
||||
:target: https://github.com/sponsors/nicolargo
|
||||
|
||||
.. image:: https://img.shields.io/twitter/url/https/twitter.com/cloudposse.svg?style=social&label=Follow%20%40nicolargo
|
||||
:target: https://twitter.com/nicolargo
|
||||
|
|
@ -65,7 +69,8 @@ Optional dependencies:
|
|||
- ``docker`` (for the Docker monitoring support) [Linux/macOS-only]
|
||||
- ``elasticsearch`` (for the Elastic Search export module)
|
||||
- ``hddtemp`` (for HDD temperature monitoring support) [Linux-only]
|
||||
- ``influxdb`` (for the InfluxDB export module)
|
||||
- ``influxdb`` (for the InfluxDB version 1 export module)
|
||||
- ``influxdb-client`` (for the InfluxDB version 2 export module) [Only for Python >= 3.6]
|
||||
- ``kafka-python`` (for the Kafka export module)
|
||||
- ``netifaces`` (for the IP plugin)
|
||||
- ``nvidia-ml-py3`` (for the GPU plugin)
|
||||
|
|
@ -161,6 +166,13 @@ If you need to install Glances in a specific user location, use:
|
|||
export PYTHONUSERBASE=~/mylocalpath
|
||||
pip install --user glances
|
||||
|
||||
The current develop branch is also published to the test.pypi.org package index.
|
||||
If you want to test the develop version, enter:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
pip install -i https://test.pypi.org/simple/ Glances
|
||||
|
||||
Docker: the funny way
|
||||
---------------------
|
||||
|
||||
|
|
@ -168,24 +180,30 @@ A Glances container is available. It includes the latest development
|
|||
HEAD version. You can use it to monitor your server and all your other
|
||||
containers!
|
||||
|
||||
Get the Glances container:
|
||||
Get the Glances container (latest develop branch):
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
docker pull nicolargo/glances
|
||||
docker pull nicolargo/glances:dev
|
||||
|
||||
Note, you can choose another branch with :
|
||||
|
||||
- nicolargo/glances:latest for the last master branch (included multiple architectures 386, amd64, arm/v7 and arm64)
|
||||
- nicolargo/glances:dev for the last develop branch (included multiple architectures 386, amd64, arm/v7 and arm64)
|
||||
- nicolargo/glances:<version> for the specific <version> (included multiple architectures 386, amd64, arm/v7 and arm64)
|
||||
|
||||
Run the container in *console mode*:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it docker.io/nicolargo/glances
|
||||
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it nicolargo/glances:dev
|
||||
|
||||
Additionally, if you want to use your own glances.conf file, you can
|
||||
create your own Dockerfile:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
FROM nicolargo/glances
|
||||
FROM nicolargo/glances:dev
|
||||
COPY glances.conf /glances/conf/glances.conf
|
||||
CMD python -m glances -C /glances/conf/glances.conf $GLANCES_OPT
|
||||
|
||||
|
|
@ -194,7 +212,7 @@ docker run options:
|
|||
|
||||
.. code-block:: console
|
||||
|
||||
docker run -v `pwd`/glances.conf:/glances/conf/glances.conf -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host -it docker.io/nicolargo/glances
|
||||
docker run -v `pwd`/glances.conf:/glances/conf/glances.conf -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host -it nicolargo/glances:dev
|
||||
|
||||
Where \`pwd\`/glances.conf is a local directory containing your glances.conf file.
|
||||
|
||||
|
|
@ -203,7 +221,7 @@ variable setting parameters for the glances startup command):
|
|||
|
||||
.. code-block:: console
|
||||
|
||||
docker run -d --restart="always" -p 61208-61209:61208-61209 -e GLANCES_OPT="-w" -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host docker.io/nicolargo/glances
|
||||
docker run -d --restart="always" -p 61208-61209:61208-61209 -e GLANCES_OPT="-w" -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host nicolargo/glances:dev
|
||||
|
||||
GNU/Linux
|
||||
---------
|
||||
|
|
@ -416,8 +434,7 @@ Donation
|
|||
|
||||
If this project help you, you can give me a tip ;)
|
||||
|
||||
.. image:: https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif
|
||||
:target: https://www.paypal.me/nicolargo
|
||||
See the sponsors_ page.
|
||||
|
||||
Author
|
||||
======
|
||||
|
|
@ -440,3 +457,4 @@ Glances is distributed under the LGPL version 3 license. See ``COPYING`` for mor
|
|||
.. _forum: https://groups.google.com/forum/?hl=en#!forum/glances-users
|
||||
.. _wiki: https://github.com/nicolargo/glances/wiki/How-to-contribute-to-Glances-%3F
|
||||
.. _package: https://repology.org/metapackage/glances/packages
|
||||
.. _sponsors: https://github.com/sponsors/nicolargo
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ careful=50
|
|||
warning=70
|
||||
critical=90
|
||||
# Allow additional file system types (comma-separated FS type)
|
||||
#allow=zfs
|
||||
#allow=shm
|
||||
|
||||
[irq]
|
||||
# Documentation: https://glances.readthedocs.io/en/stable/aoa/irq.html
|
||||
|
|
@ -327,6 +327,14 @@ port_default_gateway=True
|
|||
|
||||
[docker]
|
||||
disable=False
|
||||
# Only show specific containers (comma separeted list of container name or regular expression)
|
||||
# Comment this line to display all containers (default configuration)
|
||||
#show=telegraf
|
||||
# Hide some containers (comma separeted list of container name or regular expression)
|
||||
# Comment this line to display all containers (default configuration)
|
||||
#hide=telegraf
|
||||
# Define the maximum docker size name (default is 20 chars)
|
||||
max_name_size=20
|
||||
#cpu_careful=50
|
||||
# Thresholds for CPU and MEM (in %)
|
||||
#cpu_warning=70
|
||||
|
|
@ -390,6 +398,10 @@ height=600
|
|||
style=DarkStyle
|
||||
|
||||
[influxdb]
|
||||
# !!!
|
||||
# Will be DEPRECATED in future release.
|
||||
# Please have a look on the new influxdb2 export module (compatible with InfluxDB 1.8.x and 2.x)
|
||||
# !!!
|
||||
# Configuration for the --export influxdb option
|
||||
# https://influxdb.com/
|
||||
host=localhost
|
||||
|
|
@ -410,6 +422,27 @@ prefix=localhost
|
|||
# You can also use dynamic values
|
||||
#tags=system:`uname -s`
|
||||
|
||||
[influxdb2]
|
||||
# Configuration for the --export influxdb2 option
|
||||
# https://influxdb.com/
|
||||
host=localhost
|
||||
port=8086
|
||||
protocol=http
|
||||
org=nicolargo
|
||||
bucket=glances
|
||||
token=EjFUTWe8U-MIseEAkaVIgVnej_TrnbdvEcRkaB1imstW7gapSqy6_6-8XD-yd51V0zUUpDy-kAdVD1purDLuxA==
|
||||
# Prefix will be added for all measurement name
|
||||
# Ex: prefix=foo
|
||||
# => foo.cpu
|
||||
# => foo.mem
|
||||
# You can also use dynamic values
|
||||
#prefix=`hostname`
|
||||
prefix=localhost
|
||||
# Tags will be added for all measurements
|
||||
#tags=foo:bar,spam:eggs
|
||||
# You can also use dynamic values
|
||||
#tags=system:`uname -s`
|
||||
|
||||
[cassandra]
|
||||
# Configuration for the --export cassandra option
|
||||
# Also works for the ScyllaDB
|
||||
|
|
@ -461,6 +494,7 @@ port=5672
|
|||
user=guest
|
||||
password=guest
|
||||
queue=glances_queue
|
||||
#protocol=amqps
|
||||
|
||||
[mqtt]
|
||||
# Configuration for the --export mqtt option
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
FROM nicolargo/glances:dev
|
||||
COPY glances.conf /glances/conf/glances.conf
|
||||
CMD python -m glances -C /glances/conf/glances.conf $GLANCES_OPT
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
glances:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: Dockerfile
|
||||
restart: always
|
||||
ports:
|
||||
- "61208:61208"
|
||||
# - "61209:61209"
|
||||
environment:
|
||||
# - GLANCES_OPT="-w"
|
||||
GLANCES_OPT: "-w"
|
||||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
- "./glances.conf:/glances/conf/glances.conf"
|
||||
pid: "host"
|
||||
|
|
@ -0,0 +1,616 @@
|
|||
##############################################################################
|
||||
# Globals Glances parameters
|
||||
##############################################################################
|
||||
|
||||
[global]
|
||||
# Does Glances should 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
|
||||
|
||||
##############################################################################
|
||||
# User interface
|
||||
##############################################################################
|
||||
|
||||
[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
|
||||
|
||||
##############################################################################
|
||||
# plugins
|
||||
##############################################################################
|
||||
|
||||
[quicklook]
|
||||
# Set to true to disable a plugin
|
||||
# Note: you can also disable it from the command line (see --disable-plugin <plugin_name>)
|
||||
disable=False
|
||||
# Graphical percentage char used in the terminal user interface (default is |)
|
||||
percentage_char=|
|
||||
# Define CPU, MEM and SWAP thresholds in %
|
||||
cpu_careful=50
|
||||
cpu_warning=70
|
||||
cpu_critical=90
|
||||
mem_careful=50
|
||||
mem_warning=70
|
||||
mem_critical=90
|
||||
swap_careful=50
|
||||
swap_warning=70
|
||||
swap_critical=90
|
||||
|
||||
[cpu]
|
||||
disable=False
|
||||
# Default values if not defined: 50/70/90 (except for iowait)
|
||||
user_careful=50
|
||||
user_warning=70
|
||||
user_critical=90
|
||||
#user_log=False
|
||||
#user_critical_action=echo {{user}} {{value}} {{max}} > /tmp/cpu.alert
|
||||
system_careful=50
|
||||
system_warning=70
|
||||
system_critical=90
|
||||
steal_careful=50
|
||||
steal_warning=70
|
||||
steal_critical=90
|
||||
#steal_log=True
|
||||
# I/O wait percentage should be lower than 1/# (Logical CPU cores)
|
||||
# Leave commented to just use the default config (1/#-20% / 1/#-10% / 1/#)
|
||||
#iowait_careful=30
|
||||
#iowait_warning=40
|
||||
#iowait_critical=50
|
||||
# Context switch limit (core / second)
|
||||
# Leave commented to just use the default config (critical is 50000*# (Logical CPU cores)
|
||||
#ctx_switches_careful=10000
|
||||
#ctx_switches_warning=12000
|
||||
#ctx_switches_critical=14000
|
||||
|
||||
[percpu]
|
||||
disable=False
|
||||
# Define CPU thresholds in %
|
||||
# Default values if not defined: 50/70/90
|
||||
user_careful=50
|
||||
user_warning=70
|
||||
user_critical=90
|
||||
iowait_careful=50
|
||||
iowait_warning=70
|
||||
iowait_critical=90
|
||||
system_careful=50
|
||||
system_warning=70
|
||||
system_critical=90
|
||||
|
||||
[gpu]
|
||||
disable=False
|
||||
# Default processor values if not defined: 50/70/90
|
||||
proc_careful=50
|
||||
proc_warning=70
|
||||
proc_critical=90
|
||||
# Default memory values if not defined: 50/70/90
|
||||
mem_careful=50
|
||||
mem_warning=70
|
||||
mem_critical=90
|
||||
|
||||
[mem]
|
||||
disable=False
|
||||
# Define RAM thresholds in %
|
||||
# Default values if not defined: 50/70/90
|
||||
careful=50
|
||||
#careful_action_repeat=echo {{percent}} >> /tmp/memory.alert
|
||||
warning=70
|
||||
critical=90
|
||||
|
||||
[memswap]
|
||||
disable=False
|
||||
# Define SWAP thresholds in %
|
||||
# Default values if not defined: 50/70/90
|
||||
careful=50
|
||||
warning=70
|
||||
critical=90
|
||||
|
||||
[load]
|
||||
disable=False
|
||||
# Define LOAD thresholds
|
||||
# Value * number of cores
|
||||
# Default values if not defined: 0.7/1.0/5.0 per number of cores
|
||||
# Source: http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages
|
||||
# http://www.linuxjournal.com/article/9001
|
||||
careful=0.7
|
||||
warning=1.0
|
||||
critical=5.0
|
||||
#log=False
|
||||
|
||||
[network]
|
||||
disable=False
|
||||
# Default bitrate thresholds in % of the network interface speed
|
||||
# Default values if not defined: 70/80/90
|
||||
rx_careful=70
|
||||
rx_warning=80
|
||||
rx_critical=90
|
||||
tx_careful=70
|
||||
tx_warning=80
|
||||
tx_critical=90
|
||||
# Define the list of hidden network interfaces (comma-separated regexp)
|
||||
#hide=docker.*,lo
|
||||
# WLAN 0 alias
|
||||
#wlan0_alias=Wireless IF
|
||||
# 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
|
||||
#wlan0_rx_warning=5000000
|
||||
#wlan0_rx_critical=6000000
|
||||
#wlan0_rx_log=True
|
||||
#wlan0_tx_careful=700000
|
||||
#wlan0_tx_warning=900000
|
||||
#wlan0_tx_critical=1000000
|
||||
#wlan0_tx_log=True
|
||||
|
||||
[connections]
|
||||
# Display additional information about TCP connections
|
||||
# This plugin is disabled by default
|
||||
disable=True
|
||||
# nf_conntrack thresholds in %
|
||||
nf_conntrack_percent_careful=70
|
||||
nf_conntrack_percent_warning=80
|
||||
nf_conntrack_percent_critical=90
|
||||
|
||||
[wifi]
|
||||
disable=False
|
||||
# Define the list of hidden wireless network interfaces (comma-separated regexp)
|
||||
hide=lo,docker.*
|
||||
# Define SIGNAL thresholds in db (lower is better...)
|
||||
# Based on: http://serverfault.com/questions/501025/industry-standard-for-minimum-wifi-signal-strength
|
||||
careful=-65
|
||||
warning=-75
|
||||
critical=-85
|
||||
|
||||
[diskio]
|
||||
disable=False
|
||||
# Define the list of hidden disks (comma-separated regexp)
|
||||
#hide=sda2,sda5,loop.*
|
||||
hide=loop.*,/dev/loop*
|
||||
# Alias for sda1
|
||||
#sda1_alias=InternalDisk
|
||||
|
||||
[fs]
|
||||
disable=False
|
||||
# Define the list of hidden file system (comma-separated regexp)
|
||||
hide=/boot.*,/snap.*
|
||||
# Define filesystem space thresholds in %
|
||||
# Default values if not defined: 50/70/90
|
||||
# It is also possible to define per mount point value
|
||||
# Example: /_careful=40
|
||||
careful=50
|
||||
warning=70
|
||||
critical=90
|
||||
# Allow additional file system types (comma-separated FS type)
|
||||
#allow=shm
|
||||
|
||||
[irq]
|
||||
# Documentation: https://glances.readthedocs.io/en/stable/aoa/irq.html
|
||||
# This plugin is disabled by default
|
||||
disable=False
|
||||
|
||||
[folders]
|
||||
# Documentation: https://glances.readthedocs.io/en/stable/aoa/folders.html
|
||||
disable=False
|
||||
# Define a folder list to monitor
|
||||
# The list is composed of items (list_#nb <= 10)
|
||||
# An item is defined by:
|
||||
# * path: absolute path
|
||||
# * careful: optional careful threshold (in MB)
|
||||
# * warning: optional warning threshold (in MB)
|
||||
# * critical: optional critical threshold (in MB)
|
||||
# * refresh: interval in second between two refreshs
|
||||
#folder_1_path=/tmp
|
||||
#folder_1_careful=2500
|
||||
#folder_1_warning=3000
|
||||
#folder_1_critical=3500
|
||||
#folder_1_refresh=60
|
||||
#folder_2_path=/home/nicolargo/Videos
|
||||
#folder_2_warning=17000
|
||||
#folder_2_critical=20000
|
||||
#folder_3_path=/nonexisting
|
||||
#folder_4_path=/root
|
||||
|
||||
[raid]
|
||||
# Documentation: https://glances.readthedocs.io/en/stable/aoa/raid.html
|
||||
# This plugin is disabled by default
|
||||
disable=True
|
||||
|
||||
[smart]
|
||||
# Documentation: https://glances.readthedocs.io/en/stable/aoa/smart.html
|
||||
# This plugin is disabled by default
|
||||
disable=True
|
||||
|
||||
[hddtemp]
|
||||
disable=False
|
||||
# Define hddtemp server IP and port (default is 127.0.0.1 and 7634 (TCP))
|
||||
host=127.0.0.1
|
||||
port=7634
|
||||
|
||||
[sensors]
|
||||
# This plugin is disable by default because on some system, the PsUtil
|
||||
# consume a lot of CPU to grab the stats...
|
||||
disable=True
|
||||
# Sensors core thresholds (in Celsius...)
|
||||
# Default values if not defined: 60/70/80
|
||||
temperature_core_careful=60
|
||||
temperature_core_warning=70
|
||||
temperature_core_critical=80
|
||||
# Temperatures threshold in °C for hddtemp
|
||||
# Default values if not defined: 45/52/60
|
||||
temperature_hdd_careful=45
|
||||
temperature_hdd_warning=52
|
||||
temperature_hdd_critical=60
|
||||
# Battery threshold in %
|
||||
battery_careful=80
|
||||
battery_warning=90
|
||||
battery_critical=95
|
||||
# Sensors alias
|
||||
#temp1_alias=Motherboard 0
|
||||
#temp2_alias=Motherboard 1
|
||||
#core 0_alias=CPU Core 0
|
||||
#core 1_alias=CPU Core 1
|
||||
|
||||
[processlist]
|
||||
disable=False
|
||||
# Sort key: if not defined, the sort is automatically done by Glances (recommended)
|
||||
# Should be one of the following:
|
||||
# cpu_percent, memory_percent, io_counters, name, cpu_times, username
|
||||
#sort_key=memory_percent
|
||||
# Define CPU/MEM (per process) thresholds in %
|
||||
# Default values if not defined: 50/70/90
|
||||
cpu_careful=50
|
||||
cpu_warning=70
|
||||
cpu_critical=90
|
||||
mem_careful=50
|
||||
mem_warning=70
|
||||
mem_critical=90
|
||||
#
|
||||
# Nice priorities range from -20 to 19.
|
||||
# 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
|
||||
#
|
||||
# Nice: Example 2, low priority processes escalate from careful to critical
|
||||
#nice_careful=1,2,3,4,5,6,7,8,9
|
||||
#nice_warning=10,11,12,13,14
|
||||
#nice_critical=15,16,17,18,19
|
||||
|
||||
[ports]
|
||||
disable=False
|
||||
# Interval in second between two scans
|
||||
# Ports scanner plugin configuration
|
||||
refresh=30
|
||||
# Set the default timeout (in second) for a scan (can be overwritten in the scan list)
|
||||
timeout=3
|
||||
# If port_default_gateway is True, add the default gateway on top of the scan list
|
||||
port_default_gateway=True
|
||||
#
|
||||
# Define the scan list (1 < x < 255)
|
||||
# port_x_host (name or IP) is mandatory
|
||||
# port_x_port (TCP port number) is optional (if not set, use ICMP)
|
||||
# port_x_description is optional (if not set, define to host:port)
|
||||
# port_x_timeout is optional and overwrite the default timeout value
|
||||
# port_x_rtt_warning is optional and defines the warning threshold in ms
|
||||
#
|
||||
#port_1_host=192.168.0.1
|
||||
#port_1_port=80
|
||||
#port_1_description=Home Box
|
||||
#port_1_timeout=1
|
||||
#port_2_host=www.free.fr
|
||||
#port_2_description=My ISP
|
||||
#port_3_host=www.google.com
|
||||
#port_3_description=Internet ICMP
|
||||
#port_3_rtt_warning=1000
|
||||
#port_4_description=Internet Web
|
||||
#port_4_host=www.google.com
|
||||
#port_4_port=80
|
||||
#port_4_rtt_warning=1000
|
||||
#
|
||||
# Define Web (URL) monitoring list (1 < x < 255)
|
||||
# web_x_url is the URL to monitor (example: http://my.site.com/folder)
|
||||
# web_x_description is optional (if not set, define to URL)
|
||||
# web_x_timeout is optional and overwrite the default timeout value
|
||||
# web_x_rtt_warning is optional and defines the warning respond time in ms (approximatively)
|
||||
#
|
||||
#web_1_url=https://blog.nicolargo.com
|
||||
#web_1_description=My Blog
|
||||
#web_1_rtt_warning=3000
|
||||
#web_2_url=https://github.com
|
||||
#web_3_url=http://www.google.fr
|
||||
#web_3_description=Google Fr
|
||||
#web_4_url=https://blog.nicolargo.com/nonexist
|
||||
#web_4_description=Intranet
|
||||
|
||||
[docker]
|
||||
disable=False
|
||||
# Only show specific containers (comma separeted list of container name or regular expression)
|
||||
# Comment this line to display all containers (default configuration)
|
||||
#show=telegraf
|
||||
# Hide some containers (comma separeted list of container name or regular expression)
|
||||
# Comment this line to display all containers (default configuration)
|
||||
#hide=telegraf
|
||||
# Define the maximum docker size name (default is 20 chars)
|
||||
max_name_size=20
|
||||
#cpu_careful=50
|
||||
# Thresholds for CPU and MEM (in %)
|
||||
#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
|
||||
#
|
||||
# By default, Glances only display running containers
|
||||
# Set the following key to True to display all containers
|
||||
all=False
|
||||
|
||||
##############################################################################
|
||||
# Client/server
|
||||
##############################################################################
|
||||
|
||||
[serverlist]
|
||||
# Define the static servers list
|
||||
#server_1_name=localhost
|
||||
#server_1_alias=My local PC
|
||||
#server_1_port=61209
|
||||
#server_2_name=localhost
|
||||
#server_2_port=61235
|
||||
#server_3_name=192.168.0.17
|
||||
#server_3_alias=Another PC on my network
|
||||
#server_3_port=61209
|
||||
#server_4_name=pasbon
|
||||
#server_4_port=61237
|
||||
server_5_name=172.247.185.114
|
||||
server_5_port=10089
|
||||
|
||||
[passwords]
|
||||
# Define the passwords list
|
||||
# Syntax: host=password
|
||||
# Where: host is the hostname
|
||||
# password is the clear password
|
||||
# Additionally (and optionally) a default password could be defined
|
||||
#localhost=abc
|
||||
#default=defaultpassword
|
||||
|
||||
##############################################################################
|
||||
# Exports
|
||||
##############################################################################
|
||||
|
||||
[graph]
|
||||
# Configuration for the --export graph option
|
||||
# Set the path where the graph (.svg files) will be created
|
||||
# Can be overwrite by the --graph-path command line option
|
||||
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
|
||||
# See followings configuration keys definitions in the Pygal lib documentation
|
||||
# http://pygal.org/en/stable/documentation/index.html
|
||||
width=800
|
||||
height=600
|
||||
style=DarkStyle
|
||||
|
||||
[influxdb]
|
||||
# Configuration for the --export influxdb option
|
||||
# https://influxdb.com/
|
||||
host=localhost
|
||||
port=8086
|
||||
protocol=http
|
||||
user=root
|
||||
password=root
|
||||
db=glances
|
||||
# Prefix will be added for all measurement name
|
||||
# Ex: prefix=foo
|
||||
# => foo.cpu
|
||||
# => foo.mem
|
||||
# You can also use dynamic values
|
||||
#prefix=`hostname`
|
||||
prefix=localhost
|
||||
# Tags will be added for all measurements
|
||||
#tags=foo:bar,spam:eggs
|
||||
# You can also use dynamic values
|
||||
#tags=system:`uname -s`
|
||||
|
||||
[cassandra]
|
||||
# Configuration for the --export cassandra option
|
||||
# Also works for the ScyllaDB
|
||||
# https://influxdb.com/ or http://www.scylladb.com/
|
||||
host=localhost
|
||||
port=9042
|
||||
protocol_version=3
|
||||
keyspace=glances
|
||||
replication_factor=2
|
||||
# If not define, table name is set to host key
|
||||
table=localhost
|
||||
# If not define, username and password will not be used
|
||||
#username=cassandra
|
||||
#password=password
|
||||
|
||||
[opentsdb]
|
||||
# Configuration for the --export opentsdb option
|
||||
# http://opentsdb.net/
|
||||
host=localhost
|
||||
port=4242
|
||||
#prefix=glances
|
||||
#tags=foo:bar,spam:eggs
|
||||
|
||||
[statsd]
|
||||
# Configuration for the --export statsd option
|
||||
# https://github.com/etsy/statsd
|
||||
host=localhost
|
||||
port=8125
|
||||
#prefix=glances
|
||||
|
||||
[elasticsearch]
|
||||
# Configuration for the --export elasticsearch option
|
||||
# Data are available via the ES RESTful API. ex: URL/<index>/cpu/system
|
||||
# https://www.elastic.co
|
||||
host=localhost
|
||||
port=9200
|
||||
index=glances
|
||||
|
||||
[riemann]
|
||||
# Configuration for the --export riemann option
|
||||
# http://riemann.io
|
||||
host=localhost
|
||||
port=5555
|
||||
|
||||
[rabbitmq]
|
||||
# Configuration for the --export rabbitmq option
|
||||
host=localhost
|
||||
port=5672
|
||||
user=guest
|
||||
password=guest
|
||||
queue=glances_queue
|
||||
#protocol=amqps
|
||||
|
||||
[mqtt]
|
||||
# Configuration for the --export mqtt option
|
||||
host=localhost
|
||||
port=8883
|
||||
user=guest
|
||||
password=guest
|
||||
topic=glances
|
||||
tls=true
|
||||
|
||||
[couchdb]
|
||||
# Configuration for the --export couchdb option
|
||||
# https://www.couchdb.org
|
||||
host=localhost
|
||||
port=5984
|
||||
db=glances
|
||||
# user and password are optional (comment if not configured on the server side)
|
||||
#user=root
|
||||
#password=root
|
||||
|
||||
[kafka]
|
||||
# Configuration for the --export kafka option
|
||||
# http://kafka.apache.org/
|
||||
host=localhost
|
||||
port=9092
|
||||
topic=glances
|
||||
#compression=gzip
|
||||
# Tags will be added for all events
|
||||
#tags=foo:bar,spam:eggs
|
||||
# You can also use dynamic values
|
||||
#tags=hostname:`hostname -f`
|
||||
|
||||
[zeromq]
|
||||
# Configuration for the --export zeromq option
|
||||
# http://www.zeromq.org
|
||||
# Use * to bind on all interfaces
|
||||
host=*
|
||||
port=5678
|
||||
# Glances envelopes the stats in a publish message with two frames:
|
||||
# - First frame containing the following prefix (STRING)
|
||||
# - Second frame with the Glances plugin name (STRING)
|
||||
# - Third frame with the Glances plugin stats (JSON)
|
||||
prefix=G
|
||||
|
||||
[prometheus]
|
||||
# Configuration for the --export prometheus option
|
||||
# https://prometheus.io
|
||||
# Create a Prometheus exporter listening on localhost:9091 (default configuration)
|
||||
# Metric are exporter using the following name:
|
||||
# <prefix>_<plugin>_<stats>{labelkey:labelvalue}
|
||||
# Note: You should add this exporter to your Prometheus server configuration:
|
||||
# scrape_configs:
|
||||
# - job_name: 'glances_exporter'
|
||||
# scrape_interval: 5s
|
||||
# static_configs:
|
||||
# - targets: ['localhost:9091']
|
||||
#
|
||||
# Labels will be added for all measurements (default is src:glances)
|
||||
# labels=foo:bar,spam:eggs
|
||||
# You can also use dynamic values
|
||||
# labels=system:`uname -s`
|
||||
#
|
||||
host=localhost
|
||||
port=9091
|
||||
#prefix=glances
|
||||
labels=src:glances
|
||||
|
||||
[restful]
|
||||
# Configuration for the --export restful option
|
||||
# Example, export to http://localhost:6789/
|
||||
host=localhost
|
||||
port=6789
|
||||
protocol=http
|
||||
path=/
|
||||
|
||||
##############################################################################
|
||||
# AMPS
|
||||
# * enable: Enable (true) or disable (false) the AMP
|
||||
# * regex: Regular expression to filter the process(es)
|
||||
# * refresh: The AMP is executed every refresh seconds
|
||||
# * one_line: (optional) Force (if true) the AMP to be displayed in one line
|
||||
# * command: (optional) command to execute when the process is detected (thk to the regex)
|
||||
# * countmin: (optional) minimal number of processes
|
||||
# A warning will be displayed if number of process < count
|
||||
# * countmax: (optional) maximum number of processes
|
||||
# A warning will be displayed if number of process > count
|
||||
# * <foo>: Others variables can be defined and used in the AMP script
|
||||
##############################################################################
|
||||
|
||||
[amp_dropbox]
|
||||
# Use the default AMP (no dedicated AMP Python script)
|
||||
# Check if the Dropbox daemon is running
|
||||
# Every 3 seconds, display the 'dropbox status' command line
|
||||
enable=false
|
||||
regex=.*dropbox.*
|
||||
refresh=3
|
||||
one_line=false
|
||||
command=dropbox status
|
||||
countmin=1
|
||||
|
||||
[amp_python]
|
||||
# Use the default AMP (no dedicated AMP Python script)
|
||||
# Monitor all the Python scripts
|
||||
# Alert if more than 20 Python scripts are running
|
||||
enable=false
|
||||
regex=.*python.*
|
||||
refresh=3
|
||||
countmax=20
|
||||
|
||||
[amp_conntrack]
|
||||
# Use comma separated for multiple commands (no space around the comma)
|
||||
# If the regex key is not defined, the AMP will be executed every refresh second
|
||||
# and the process count will not be displayed (countmin and countmax will be ignore)
|
||||
enable=false
|
||||
refresh=30
|
||||
one_line=false
|
||||
command=sysctl net.netfilter.nf_conntrack_count;sysctl net.netfilter.nf_conntrack_max
|
||||
|
||||
[amp_nginx]
|
||||
# Use the NGinx AMP
|
||||
# Nginx status page should be enable (https://easyengine.io/tutorials/nginx/status-page/)
|
||||
enable=false
|
||||
regex=\/usr\/sbin\/nginx
|
||||
refresh=60
|
||||
one_line=false
|
||||
status_url=http://localhost/nginx_status
|
||||
|
||||
[amp_systemd]
|
||||
# Use the Systemd AMP
|
||||
enable=false
|
||||
regex=\/lib\/systemd\/systemd
|
||||
refresh=30
|
||||
one_line=true
|
||||
systemctl_cmd=/bin/systemctl --plain
|
||||
|
||||
[amp_systemv]
|
||||
# Use the Systemv AMP
|
||||
enable=false
|
||||
regex=\/sbin\/init
|
||||
refresh=30
|
||||
one_line=true
|
||||
service_cmd=/usr/bin/service --status-all
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# Glances Dockerfile (based on Ubuntu)
|
||||
#
|
||||
# https://github.com/nicolargo/glances
|
||||
#
|
||||
|
||||
ARG ARCH=
|
||||
FROM ${ARCH}python:3-slim-buster
|
||||
|
||||
# Install package
|
||||
# Must used calibre package to be able to run external module
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y \
|
||||
curl \
|
||||
gcc \
|
||||
lm-sensors \
|
||||
wireless-tools \
|
||||
iputils-ping && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Force rebuild otherwise it could be cached without rerun
|
||||
ARG VCS_REF
|
||||
RUN pip install glances[all]
|
||||
|
||||
# Define working directory.
|
||||
WORKDIR /glances
|
||||
|
||||
# EXPOSE PORT (XMLRPC / WebUI)
|
||||
EXPOSE 61209 61208
|
||||
|
||||
# Define default command.
|
||||
CMD python3 -m glances -C /glances/conf/glances.conf $GLANCES_OPT
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#
|
||||
# Glances Dockerfile (based on Ubuntu)
|
||||
#
|
||||
# https://github.com/nicolargo/glances
|
||||
#
|
||||
|
||||
ARG ARCH=
|
||||
FROM ${ARCH}python:3-buster
|
||||
|
||||
# Install package
|
||||
# Must used calibre package to be able to run external module
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y \
|
||||
curl \
|
||||
gcc \
|
||||
git \
|
||||
lm-sensors \
|
||||
wireless-tools \
|
||||
iputils-ping && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pip install psutil bottle
|
||||
|
||||
# Define working directory
|
||||
WORKDIR /glances
|
||||
|
||||
COPY *requirements.txt .
|
||||
|
||||
RUN CASS_DRIVER_NO_CYTHON=1 pip install -r optional-requirements.txt
|
||||
|
||||
COPY . /glances
|
||||
|
||||
# EXPOSE PORT (XMLRPC / WebUI)
|
||||
EXPOSE 61209 61208
|
||||
|
||||
# Define default command.
|
||||
CMD python3 -m glances -C /glances/conf/glances.conf $GLANCES_OPT
|
||||
|
|
@ -8,8 +8,7 @@
|
|||
FROM alpine
|
||||
|
||||
# Install Glances (develop branch)
|
||||
RUN apk add python py2-psutil py2-bottle
|
||||
RUN apk add git
|
||||
RUN apk add python3 py3-psutil py3-bottle docker-py git
|
||||
RUN git clone -b develop https://github.com/nicolargo/glances.git
|
||||
|
||||
# Define working directory.
|
||||
|
|
@ -22,4 +21,4 @@ EXPOSE 61209
|
|||
EXPOSE 61208
|
||||
|
||||
# Define default command.
|
||||
CMD python -m glances -C /glances/conf/glances.conf $GLANCES_OPT
|
||||
CMD /usr/bin/python3 -m glances -C /glances/conf/glances.conf $GLANCES_OPT
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
#
|
||||
# Glances Dockerfile for ARM (based on Alpine ARM)
|
||||
#
|
||||
# https://github.com/nicolargo/glances
|
||||
#
|
||||
|
||||
# Pull base image.
|
||||
FROM python:2.7-alpine
|
||||
|
||||
# Install Glances (develop branch)
|
||||
RUN apk add --no-cache --virtual .build_deps \
|
||||
gcc \
|
||||
musl-dev \
|
||||
linux-headers \
|
||||
git \
|
||||
&& git clone -b develop https://github.com/nicolargo/glances.git \
|
||||
&& pip install --no-cache-dir -r glances/requirements.txt bottle \
|
||||
&& apk del .build_deps
|
||||
|
||||
# Define working directory.
|
||||
WORKDIR /glances
|
||||
|
||||
# EXPOSE PORT (For Web UI & XMLRPC)
|
||||
EXPOSE 61208 61209
|
||||
|
||||
# Define default command.
|
||||
CMD python -m glances -C /glances/conf/glances.conf $GLANCES_OPT
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
#
|
||||
# Glances Dockerfile based on Ubuntu OS
|
||||
#
|
||||
# https://github.com/nicolargo/glances
|
||||
#
|
||||
|
||||
# Pull base image.
|
||||
FROM ubuntu:20.04
|
||||
|
||||
# Install Glances (develop branch)
|
||||
RUN apt-get update && apt-get -y install curl iputils-ping && rm -rf /var/lib/apt/lists/*
|
||||
RUN curl -L https://raw.githubusercontent.com/nicolargo/glancesautoinstall/master/install-develop.sh | /bin/bash && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
# Define working directory.
|
||||
WORKDIR /glances
|
||||
|
||||
# EXPOSE PORT (For XMLRPC)
|
||||
EXPOSE 61209
|
||||
|
||||
# EXPOSE PORT (For Web UI)
|
||||
EXPOSE 61208
|
||||
|
||||
# Define default command.
|
||||
CMD python -m glances -C /glances/conf/glances.conf $GLANCES_OPT
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#
|
||||
# Glances Dockerfile (based on Ubuntu)
|
||||
#
|
||||
# https://github.com/nicolargo/glances
|
||||
#
|
||||
|
||||
# Pull base image.
|
||||
FROM ubuntu:20.04
|
||||
|
||||
|
||||
# Install package
|
||||
# Must used calibre package to be able to run external module
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y \
|
||||
curl \
|
||||
gcc \
|
||||
lm-sensors \
|
||||
wireless-tools \
|
||||
iputils-ping \
|
||||
python3-pip \
|
||||
python3-dev && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
## Instal glances
|
||||
RUN \
|
||||
pip3 install --upgrade pip && \
|
||||
pip3 install setuptools \
|
||||
glances[action,batinfo,browser,cpuinfo,docker,export,folders,gpu,graph,ip,raid,snmp,web,wifi] \
|
||||
glances
|
||||
|
||||
# Define working directory.
|
||||
WORKDIR /glances
|
||||
|
||||
# EXPOSE PORT (For XMLRPC)
|
||||
EXPOSE 61209
|
||||
|
||||
# EXPOSE PORT (For Web UI)
|
||||
EXPOSE 61208
|
||||
|
||||
# Define default command.
|
||||
CMD python3 -m glances -C /glances/conf/glances.conf $GLANCES_OPT
|
||||
|
|
@ -20,6 +20,13 @@ under the ``[docker]`` section:
|
|||
.. code-block:: ini
|
||||
|
||||
[docker]
|
||||
disable=False
|
||||
# Only show specific containers (comma separeted list of container name or regular expression)
|
||||
show=thiscontainer,andthisone,andthoseones.*
|
||||
# Hide some containers (comma separeted list of container name or regular expression)
|
||||
hide=donotshowthisone,andthose.*
|
||||
# Define the maximum docker size name (default is 20 chars)
|
||||
max_name_size=20
|
||||
# Global containers' thresholds for CPU and MEM (in %)
|
||||
cpu_careful=50
|
||||
cpu_warning=70
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ User disk space usage Status
|
|||
|
||||
By default, the plugin only displays physical devices (hard disks, USB
|
||||
keys). To allow other file system types, you have to enable them in the
|
||||
configuration file. For example, if you want to allow the ``zfs`` file
|
||||
configuration file. For example, if you want to allow the ``shm`` file
|
||||
system:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[fs]
|
||||
allow=zfs
|
||||
allow=shm
|
||||
|
||||
Also, you can hide mount points as well (in the following ``/boot``):
|
||||
|
||||
|
|
|
|||
|
|
@ -128,6 +128,9 @@ The extended stats feature can be enabled using the
|
|||
``--enable-process-extended`` option (command line) or the ``e`` key
|
||||
(curses interface).
|
||||
|
||||
In curses/standalone mode, you can select a process using ``UP`` and ``DOWN`` and press:
|
||||
- ``k`` to kill the selected process
|
||||
|
||||
.. note::
|
||||
Limit for CPU and MEM percent values can be overwritten in the
|
||||
configuration file under the ``[processlist]`` section. It is also
|
||||
|
|
|
|||
|
|
@ -18,3 +18,6 @@ There is no alert on this information.
|
|||
|
||||
.. note::
|
||||
This plugin is disabled by default in the configuration file.
|
||||
To enable it just use the following option:
|
||||
|
||||
# glances --enable-plugin sensors
|
||||
|
|
|
|||
|
|
@ -375,6 +375,8 @@ The following commands (key pressed) are supported while in Glances:
|
|||
Enable/disable mean GPU mode
|
||||
``/``
|
||||
Switch between process command line or command name
|
||||
``F5``
|
||||
Refresh stats in curses user interface
|
||||
|
||||
In the Glances client browser (accessible through the ``--browser``
|
||||
command line argument):
|
||||
|
|
|
|||
|
|
@ -54,7 +54,10 @@ master_doc = 'index'
|
|||
# General information about the project.
|
||||
project = 'Glances'
|
||||
author = 'Nicolas Hennion'
|
||||
year = datetime.now().year
|
||||
try:
|
||||
year = datetime.utcfromtimestamp(int(os.environ['SOURCE_DATE_EPOCH'])).year
|
||||
except (KeyError, ValueError):
|
||||
year = datetime.now().year
|
||||
copyright = '%d, %s' % (year, author)
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ Location
|
|||
You can put your own ``glances.conf`` file in the following locations:
|
||||
|
||||
==================== =============================================================
|
||||
``Linux``, ``SunOS`` ~/.config/glances, /etc/glances
|
||||
``*BSD`` ~/.config/glances, /usr/local/etc/glances
|
||||
``macOS`` ~/Library/Application Support/glances, /usr/local/etc/glances
|
||||
``Windows`` %APPDATA%\\glances
|
||||
``Linux``, ``SunOS`` ~/.config/glances/glances.conf, /etc/glances/glances.conf
|
||||
``*BSD`` ~/.config/glances/glances.conf, /usr/local/etc/glances/glances.conf
|
||||
``macOS`` ~/Library/Application Support/glances/glances.conf, /usr/local/etc/glances/glances.conf
|
||||
``Windows`` %APPDATA%\\glances\glances.conf
|
||||
==================== =============================================================
|
||||
|
||||
- On Windows XP, ``%APPDATA%`` is: ``C:\Documents and Settings\<USERNAME>\Application Data``.
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ which will prompt you to answer the following questions:
|
|||
after which you will need to kill the process by entering ``CTRL+C`` (potentially twice), before leaving the container:
|
||||
|
||||
.. code-block:: console
|
||||
^C^C
|
||||
exit
|
||||
|
||||
You will then need to copy the password file to your host machine:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ InfluxDB
|
|||
========
|
||||
|
||||
You can export statistics to an ``InfluxDB`` server (time series server).
|
||||
|
||||
InfluxDB (up to version 1.7.x)
|
||||
------------------------------
|
||||
|
||||
The connection should be defined in the Glances configuration file as
|
||||
following:
|
||||
|
||||
|
|
@ -16,6 +20,13 @@ following:
|
|||
user=root
|
||||
password=root
|
||||
db=glances
|
||||
# Prefix will be added for all measurement name
|
||||
# Ex: prefix=foo
|
||||
# => foo.cpu
|
||||
# => foo.mem
|
||||
# You can also use dynamic values
|
||||
#prefix=`hostname`
|
||||
prefix=localhost
|
||||
# Tags will be added for all measurements
|
||||
#tags=foo:bar,spam:eggs
|
||||
# You can also use dynamic values
|
||||
|
|
@ -33,6 +44,45 @@ configuration file (no limit on columns number).
|
|||
|
||||
Note: if you want to use SSL, please set 'protocol=https'.
|
||||
|
||||
|
||||
InfluxDB v2 (from InfluxDB v1.8.x/Flux and InfluxDB v2.x)
|
||||
---------------------------------------------------------
|
||||
|
||||
Note: The InfluxDB v2 client (https://pypi.org/project/influxdb-client/)
|
||||
is only available for Python 3.6 or higher.
|
||||
|
||||
The connection should be defined in the Glances configuration file as
|
||||
following:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[influxdb]
|
||||
host=localhost
|
||||
port=8086
|
||||
protocol=http
|
||||
org=nicolargo
|
||||
bucket=glances
|
||||
token=EjFUTWe8U-MIseEAkaVIgVnej_TrnbdvEcRkaB1imstW7gapSqy6_6-8XD-yd51V0zUUpDy-kAdVD1purDLuxA==
|
||||
# Prefix will be added for all measurement name
|
||||
# Ex: prefix=foo
|
||||
# => foo.cpu
|
||||
# => foo.mem
|
||||
# You can also use dynamic values
|
||||
#prefix=`hostname`
|
||||
prefix=localhost
|
||||
# Tags will be added for all measurements
|
||||
#tags=foo:bar,spam:eggs
|
||||
# You can also use dynamic values
|
||||
#tags=system:`uname -s`
|
||||
|
||||
and run Glances with:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ glances --export influxdb2
|
||||
|
||||
Note: if you want to use SSL, please set 'protocol=https'.
|
||||
|
||||
Grafana
|
||||
-------
|
||||
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ JSON
|
|||
It's possible to export stats to a JSON file.
|
||||
|
||||
.. code-block:: console
|
||||
$ glances --export json --export-json-file /tmp/glances.json
|
||||
|
||||
$ glances --export json --export-json-file json /tmp/glances.json
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ following:
|
|||
user=glances
|
||||
password=glances
|
||||
queue=glances_queue
|
||||
#protocol=amqps
|
||||
|
||||
and run Glances with:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "GLANCES" "1" "Aug 19, 2020" "3.1.5" "Glances"
|
||||
.TH "GLANCES" "1" "Jan 23, 2021" "3.1.6" "Glances"
|
||||
.SH NAME
|
||||
glances \- An eye on your system
|
||||
.
|
||||
|
|
@ -479,6 +479,9 @@ Enable/disable mean GPU mode
|
|||
.TP
|
||||
.B \fB/\fP
|
||||
Switch between process command line or command name
|
||||
.TP
|
||||
.B \fBF5\fP
|
||||
Refresh stats in curses user interface
|
||||
.UNINDENT
|
||||
.sp
|
||||
In the Glances client browser (accessible through the \fB\-\-browser\fP
|
||||
|
|
@ -520,25 +523,25 @@ _
|
|||
T{
|
||||
\fBLinux\fP, \fBSunOS\fP
|
||||
T} T{
|
||||
~/.config/glances, /etc/glances
|
||||
~/.config/glances/glances.conf, /etc/glances/glances.conf
|
||||
T}
|
||||
_
|
||||
T{
|
||||
\fB*BSD\fP
|
||||
T} T{
|
||||
~/.config/glances, /usr/local/etc/glances
|
||||
~/.config/glances/glances.conf, /usr/local/etc/glances/glances.conf
|
||||
T}
|
||||
_
|
||||
T{
|
||||
\fBmacOS\fP
|
||||
T} T{
|
||||
~/Library/Application Support/glances, /usr/local/etc/glances
|
||||
~/Library/Application Support/glances/glances.conf, /usr/local/etc/glances/glances.conf
|
||||
T}
|
||||
_
|
||||
T{
|
||||
\fBWindows\fP
|
||||
T} T{
|
||||
%APPDATA%\eglances
|
||||
%APPDATA%\eglancesglances.conf
|
||||
T}
|
||||
_
|
||||
.TE
|
||||
|
|
@ -838,6 +841,6 @@ $ glances –browser
|
|||
.sp
|
||||
Nicolas Hennion aka Nicolargo <\fI\%contact@nicolargo.com\fP>
|
||||
.SH COPYRIGHT
|
||||
2020, Nicolas Hennion
|
||||
2021, Nicolas Hennion
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ import signal
|
|||
import sys
|
||||
|
||||
# Global name
|
||||
__version__ = '3.1.5'
|
||||
# Version should start and end with a numerical char
|
||||
# See https://packaging.python.org/specifications/core-metadata/#version
|
||||
__version__ = '3.1.6'
|
||||
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
|
||||
__license__ = 'LGPLv3'
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,11 @@ class Config(object):
|
|||
# Re patern for optimize research of `foo`
|
||||
self.re_pattern = re.compile(r'(\`.+?\`)')
|
||||
|
||||
self.parser = ConfigParser()
|
||||
try:
|
||||
self.parser = ConfigParser(interpolation=None)
|
||||
except TypeError:
|
||||
self.parser = ConfigParser()
|
||||
|
||||
self.read()
|
||||
|
||||
def config_file_paths(self):
|
||||
|
|
@ -153,6 +157,16 @@ class Config(object):
|
|||
self._loaded_config_file = config_file
|
||||
break
|
||||
|
||||
# Globals
|
||||
if not self.parser.has_section('global'):
|
||||
self.parser.add_section('global')
|
||||
self.set_default('global', 'strftime_format', '')
|
||||
|
||||
# check_update
|
||||
if not self.parser.has_section('global'):
|
||||
self.parser.add_section('global')
|
||||
self.set_default('global', 'check_update', 'false')
|
||||
|
||||
# Quicklook
|
||||
if not self.parser.has_section('quicklook'):
|
||||
self.parser.add_section('quicklook')
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""InfluxDB interface class."""
|
||||
"""InfluxDB (up to InfluxDB 1.7.x) interface class."""
|
||||
|
||||
import sys
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# Copyright (C) 2020 Nicolargo <nicolas@nicolargo.com>
|
||||
#
|
||||
# Glances is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Glances is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""InfluxDB (from to InfluxDB 1.8+) interface class."""
|
||||
|
||||
import sys
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
|
||||
from influxdb_client import InfluxDBClient, WriteOptions
|
||||
|
||||
|
||||
class Export(GlancesExport):
|
||||
"""This class manages the InfluxDB export module."""
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the InfluxDB export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
|
||||
# Mandatories configuration keys (additional to host and port)
|
||||
self.org = None
|
||||
self.bucket = None
|
||||
self.token = None
|
||||
|
||||
# Optionals configuration keys
|
||||
self.protocol = 'http'
|
||||
self.prefix = None
|
||||
self.tags = None
|
||||
|
||||
# Load the InfluxDB configuration file
|
||||
self.export_enable = self.load_conf('influxdb2',
|
||||
mandatories=['host', 'port',
|
||||
'user', 'password',
|
||||
'org', 'bucket', 'token'],
|
||||
options=['protocol',
|
||||
'prefix',
|
||||
'tags'])
|
||||
if not self.export_enable:
|
||||
sys.exit(2)
|
||||
|
||||
# Init the InfluxDB client
|
||||
self.client = self.init()
|
||||
|
||||
def init(self):
|
||||
"""Init the connection to the InfluxDB server."""
|
||||
if not self.export_enable:
|
||||
return None
|
||||
|
||||
url = '{}://{}:{}'.format(self.protocol, self.host, self.port)
|
||||
try:
|
||||
client = InfluxDBClient(url=url,
|
||||
enable_gzip=False,
|
||||
org=self.org,
|
||||
token=self.token)
|
||||
except Exception as e:
|
||||
logger.critical("Cannot connect to InfluxDB server '%s' (%s)" % (url, e))
|
||||
sys.exit(2)
|
||||
else:
|
||||
logger.info("Connected to InfluxDB server version {} ({})".format(client.health().version,
|
||||
client.health().message))
|
||||
|
||||
|
||||
# Create the write client
|
||||
write_client = client.write_api(write_options=WriteOptions(batch_size=500,
|
||||
flush_interval=10000,
|
||||
jitter_interval=2000,
|
||||
retry_interval=5000,
|
||||
max_retries=5,
|
||||
max_retry_delay=30000,
|
||||
exponential_base=2))
|
||||
return write_client
|
||||
|
||||
def _normalize(self, name, columns, points):
|
||||
"""Normalize data for the InfluxDB's data model."""
|
||||
|
||||
for i, _ in enumerate(points):
|
||||
# Supported type:
|
||||
# https://docs.influxdata.com/influxdb/v2.0/reference/syntax/line-protocol/
|
||||
if points[i] is None:
|
||||
# Ignore points with None value
|
||||
del(points[i])
|
||||
del(columns[i])
|
||||
continue
|
||||
try:
|
||||
points[i] = float(points[i])
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
else:
|
||||
continue
|
||||
try:
|
||||
points[i] = str(points[i])
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
else:
|
||||
continue
|
||||
|
||||
return [{'measurement': name,
|
||||
'tags': self.parse_tags(self.tags),
|
||||
'fields': dict(zip(columns, points))}]
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Write the points to the InfluxDB server."""
|
||||
# Manage prefix
|
||||
if self.prefix is not None:
|
||||
name = self.prefix + '.' + name
|
||||
# Write input to the InfluxDB database
|
||||
if len(points) == 0:
|
||||
logger.debug("Cannot export empty {} stats to InfluxDB".format(name))
|
||||
else:
|
||||
try:
|
||||
self.client.write(self.bucket,
|
||||
self.org,
|
||||
self._normalize(name, columns, points),
|
||||
time_precision="s")
|
||||
except Exception as e:
|
||||
# Log level set to debug instead of error (see: issue #1561)
|
||||
logger.debug("Cannot export {} stats to InfluxDB ({})".format(name, e))
|
||||
else:
|
||||
logger.debug("Export {} stats to InfluxDB".format(name))
|
||||
|
|
@ -254,6 +254,9 @@ Examples of use:
|
|||
# Globals options
|
||||
parser.add_argument('--disable-check-update', action='store_true', default=False,
|
||||
dest='disable_check_update', help='disable online Glances version ckeck')
|
||||
parser.add_argument('--strftime', dest='strftime_format', default='',
|
||||
help='strftime format string for displaying current date in standalone mode')
|
||||
|
||||
return parser
|
||||
|
||||
def parse_args(self):
|
||||
|
|
@ -419,6 +422,13 @@ Examples of use:
|
|||
disable(args, 'hddtemp')
|
||||
logger.debug("Sensors and HDDTemp are disabled")
|
||||
|
||||
# Let the plugins known the Glances mode
|
||||
self.args.is_standalone = self.is_standalone()
|
||||
self.args.is_client = self.is_client()
|
||||
self.args.is_client_browser = self.is_client_browser()
|
||||
self.args.is_server = self.is_server()
|
||||
self.args.is_webserver = self.is_webserver()
|
||||
|
||||
return args
|
||||
|
||||
def is_standalone(self):
|
||||
|
|
|
|||
|
|
@ -50,10 +50,13 @@ class _GlancesCurses(object):
|
|||
"""
|
||||
|
||||
_hotkeys = {
|
||||
# 'ENTER' > Edit the process filter
|
||||
'0': {'switch': 'disable_irix'},
|
||||
'1': {'switch': 'percpu'},
|
||||
'2': {'switch': 'disable_left_sidebar'},
|
||||
'3': {'switch': 'disable_quicklook'},
|
||||
# '4' > Enable or disable quicklook
|
||||
# '5' > Enable or disable top menu
|
||||
'6': {'switch': 'meangpu'},
|
||||
'/': {'switch': 'process_short_name'},
|
||||
'a': {'sort_key': 'auto'},
|
||||
|
|
@ -64,13 +67,17 @@ class _GlancesCurses(object):
|
|||
'C': {'switch': 'disable_cloud'},
|
||||
'd': {'switch': 'disable_diskio'},
|
||||
'D': {'switch': 'disable_docker'},
|
||||
# 'e' > Enable/Disable process extended
|
||||
# 'E' > Erase the process filter
|
||||
# 'f' > Show/hide fs / folder stats
|
||||
'F': {'switch': 'fs_free_space'},
|
||||
'g': {'switch': 'generate_graph'},
|
||||
'G': {'switch': 'disable_gpu'},
|
||||
'h': {'switch': 'help_tag'},
|
||||
'i': {'sort_key': 'io_counters'},
|
||||
'I': {'switch': 'disable_ip'},
|
||||
'k': {'switch': 'disable_connections'},
|
||||
# 'k' > Kill selected process
|
||||
'K': {'switch': 'disable_connections'},
|
||||
'l': {'switch': 'disable_alert'},
|
||||
'm': {'sort_key': 'memory_percent'},
|
||||
'M': {'switch': 'reset_minmax_tag'},
|
||||
|
|
@ -78,6 +85,7 @@ class _GlancesCurses(object):
|
|||
'N': {'switch': 'disable_now'},
|
||||
'p': {'sort_key': 'name'},
|
||||
'P': {'switch': 'disable_ports'},
|
||||
# 'q' or ESCAPE > Quit
|
||||
'Q': {'switch': 'enable_irq'},
|
||||
'r': {'switch': 'disable_smart'},
|
||||
'R': {'switch': 'disable_raid'},
|
||||
|
|
@ -87,7 +95,14 @@ class _GlancesCurses(object):
|
|||
'T': {'switch': 'network_sum'},
|
||||
'u': {'sort_key': 'username'},
|
||||
'U': {'switch': 'network_cumul'},
|
||||
# 'w' > Delete finished warning logs
|
||||
'W': {'switch': 'disable_wifi'},
|
||||
# 'x' > Delete finished warning and critical logs
|
||||
# 'z' > Enable or disable processes
|
||||
# "<" (left arrow) navigation through process sort
|
||||
# ">" (right arrow) navigation through process sort
|
||||
# 'UP' > Up in the server list
|
||||
# 'DOWN' > Down in the server list
|
||||
}
|
||||
|
||||
_sort_loop = ['cpu_percent', 'memory_percent', 'username',
|
||||
|
|
@ -144,9 +159,15 @@ class _GlancesCurses(object):
|
|||
# Init edit filter tag
|
||||
self.edit_filter = False
|
||||
|
||||
# Init kill process tag
|
||||
self.kill_process = False
|
||||
|
||||
# Init the process min/max reset
|
||||
self.args.reset_minmax_tag = False
|
||||
|
||||
# Init cursor
|
||||
self.args.cursor_position = 0
|
||||
|
||||
# Catch key pressed with non blocking mode
|
||||
self.term_window.keypad(1)
|
||||
self.term_window.nodelay(1)
|
||||
|
|
@ -188,6 +209,8 @@ class _GlancesCurses(object):
|
|||
try:
|
||||
if hasattr(curses, 'start_color'):
|
||||
curses.start_color()
|
||||
logger.debug(
|
||||
'Curses interface compatible with {} colors'.format(curses.COLORS))
|
||||
if hasattr(curses, 'use_default_colors'):
|
||||
curses.use_default_colors()
|
||||
except Exception as e:
|
||||
|
|
@ -226,35 +249,35 @@ class _GlancesCurses(object):
|
|||
curses.init_pair(8, curses.COLOR_BLUE, -1)
|
||||
|
||||
# Colors text styles
|
||||
if curses.COLOR_PAIRS > 8:
|
||||
try:
|
||||
curses.init_pair(9, curses.COLOR_MAGENTA, -1)
|
||||
except Exception:
|
||||
if self.is_theme('white'):
|
||||
curses.init_pair(9, curses.COLOR_BLACK, -1)
|
||||
else:
|
||||
curses.init_pair(9, curses.COLOR_WHITE, -1)
|
||||
try:
|
||||
curses.init_pair(10, curses.COLOR_CYAN, -1)
|
||||
except Exception:
|
||||
if self.is_theme('white'):
|
||||
curses.init_pair(10, curses.COLOR_BLACK, -1)
|
||||
else:
|
||||
curses.init_pair(10, curses.COLOR_WHITE, -1)
|
||||
|
||||
self.ifWARNING_color2 = curses.color_pair(9) | A_BOLD
|
||||
self.ifCRITICAL_color2 = curses.color_pair(6) | A_BOLD
|
||||
self.filter_color = curses.color_pair(10) | A_BOLD
|
||||
|
||||
self.no_color = curses.color_pair(1)
|
||||
self.default_color = curses.color_pair(3) | A_BOLD
|
||||
self.nice_color = curses.color_pair(9)
|
||||
self.cpu_time_color = curses.color_pair(9)
|
||||
self.nice_color = curses.color_pair(5)
|
||||
self.cpu_time_color = curses.color_pair(5)
|
||||
self.ifCAREFUL_color = curses.color_pair(4) | A_BOLD
|
||||
self.ifWARNING_color = curses.color_pair(5) | A_BOLD
|
||||
self.ifCRITICAL_color = curses.color_pair(2) | A_BOLD
|
||||
self.default_color2 = curses.color_pair(7)
|
||||
self.ifCAREFUL_color2 = curses.color_pair(8) | A_BOLD
|
||||
self.ifWARNING_color2 = curses.color_pair(5) | A_BOLD
|
||||
self.ifCRITICAL_color2 = curses.color_pair(6) | A_BOLD
|
||||
self.filter_color = A_BOLD
|
||||
self.selected_color = A_BOLD
|
||||
|
||||
if curses.COLOR_PAIRS > 8:
|
||||
colors_list = [curses.COLOR_MAGENTA, curses.COLOR_CYAN, curses.COLOR_YELLOW]
|
||||
for i in range(0, 3):
|
||||
try:
|
||||
curses.init_pair(i + 9, colors_list[i], -1)
|
||||
except Exception:
|
||||
if self.is_theme('white'):
|
||||
curses.init_pair(i + 9, curses.COLOR_BLACK, -1)
|
||||
else:
|
||||
curses.init_pair(i + 9, curses.COLOR_WHITE, -1)
|
||||
self.nice_color = curses.color_pair(9)
|
||||
self.cpu_time_color = curses.color_pair(9)
|
||||
self.ifWARNING_color2 = curses.color_pair(9) | A_BOLD
|
||||
self.filter_color = curses.color_pair(10) | A_BOLD
|
||||
self.selected_color = curses.color_pair(11) | A_BOLD
|
||||
|
||||
else:
|
||||
# The screen is NOT compatible with a colored design
|
||||
|
|
@ -271,6 +294,7 @@ class _GlancesCurses(object):
|
|||
self.ifWARNING_color2 = A_BOLD
|
||||
self.ifCRITICAL_color2 = curses.A_REVERSE
|
||||
self.filter_color = A_BOLD
|
||||
self.selected_color = A_BOLD
|
||||
|
||||
# Define the colors list (hash table) for stats
|
||||
self.colors_list = {
|
||||
|
|
@ -283,6 +307,7 @@ class _GlancesCurses(object):
|
|||
'FILTER': self.filter_color,
|
||||
'TITLE': self.title_color,
|
||||
'PROCESS': self.default_color2,
|
||||
'PROCESS_SELECTED': self.default_color2 | curses.A_UNDERLINE,
|
||||
'STATUS': self.default_color2,
|
||||
'NICE': self.nice_color,
|
||||
'CPU_TIME': self.cpu_time_color,
|
||||
|
|
@ -293,7 +318,8 @@ class _GlancesCurses(object):
|
|||
'CAREFUL_LOG': self.ifCAREFUL_color,
|
||||
'WARNING_LOG': self.ifWARNING_color,
|
||||
'CRITICAL_LOG': self.ifCRITICAL_color,
|
||||
'PASSWORD': curses.A_PROTECT
|
||||
'PASSWORD': curses.A_PROTECT,
|
||||
'SELECTED': self.selected_color
|
||||
}
|
||||
|
||||
def set_cursor(self, value):
|
||||
|
|
@ -331,22 +357,18 @@ class _GlancesCurses(object):
|
|||
self._hotkeys[hotkey]['sort_key'] == 'auto')
|
||||
|
||||
# Other actions...
|
||||
if self.pressedkey == ord('\x1b') or self.pressedkey == ord('q'):
|
||||
# 'ESC'|'q' > Quit
|
||||
if return_to_browser:
|
||||
logger.info("Stop Glances client and return to the browser")
|
||||
else:
|
||||
logger.info("Stop Glances (keypressed: {})".format(self.pressedkey))
|
||||
elif self.pressedkey == ord('\n'):
|
||||
if self.pressedkey == ord('\n'):
|
||||
# 'ENTER' > Edit the process filter
|
||||
self.edit_filter = not self.edit_filter
|
||||
elif self.pressedkey == ord('4'):
|
||||
# '4' > Enable or disable quicklook
|
||||
self.args.full_quicklook = not self.args.full_quicklook
|
||||
if self.args.full_quicklook:
|
||||
self.enable_fullquicklook()
|
||||
else:
|
||||
self.disable_fullquicklook()
|
||||
elif self.pressedkey == ord('5'):
|
||||
# '5' > Enable or disable top menu
|
||||
self.args.disable_top = not self.args.disable_top
|
||||
if self.args.disable_top:
|
||||
self.disable_top()
|
||||
|
|
@ -366,6 +388,9 @@ class _GlancesCurses(object):
|
|||
# 'f' > Show/hide fs / folder stats
|
||||
self.args.disable_fs = not self.args.disable_fs
|
||||
self.args.disable_folders = not self.args.disable_folders
|
||||
elif self.pressedkey == ord('k'):
|
||||
# 'k' > Kill selected process (after confirmation)
|
||||
self.kill_process = not self.kill_process
|
||||
elif self.pressedkey == ord('w'):
|
||||
# 'w' > Delete finished warning logs
|
||||
glances_events.clean()
|
||||
|
|
@ -387,6 +412,25 @@ class _GlancesCurses(object):
|
|||
# ">" (right arrow) navigation through process sort
|
||||
next_sort = (self.loop_position() + 1) % len(self._sort_loop)
|
||||
glances_processes.set_sort_key(self._sort_loop[next_sort], False)
|
||||
elif self.pressedkey == curses.KEY_UP or self.pressedkey == 65:
|
||||
# 'UP' > Up in the server list
|
||||
if self.args.cursor_position > 0:
|
||||
self.args.cursor_position -= 1
|
||||
elif self.pressedkey == curses.KEY_DOWN or self.pressedkey == 66:
|
||||
# 'DOWN' > Down in the server list
|
||||
# if self.args.cursor_position < glances_processes.max_processes - 2:
|
||||
if self.args.cursor_position < glances_processes.processes_count:
|
||||
self.args.cursor_position += 1
|
||||
elif self.pressedkey == ord('\x1b') or self.pressedkey == ord('q'):
|
||||
# 'ESC'|'q' > Quit
|
||||
if return_to_browser:
|
||||
logger.info("Stop Glances client and return to the browser")
|
||||
else:
|
||||
logger.info(
|
||||
"Stop Glances (keypressed: {})".format(self.pressedkey))
|
||||
elif self.pressedkey == curses.KEY_F5:
|
||||
# "F5" manual refresh requested
|
||||
pass
|
||||
|
||||
# Return the key code
|
||||
return self.pressedkey
|
||||
|
|
@ -591,13 +635,39 @@ class _GlancesCurses(object):
|
|||
'- cmdline:.*glances.*\n' +
|
||||
'- username:nicolargo\n' +
|
||||
'- username:^root ',
|
||||
is_input=True,
|
||||
popup_type='input',
|
||||
input_value=glances_processes.process_filter_input)
|
||||
glances_processes.process_filter = new_filter
|
||||
elif self.edit_filter and cs_status is not None:
|
||||
self.display_popup('Process filter only available in standalone mode')
|
||||
self.edit_filter = False
|
||||
|
||||
# Display kill process confirmation popup
|
||||
# Only in standalone mode (cs_status is None)
|
||||
if self.kill_process and cs_status is None:
|
||||
selected_process_raw = stats.get_plugin('processlist').get_raw()[
|
||||
self.args.cursor_position]
|
||||
confirm = self.display_popup(
|
||||
'Kill process: {} (pid: {}) ?\n\nConfirm ([y]es/[n]o): '.format(
|
||||
selected_process_raw['name'],
|
||||
selected_process_raw['pid']),
|
||||
popup_type='yesno')
|
||||
if confirm.lower().startswith('y'):
|
||||
try:
|
||||
ret_kill = glances_processes.kill(selected_process_raw['pid'])
|
||||
except Exception as e:
|
||||
logger.error('Can not kill process {} ({})'.format(
|
||||
selected_process_raw['name'], e))
|
||||
else:
|
||||
logger.info('Kill signal has been sent to process {} (return code: {})'.format(
|
||||
selected_process_raw['name'], ret_kill))
|
||||
|
||||
elif self.kill_process and cs_status is not None:
|
||||
self.display_popup(
|
||||
'Kill process only available in standalone mode')
|
||||
self.kill_process = False
|
||||
|
||||
|
||||
# Display graph generation popup
|
||||
if self.args.generate_graph:
|
||||
self.display_popup('Generate graph in {}'.format(self.args.export_graph_path))
|
||||
|
|
@ -753,30 +823,37 @@ class _GlancesCurses(object):
|
|||
def display_popup(self, message,
|
||||
size_x=None, size_y=None,
|
||||
duration=3,
|
||||
is_input=False,
|
||||
popup_type='info',
|
||||
input_size=30,
|
||||
input_value=None):
|
||||
"""
|
||||
Display a centered popup.
|
||||
|
||||
If is_input is False:
|
||||
popup_type='info'
|
||||
Just an infotmation popup, no user interaction
|
||||
Display a centered popup with the given message during duration seconds
|
||||
If size_x and size_y: set the popup size
|
||||
else set it automatically
|
||||
Return True if the popup could be displayed
|
||||
|
||||
If is_input is True:
|
||||
popup_type='input'
|
||||
Display a centered popup with the given message and a input field
|
||||
If size_x and size_y: set the popup size
|
||||
else set it automatically
|
||||
Return the input string or None if the field is empty
|
||||
|
||||
popup_type='yesno'
|
||||
Display a centered popup with the given message
|
||||
If size_x and size_y: set the popup size
|
||||
else set it automatically
|
||||
Return True (yes) or False (no)
|
||||
"""
|
||||
# Center the popup
|
||||
sentence_list = message.split('\n')
|
||||
if size_x is None:
|
||||
size_x = len(max(sentence_list, key=len)) + 4
|
||||
# Add space for the input field
|
||||
if is_input:
|
||||
if popup_type == 'input':
|
||||
size_x += input_size
|
||||
if size_y is None:
|
||||
size_y = len(sentence_list) + 4
|
||||
|
|
@ -795,10 +872,15 @@ class _GlancesCurses(object):
|
|||
popup.border()
|
||||
|
||||
# Add the message
|
||||
for y, m in enumerate(message.split('\n')):
|
||||
for y, m in enumerate(sentence_list):
|
||||
popup.addnstr(2 + y, 2, m, len(m))
|
||||
|
||||
if is_input:
|
||||
if popup_type == 'info':
|
||||
# Display the popup
|
||||
popup.refresh()
|
||||
self.wait(duration * 1000)
|
||||
return True
|
||||
elif popup_type == 'input':
|
||||
# Create a subwindow for the text field
|
||||
subpop = popup.derwin(1, input_size, 2, 2 + len(m))
|
||||
subpop.attron(self.colors_list['FILTER'])
|
||||
|
|
@ -811,10 +893,10 @@ class _GlancesCurses(object):
|
|||
# Create the textbox inside the subwindows
|
||||
self.set_cursor(2)
|
||||
self.term_window.keypad(1)
|
||||
textbox = GlancesTextbox(subpop, insert_mode=False)
|
||||
textbox = GlancesTextbox(subpop, insert_mode=True)
|
||||
textbox.edit()
|
||||
self.set_cursor(0)
|
||||
self.term_window.keypad(0)
|
||||
# self.term_window.keypad(0)
|
||||
if textbox.gather() != '':
|
||||
logger.debug(
|
||||
"User enters the following string: %s" % textbox.gather())
|
||||
|
|
@ -822,11 +904,23 @@ class _GlancesCurses(object):
|
|||
else:
|
||||
logger.debug("User centers an empty string")
|
||||
return None
|
||||
else:
|
||||
elif popup_type == 'yesno':
|
||||
# # Create a subwindow for the text field
|
||||
subpop = popup.derwin(1, 2, len(sentence_list) + 1, len(m) + 2)
|
||||
subpop.attron(self.colors_list['FILTER'])
|
||||
# Init the field with the current value
|
||||
subpop.addnstr(0, 0, '', 0)
|
||||
# Display the popup
|
||||
popup.refresh()
|
||||
self.wait(duration * 1000)
|
||||
return True
|
||||
subpop.refresh()
|
||||
# Create the textbox inside the subwindows
|
||||
self.set_cursor(2)
|
||||
self.term_window.keypad(1)
|
||||
textbox = GlancesTextboxYesNo(subpop, insert_mode=False)
|
||||
textbox.edit()
|
||||
self.set_cursor(0)
|
||||
# self.term_window.keypad(0)
|
||||
return textbox.gather()
|
||||
|
||||
def display_plugin(self, plugin_stats,
|
||||
display_optional=True,
|
||||
|
|
@ -981,6 +1075,9 @@ class _GlancesCurses(object):
|
|||
pressedkey = self.__catch_key(return_to_browser=return_to_browser)
|
||||
# Is it an exit key ?
|
||||
exitkey = (pressedkey == ord('\x1b') or pressedkey == ord('q'))
|
||||
if pressedkey == curses.KEY_F5:
|
||||
# were asked to refresh
|
||||
return exitkey
|
||||
if not exitkey and pressedkey > -1:
|
||||
# Redraw display
|
||||
self.flush(stats, cs_status=cs_status)
|
||||
|
|
@ -1049,3 +1146,12 @@ class GlancesTextbox(Textbox, object):
|
|||
if ch == 127: # Back
|
||||
return 8
|
||||
return super(GlancesTextbox, self).do_command(ch)
|
||||
|
||||
|
||||
class GlancesTextboxYesNo(Textbox, object):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GlancesTextboxYesNo, self).__init__(*args, **kwargs)
|
||||
|
||||
def do_command(self, ch):
|
||||
return super(GlancesTextboxYesNo, self).do_command(ch)
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
yarn.lock
|
||||
|
|
@ -148,7 +148,7 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
#amps-plugin .process-result {
|
||||
#amps .process-result {
|
||||
max-width: 300px;
|
||||
overflow: hidden;
|
||||
white-space: pre-wrap;
|
||||
|
|
@ -156,7 +156,7 @@ body {
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#gpu-plugin .gpu-name {
|
||||
#gpu .gpu-name {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export default function GlancesPluginAmpsController($scope, GlancesStats, favico
|
|||
}, this);
|
||||
};
|
||||
|
||||
vm.getDescriptionDecoration = function (process) {
|
||||
vm.getNameDecoration = function (process) {
|
||||
var count = process.count;
|
||||
var countMin = process.countmin;
|
||||
var countMax = process.countmax;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<section id="amps" class="plugin">
|
||||
<div class="table">
|
||||
<div class="table-row" ng-repeat="process in vm.processes">
|
||||
<div class="table-cell text-left" ng-class="vm.getDescriptionDecoration(process)">{{ process.name }}</div>
|
||||
<div class="table-cell text-left">{{ process.count }}</div>
|
||||
<div class="table-cell text-left" ng-class="vm.getNameDecoration(process)">{{ process.name }}</div>
|
||||
<div class="table-cell text-left" ng-if="process.regex">{{ process.count }}</div>
|
||||
<div class="table-cell text-left process-result" ng-bind-html="process.result|nl2br"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export default function GlancesPluginDockerController($scope, GlancesStats) {
|
|||
'status': containerData.Status,
|
||||
'cpu': containerData.cpu.total,
|
||||
'memory': containerData.memory.usage != undefined ? containerData.memory.usage : '?',
|
||||
'rss': containerData.memory.rss != undefined ? containerData.memory.usage: '?',
|
||||
'rss': containerData.memory.rss != undefined ? containerData.memory.rss : '?',
|
||||
'ior': containerData.io.ior != undefined ? containerData.io.ior : '?',
|
||||
'iow': containerData.io.iow != undefined ? containerData.io.iow : '?',
|
||||
'io_time_since_update': containerData.io.time_since_update,
|
||||
|
|
|
|||
|
|
@ -5,27 +5,26 @@
|
|||
<div class="table">
|
||||
<div class="table-row" ng-if="arguments.meangpu || vm.gpus.length === 1">
|
||||
<div class="table-cell text-left">proc:</div>
|
||||
<div class="table-cell" ng-class="vm.getMeanDecoration('proc')" ng-if="vm.mean.proc">{{ vm.mean.proc |
|
||||
<div class="table-cell" ng-class="vm.getMeanDecoration('proc')" ng-if="vm.mean.proc != null">{{ vm.mean.proc |
|
||||
number : 0 }}%
|
||||
</div>
|
||||
<div class="table-cell" ng-if="!vm.mean.proc">N/A</div>
|
||||
<div class="table-cell" ng-if="vm.mean.proc == null">N/A</div>
|
||||
</div>
|
||||
<div class="table-row" ng-if="arguments.meangpu || vm.gpus.length === 1">
|
||||
<div class="table-cell text-left">mem:</div>
|
||||
<div class="table-cell" ng-class="vm.getMeanDecoration('mem')" ng-if="vm.mean.mem">{{ vm.mean.mem | number :
|
||||
<div class="table-cell" ng-class="vm.getMeanDecoration('mem')" ng-if="vm.mean.mem != null">{{ vm.mean.mem | number :
|
||||
0 }}%
|
||||
</div>
|
||||
<div class="table-cell" ng-if="!vm.mean.mem">N/A</div>
|
||||
<div class="table-cell" ng-if="vm.mean.mem == null">N/A</div>
|
||||
</div>
|
||||
<div class="table-row" ng-if="!arguments.meangpu && vm.gpus.length > 1" ng-repeat="gpu in vm.gpus">
|
||||
<div class="table-cell text-left">
|
||||
{{ gpu.gpu_id }}:
|
||||
<span ng-class="vm.getDecoration(gpu.gpu_id, 'proc')"
|
||||
ng-if="gpu.proc">{{ gpu.proc | number : 0 }}%</span>
|
||||
<span ng-if="!gpu.proc">N/A</span>
|
||||
<span ng-class="vm.getDecoration(gpu.gpu_id, 'proc')" ng-if="gpu.proc != null">{{ gpu.proc | number : 0 }}%</span>
|
||||
<span ng-if="gpu.proc == null">N/A</span>
|
||||
mem:
|
||||
<span ng-class="vm.getDecoration(gpu.gpu_id, 'mem')" ng-if="gpu.mem">{{ gpu.mem | number : 0 }}%</span>
|
||||
<span ng-if="!gpu.mem">N/A</span>
|
||||
<span ng-class="vm.getDecoration(gpu.gpu_id, 'mem')" ng-if="gpu.mem != null">{{ gpu.mem | number : 0 }}%</span>
|
||||
<span ng-if="gpu.mem == null">N/A</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export default function GlancesPluginProcessController(ARGUMENTS, hotkeys) {
|
|||
return !(column === 'username' || column === 'name');
|
||||
},
|
||||
getColumnLabel: function (column) {
|
||||
if (_.isEqual(column, ['io_read', 'io_write'])) {
|
||||
if (column === 'io_read' || column === 'io_write') {
|
||||
return 'io_counters';
|
||||
} else {
|
||||
return column;
|
||||
|
|
|
|||
|
|
@ -37,35 +37,26 @@ export default function GlancesPluginProcesslistController($scope, GlancesStats,
|
|||
}
|
||||
|
||||
if (process.num_threads === null) {
|
||||
process.num_threads = -1;
|
||||
process.num_threads = -1;
|
||||
}
|
||||
|
||||
if (process.cpu_percent === null) {
|
||||
process.cpu_percent = -1;
|
||||
process.cpu_percent = -1;
|
||||
}
|
||||
|
||||
if (process.memory_percent === null) {
|
||||
process.memory_percent = -1;
|
||||
if (process.memory_percent === null) {
|
||||
process.memory_percent = -1;
|
||||
}
|
||||
|
||||
|
||||
process.ioRead = null;
|
||||
process.ioWrite = null;
|
||||
process.io_read = null;
|
||||
process.io_write = null;
|
||||
|
||||
if (process.io_counters) {
|
||||
vm.ioReadWritePresent = true;
|
||||
|
||||
process.ioRead = (process.io_counters[0] - process.io_counters[2]) / process.time_since_update;
|
||||
|
||||
if (process.ioRead != 0) {
|
||||
process.ioRead = $filter('bytes')(process.ioRead);
|
||||
}
|
||||
|
||||
process.ioWrite = (process.io_counters[1] - process.io_counters[3]) / process.time_since_update;
|
||||
|
||||
if (process.ioWrite != 0) {
|
||||
process.ioWrite = $filter('bytes')(process.ioWrite);
|
||||
}
|
||||
process.io_read = (process.io_counters[0] - process.io_counters[2]) / process.time_since_update;
|
||||
process.io_write = (process.io_counters[1] - process.io_counters[3]) / process.time_since_update;
|
||||
}
|
||||
|
||||
process.isNice = process.nice !== undefined && ((data.stats.isWindows && process.nice != 32) || (!data.stats.isWindows && process.nice != 0));
|
||||
|
|
@ -81,7 +72,7 @@ export default function GlancesPluginProcesslistController($scope, GlancesStats,
|
|||
if (data.isWindows && process.username !== null) {
|
||||
process.username = _.last(process.username.split('\\'));
|
||||
}
|
||||
|
||||
|
||||
vm.processes.push(process);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@
|
|||
<div class="table-cell text-left hidden-xs hidden-sm">{{ process.num_threads == -1 ? '?' : process.num_threads }}</div>
|
||||
<div class="table-cell" ng-class="{nice: process.isNice}">{{process.nice | exclamation}}</div>
|
||||
<div class="table-cell" ng-class="{status: process.status == 'R'}">{{process.status}}</div>
|
||||
<div class="table-cell hidden-xs hidden-sm" ng-show="vm.ioReadWritePresent">{{process.ioRead}}</div>
|
||||
<div class="table-cell text-left hidden-xs hidden-sm" ng-show="vm.ioReadWritePresent">{{process.ioWrite}}</div>
|
||||
<div class="table-cell hidden-xs hidden-sm" ng-show="vm.ioReadWritePresent">{{process.io_read | bytes}}</div>
|
||||
<div class="table-cell text-left hidden-xs hidden-sm" ng-show="vm.ioReadWritePresent">{{process.io_write | bytes}}</div>
|
||||
<div class="table-cell text-left" ng-show="vm.arguments.process_short_name">{{process.name}}</div>
|
||||
<div class="table-cell text-left" ng-show="!vm.arguments.process_short_name">{{process.cmdline}}</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -83,9 +83,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"angular": {
|
||||
"version": "1.7.9",
|
||||
"resolved": "https://registry.npmjs.org/angular/-/angular-1.7.9.tgz",
|
||||
"integrity": "sha512-5se7ZpcOtu0MBFlzGv5dsM1quQDoDeUTwZrWjGtTNA7O88cD8TEk5IEKCTDa3uECV9XnvKREVUr7du1ACiWGFQ=="
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.0.tgz",
|
||||
"integrity": "sha512-VdaMx+Qk0Skla7B5gw77a8hzlcOakwF8mjlW13DpIWIDlfqwAbSSLfd8N/qZnzEmQF4jC4iofInd3gE7vL8ZZg=="
|
||||
},
|
||||
"angular-hotkeys": {
|
||||
"version": "1.7.0",
|
||||
|
|
@ -403,7 +403,6 @@
|
|||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
|
|
@ -707,7 +706,7 @@
|
|||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
@ -1395,7 +1394,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
|
|
@ -1408,9 +1406,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
|
||||
"integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
|
||||
"integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bn.js": "^4.4.0",
|
||||
|
|
@ -1936,7 +1934,7 @@
|
|||
"dependencies": {
|
||||
"combined-stream": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
@ -3305,8 +3303,7 @@
|
|||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"jsesc": {
|
||||
"version": "0.5.0",
|
||||
|
|
@ -3475,9 +3472,9 @@
|
|||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
|
||||
},
|
||||
"lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
|
|
@ -5774,9 +5771,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.14.2",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
|
||||
"integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
|
|
@ -6104,8 +6101,7 @@
|
|||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"typedarray": {
|
||||
"version": "0.0.6",
|
||||
|
|
@ -6143,7 +6139,7 @@
|
|||
},
|
||||
"yargs": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
|
||||
"integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
@ -6432,7 +6428,7 @@
|
|||
},
|
||||
"load-json-file": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"angular": "^1.7.9",
|
||||
"angular": "^1.8.0",
|
||||
"angular-hotkeys": "^1.7.0",
|
||||
"bootstrap": "^3.4.1",
|
||||
"favico.js": "^0.3.10",
|
||||
"lodash": "^4.17.15"
|
||||
"lodash": "^4.17.19"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "^0.1.19",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
|
@ -23,6 +23,7 @@ from __future__ import unicode_literals
|
|||
from glances.compat import nativestr, n
|
||||
from glances.timer import getTimeSinceLastUpdate
|
||||
from glances.plugins.glances_plugin import GlancesPlugin
|
||||
from glances.logger import logger
|
||||
|
||||
import psutil
|
||||
|
||||
|
|
@ -51,6 +52,9 @@ class Plugin(GlancesPlugin):
|
|||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
# Hide stats if it has never been != 0
|
||||
self.hide_zero = True
|
||||
self.hide_zero_fields = ['read_bytes', 'write_bytes']
|
||||
|
||||
def get_key(self):
|
||||
"""Return the key of the list."""
|
||||
|
|
@ -143,9 +147,12 @@ class Plugin(GlancesPlugin):
|
|||
# Call the father's method
|
||||
super(Plugin, self).update_views()
|
||||
|
||||
# Check if the stats should be hidden
|
||||
self.update_views_hidden()
|
||||
|
||||
# Add specifics informations
|
||||
# Alert
|
||||
for i in self.stats:
|
||||
for i in self.get_raw():
|
||||
disk_real_name = i['disk_name']
|
||||
self.views[i[self.get_key()]]['read_bytes']['decoration'] = self.get_alert(int(i['read_bytes'] // i['time_since_update']),
|
||||
header=disk_real_name + '_rx')
|
||||
|
|
@ -179,6 +186,9 @@ class Plugin(GlancesPlugin):
|
|||
ret.append(self.curse_add_line(msg))
|
||||
# Disk list (sorted by name)
|
||||
for i in self.sorted_stats():
|
||||
# Hide stats if never be different from 0 (issue #1787)
|
||||
if all([self.get_views(item=i[self.get_key()], key=f, option='hidden') for f in self.hide_zero_fields]):
|
||||
continue
|
||||
# Is there an alias for the disk name ?
|
||||
disk_real_name = i['disk_name']
|
||||
disk_name = self.has_alias(i['disk_name'])
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@ class Plugin(GlancesPlugin):
|
|||
# The plgin can be disable using: args.disable_docker
|
||||
self.args = args
|
||||
|
||||
# Default config keys
|
||||
self.config = config
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
|
||||
|
|
@ -207,6 +210,14 @@ class Plugin(GlancesPlugin):
|
|||
# Get stats for all containers
|
||||
stats['containers'] = []
|
||||
for container in containers:
|
||||
# Only show specific containers
|
||||
if not self.is_show(nativestr(container.name)):
|
||||
continue
|
||||
|
||||
# Do not take hiden container into account
|
||||
if self.is_hide(nativestr(container.name)):
|
||||
continue
|
||||
|
||||
# Init the stats for the current container
|
||||
container_stats = {}
|
||||
# The key is the container name and not the Id
|
||||
|
|
@ -524,8 +535,11 @@ class Plugin(GlancesPlugin):
|
|||
ret.append(self.curse_new_line())
|
||||
# Header
|
||||
ret.append(self.curse_new_line())
|
||||
# Get the maximum containers name (cutted to 20 char max)
|
||||
name_max_width = min(20, len(max(self.stats['containers'], key=lambda x: len(x['name']))['name']))
|
||||
# Get the maximum containers name
|
||||
# Max size is configurable. See feature request #1723.
|
||||
name_max_width = min(self.config.get_int_value('docker', 'max_name_size', default=20),
|
||||
len(max(self.stats['containers'],
|
||||
key=lambda x: len(x['name']))['name']))
|
||||
msg = ' {:{width}}'.format('Name', width=name_max_width)
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:>10}'.format('Status')
|
||||
|
|
|
|||
|
|
@ -103,8 +103,6 @@ class Plugin(GlancesPlugin):
|
|||
return self.stats
|
||||
|
||||
# Optionnal hack to allow logicals mounts points (issue #448)
|
||||
# Ex: Had to put 'allow=zfs' in the [fs] section of the conf file
|
||||
# to allow zfs monitoring
|
||||
for fstype in self.get_conf_value('allow'):
|
||||
try:
|
||||
fs_stat += [f for f in psutil.disk_partitions(all=True) if f.fstype.find(fstype) >= 0]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# Copyright (C) 2018 Kirby Banman <kirby.banman@gmail.com>
|
||||
# Copyright (C) 2020 Kirby Banman <kirby.banman@gmail.com>
|
||||
#
|
||||
# Glances is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
|
|
@ -226,11 +226,11 @@ class Plugin(GlancesPlugin):
|
|||
id_msg = '{}'.format(gpu_stats['gpu_id'])
|
||||
try:
|
||||
proc_msg = '{:>3.0f}%'.format(gpu_stats['proc'])
|
||||
except ValueError:
|
||||
except (ValueError, TypeError):
|
||||
proc_msg = '{:>4}'.format('N/A')
|
||||
try:
|
||||
mem_msg = '{:>3.0f}%'.format(gpu_stats['mem'])
|
||||
except ValueError:
|
||||
except (ValueError, TypeError):
|
||||
mem_msg = '{:>4}'.format('N/A')
|
||||
msg = '{}: {} mem: {}'.format(id_msg,
|
||||
proc_msg,
|
||||
|
|
|
|||
|
|
@ -150,6 +150,9 @@ class Plugin(GlancesPlugin):
|
|||
"""
|
||||
# Thanks to @Atticfire
|
||||
# See https://github.com/nicolargo/glances/issues/1417#issuecomment-469894399
|
||||
if ip is None:
|
||||
# Correct issue #1528
|
||||
return 0
|
||||
return sum(bin(int(x)).count('1') for x in ip.split('.'))
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -66,20 +66,24 @@ class Plugin(GlancesPlugin):
|
|||
if self.input_method == 'local':
|
||||
# Update stats using the standard system lib
|
||||
# Grab SWAP using the psutil swap_memory method
|
||||
sm_stats = psutil.swap_memory()
|
||||
|
||||
# Get all the swap stats (copy/paste of the psutil documentation)
|
||||
# total: total swap memory in bytes
|
||||
# used: used swap memory in bytes
|
||||
# free: free swap memory in bytes
|
||||
# percent: the percentage usage
|
||||
# sin: the number of bytes the system has swapped in from disk (cumulative)
|
||||
# sout: the number of bytes the system has swapped out from disk
|
||||
# (cumulative)
|
||||
for swap in ['total', 'used', 'free', 'percent',
|
||||
'sin', 'sout']:
|
||||
if hasattr(sm_stats, swap):
|
||||
stats[swap] = getattr(sm_stats, swap)
|
||||
try:
|
||||
sm_stats = psutil.swap_memory()
|
||||
except RuntimeError:
|
||||
# Crash on startup on Illumos when no swap is configured #1767
|
||||
pass
|
||||
else:
|
||||
# Get all the swap stats (copy/paste of the psutil documentation)
|
||||
# total: total swap memory in bytes
|
||||
# used: used swap memory in bytes
|
||||
# free: free swap memory in bytes
|
||||
# percent: the percentage usage
|
||||
# sin: the number of bytes the system has swapped in from disk (cumulative)
|
||||
# sout: the number of bytes the system has swapped out from disk
|
||||
# (cumulative)
|
||||
for swap in ['total', 'used', 'free', 'percent',
|
||||
'sin', 'sout']:
|
||||
if hasattr(sm_stats, swap):
|
||||
stats[swap] = getattr(sm_stats, swap)
|
||||
elif self.input_method == 'snmp':
|
||||
# Update stats using SNMP
|
||||
if self.short_system_name == 'windows':
|
||||
|
|
@ -135,7 +139,8 @@ class Plugin(GlancesPlugin):
|
|||
|
||||
# Add specifics informations
|
||||
# Alert and log
|
||||
self.views['used']['decoration'] = self.get_alert_log(self.stats['used'], maximum=self.stats['total'])
|
||||
if 'used' in self.stats and 'total' in self.stats:
|
||||
self.views['used']['decoration'] = self.get_alert_log(self.stats['used'], maximum=self.stats['total'])
|
||||
|
||||
def msg_curse(self, args=None, max_width=None):
|
||||
"""Return the dict to display in the curse interface."""
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ class Plugin(GlancesPlugin):
|
|||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
# Hide stats if it has never been != 0
|
||||
self.hide_zero = True
|
||||
self.hide_zero_fields = ['rx', 'tx']
|
||||
|
||||
def get_key(self):
|
||||
"""Return the key of the list."""
|
||||
|
|
@ -223,13 +226,17 @@ class Plugin(GlancesPlugin):
|
|||
# Call the father's method
|
||||
super(Plugin, self).update_views()
|
||||
|
||||
# Check if the stats should be hidden
|
||||
self.update_views_hidden()
|
||||
|
||||
# Add specifics informations
|
||||
# Alert
|
||||
for i in self.stats:
|
||||
for i in self.get_raw():
|
||||
ifrealname = i['interface_name'].split(':')[0]
|
||||
# Convert rate in bps ( to be able to compare to interface speed)
|
||||
# Convert rate in bps (to be able to compare to interface speed)
|
||||
bps_rx = int(i['rx'] // i['time_since_update'] * 8)
|
||||
bps_tx = int(i['tx'] // i['time_since_update'] * 8)
|
||||
|
||||
# Decorate the bitrate with the configuration file thresolds
|
||||
alert_rx = self.get_alert(bps_rx, header=ifrealname + '_rx')
|
||||
alert_tx = self.get_alert(bps_tx, header=ifrealname + '_tx')
|
||||
|
|
@ -290,6 +297,9 @@ class Plugin(GlancesPlugin):
|
|||
# Do not display interface in down state (issue #765)
|
||||
if ('is_up' in i) and (i['is_up'] is False):
|
||||
continue
|
||||
# Hide stats if never be different from 0 (issue #1787)
|
||||
if all([self.get_views(item=i[self.get_key()], key=f, option='hidden') for f in self.hide_zero_fields]):
|
||||
continue
|
||||
# Format stats
|
||||
# Is there an alias for the interface name ?
|
||||
ifrealname = i['interface_name'].split(':')[0]
|
||||
|
|
|
|||
|
|
@ -41,6 +41,12 @@ class Plugin(GlancesPlugin):
|
|||
# Set the message position
|
||||
self.align = 'bottom'
|
||||
|
||||
if args.strftime_format:
|
||||
self.strftime = args.strftime_format
|
||||
elif config is not None:
|
||||
if 'global' in config.as_dict():
|
||||
self.strftime = config.as_dict()['global']['strftime_format']
|
||||
|
||||
def reset(self):
|
||||
"""Reset/init the stats."""
|
||||
self.stats = ''
|
||||
|
|
@ -49,10 +55,14 @@ class Plugin(GlancesPlugin):
|
|||
"""Update current date/time."""
|
||||
# Had to convert it to string because datetime is not JSON serializable
|
||||
# Add the time zone (issue #1249 / #1337 / #1598)
|
||||
if (len(tzname[1]) > 6):
|
||||
self.stats = strftime('%Y-%m-%d %H:%M:%S %z')
|
||||
|
||||
if self.strftime:
|
||||
self.stats = strftime(self.strftime)
|
||||
else:
|
||||
self.stats = strftime('%Y-%m-%d %H:%M:%S %Z')
|
||||
if (len(tzname[1]) > 6):
|
||||
self.stats = strftime('%Y-%m-%d %H:%M:%S %z')
|
||||
else:
|
||||
self.stats = strftime('%Y-%m-%d %H:%M:%S %Z')
|
||||
|
||||
return self.stats
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,11 @@ class GlancesPlugin(object):
|
|||
# Init the views
|
||||
self.views = dict()
|
||||
|
||||
# Hide stats if all the hide_zero_fields has never been != 0
|
||||
# Default is False, always display stats
|
||||
self.hide_zero = False
|
||||
self.hide_zero_fields = []
|
||||
|
||||
# Init the stats
|
||||
self.stats_init_value = stats_init_value
|
||||
self.stats = None
|
||||
|
|
@ -422,16 +427,61 @@ class GlancesPlugin(object):
|
|||
"Cannot get item({})=value({}) ({})".format(item, value, e))
|
||||
return None
|
||||
|
||||
def update_views_hidden(self):
|
||||
"""If the self.hide_zero is set then update the hidden field of the view
|
||||
It will check if all fields values are already be different from 0
|
||||
In this case, the hidden field is set to True
|
||||
|
||||
Note: This function should be called by plugin (in the update_views method)
|
||||
|
||||
Example (for network plugin):
|
||||
__Init__
|
||||
self.hide_zero_fields = ['rx', 'tx']
|
||||
Update views
|
||||
...
|
||||
self.update_views_hidden()
|
||||
"""
|
||||
if not self.hide_zero:
|
||||
return False
|
||||
if (isinstance(self.get_raw(), list) and
|
||||
self.get_raw() is not None and
|
||||
self.get_key() is not None):
|
||||
# Stats are stored in a list of dict (ex: NETWORK, FS...)
|
||||
for i in self.get_raw():
|
||||
if any([i[f] for f in self.hide_zero_fields]):
|
||||
for f in self.hide_zero_fields:
|
||||
self.views[i[self.get_key(
|
||||
)]][f]['_zero'] = self.views[i[self.get_key()]][f]['hidden']
|
||||
for f in self.hide_zero_fields:
|
||||
self.views[i[self.get_key(
|
||||
)]][f]['hidden'] = self.views[i[self.get_key()]][f]['_zero'] and i[f] == 0
|
||||
elif isinstance(self.get_raw(), dict) and self.get_raw() is not None:
|
||||
#
|
||||
# Warning: This code has never been tested because
|
||||
# no plugin with dict instance use the hidden function...
|
||||
# vvvv
|
||||
#
|
||||
# Stats are stored in a dict (ex: CPU, LOAD...)
|
||||
for key in listkeys(self.get_raw()):
|
||||
if any([self.get_raw()[f] for f in self.hide_zero_fields]):
|
||||
for f in self.hide_zero_fields:
|
||||
self.views[f]['_zero'] = self.views[f]['hidden']
|
||||
for f in self.hide_zero_fields:
|
||||
self.views[f]['hidden'] = self.views['_zero'] and self.views[f] == 0
|
||||
return True
|
||||
|
||||
def update_views(self):
|
||||
"""Update the stats views.
|
||||
|
||||
The V of MVC
|
||||
A dict of dict with the needed information to display the stats.
|
||||
Example for the stat xxx:
|
||||
'xxx': {'decoration': 'DEFAULT',
|
||||
'optional': False,
|
||||
'additional': False,
|
||||
'splittable': False}
|
||||
'xxx': {'decoration': 'DEFAULT', >>> The decoration of the stats
|
||||
'optional': False, >>> Is the stat optional
|
||||
'additional': False, >>> Is the stat provide additional information
|
||||
'splittable': False, >>> Is the stat can be cut (like process lon name)
|
||||
'hidden': False, >>> Is the stats should be hidden in the UI
|
||||
'_zero': True} >>> For internal purpose only
|
||||
"""
|
||||
ret = {}
|
||||
|
||||
|
|
@ -440,12 +490,15 @@ class GlancesPlugin(object):
|
|||
self.get_key() is not None):
|
||||
# Stats are stored in a list of dict (ex: NETWORK, FS...)
|
||||
for i in self.get_raw():
|
||||
# i[self.get_key()] is the interface name (example for NETWORK)
|
||||
ret[i[self.get_key()]] = {}
|
||||
for key in listkeys(i):
|
||||
value = {'decoration': 'DEFAULT',
|
||||
'optional': False,
|
||||
'additional': False,
|
||||
'splittable': False}
|
||||
'splittable': False,
|
||||
'hidden': False,
|
||||
'_zero': self.views[i[self.get_key()]][key]['_zero'] if i[self.get_key()] in self.views and key in self.views[i[self.get_key()]] else True}
|
||||
ret[i[self.get_key()]][key] = value
|
||||
elif isinstance(self.get_raw(), dict) and self.get_raw() is not None:
|
||||
# Stats are stored in a dict (ex: CPU, LOAD...)
|
||||
|
|
@ -453,7 +506,9 @@ class GlancesPlugin(object):
|
|||
value = {'decoration': 'DEFAULT',
|
||||
'optional': False,
|
||||
'additional': False,
|
||||
'splittable': False}
|
||||
'splittable': False,
|
||||
'hidden': False,
|
||||
'_zero': self.views[key]['_zero'] if key in self.views and '_zero' in self.views[key] else True}
|
||||
ret[key] = value
|
||||
|
||||
self.views = ret
|
||||
|
|
@ -752,6 +807,21 @@ class GlancesPlugin(object):
|
|||
except KeyError:
|
||||
return default
|
||||
|
||||
def is_show(self, value, header=""):
|
||||
"""Return True if the value is in the show configuration list.
|
||||
If the show value is empty, return True (show by default)
|
||||
|
||||
The show configuration list is defined in the glances.conf file.
|
||||
It is a comma separed list of regexp.
|
||||
Example for diskio:
|
||||
show=sda.*
|
||||
"""
|
||||
# @TODO: possible optimisation: create a re.compile list
|
||||
if self.get_conf_value('show', header=header) == []:
|
||||
return True
|
||||
else:
|
||||
return any(j for j in [re.match(i, value) for i in self.get_conf_value('show', header=header)])
|
||||
|
||||
def is_hide(self, value, header=""):
|
||||
"""Return True if the value is in the hide configuration list.
|
||||
|
||||
|
|
@ -760,9 +830,7 @@ class GlancesPlugin(object):
|
|||
Example for diskio:
|
||||
hide=sda2,sda5,loop.*
|
||||
"""
|
||||
# TODO: possible optimisation: create a re.compile list
|
||||
# Old version (see issue #1691)
|
||||
#return not all(j is None for j in [re.match(i, value.lower()) for i in self.get_conf_value('hide', header=header)])
|
||||
# @TODO: possible optimisation: create a re.compile list
|
||||
return any(j for j in [re.match(i, value) for i in self.get_conf_value('hide', header=header)])
|
||||
|
||||
def has_alias(self, header):
|
||||
|
|
|
|||
|
|
@ -70,12 +70,13 @@ class Plugin(GlancesPlugin):
|
|||
'status': '{:>1} ',
|
||||
'ior': '{:>4} ',
|
||||
'iow': '{:<4} ',
|
||||
'command': '{}',
|
||||
'command': '{} {}',
|
||||
}
|
||||
|
||||
# Define the stat layout of the processes list columns
|
||||
layout_stat = {
|
||||
'cpu': '{:<6.1f} ',
|
||||
'cpu': '{:<6.1f}',
|
||||
'cpu_no_digit': '{:<6.0f}',
|
||||
'mem': '{:<5.1f} ',
|
||||
'virt': '{:<5} ',
|
||||
'res': '{:<5} ',
|
||||
|
|
@ -172,19 +173,26 @@ class Plugin(GlancesPlugin):
|
|||
pass
|
||||
return 'DEFAULT'
|
||||
|
||||
def get_process_curses_data(self, p, first, args):
|
||||
def get_process_curses_data(self, p, selected, args):
|
||||
"""Get curses data to display for a process.
|
||||
|
||||
- p is the process to display
|
||||
- first is a tag=True if the process is the first on the list
|
||||
- selected is a tag=True if the selected process
|
||||
"""
|
||||
ret = [self.curse_new_line()]
|
||||
# When a process is selected:
|
||||
# * display a special caracter at the beginning of the line
|
||||
# * underline the command name
|
||||
if args.is_standalone:
|
||||
ret.append(self.curse_add_line('>' if selected else ' ', 'SELECTED'))
|
||||
# CPU
|
||||
if 'cpu_percent' in p and p['cpu_percent'] is not None and p['cpu_percent'] != '':
|
||||
cpu_layout = self.layout_stat['cpu'] if p['cpu_percent'] < 100 else self.layout_stat['cpu_no_digit']
|
||||
if args.disable_irix and self.nb_log_core != 0:
|
||||
msg = self.layout_stat['cpu'].format(p['cpu_percent'] / float(self.nb_log_core))
|
||||
msg = cpu_layout.format(
|
||||
p['cpu_percent'] / float(self.nb_log_core))
|
||||
else:
|
||||
msg = self.layout_stat['cpu'].format(p['cpu_percent'])
|
||||
msg = cpu_layout.format(p['cpu_percent'])
|
||||
alert = self.get_alert(p['cpu_percent'],
|
||||
highlight_zero=False,
|
||||
is_max=(p['cpu_percent'] == self.max_values['cpu_percent']),
|
||||
|
|
@ -321,28 +329,34 @@ class Plugin(GlancesPlugin):
|
|||
else:
|
||||
cmdline = '?'
|
||||
try:
|
||||
process_decoration = 'PROCESS_SELECTED' if (selected and args.is_standalone) else 'PROCESS'
|
||||
if cmdline:
|
||||
path, cmd, arguments = split_cmdline(cmdline)
|
||||
# Manage end of line in arguments (see #1692)
|
||||
arguments.replace('\r\n', ' ')
|
||||
arguments.replace('\n', ' ')
|
||||
if os.path.isdir(path) and not args.process_short_name:
|
||||
msg = self.layout_stat['command'].format(path) + os.sep
|
||||
ret.append(self.curse_add_line(msg, splittable=True))
|
||||
ret.append(self.curse_add_line(cmd, decoration='PROCESS', splittable=True))
|
||||
ret.append(self.curse_add_line(
|
||||
cmd, decoration=process_decoration, splittable=True))
|
||||
else:
|
||||
msg = self.layout_stat['command'].format(cmd)
|
||||
ret.append(self.curse_add_line(msg, decoration='PROCESS', splittable=True))
|
||||
ret.append(self.curse_add_line(
|
||||
msg, decoration=process_decoration, splittable=True))
|
||||
if arguments:
|
||||
msg = ' ' + self.layout_stat['command'].format(arguments)
|
||||
ret.append(self.curse_add_line(msg, splittable=True))
|
||||
else:
|
||||
msg = self.layout_stat['name'].format(p['name'])
|
||||
ret.append(self.curse_add_line(msg, splittable=True))
|
||||
ret.append(self.curse_add_line(msg, decoration=process_decoration, splittable=True))
|
||||
except (TypeError, UnicodeEncodeError) as e:
|
||||
# Avoid crach after running fine for several hours #1335
|
||||
logger.debug("Can not decode command line '{}' ({})".format(cmdline, e))
|
||||
ret.append(self.curse_add_line('', splittable=True))
|
||||
|
||||
# Add extended stats but only for the top processes
|
||||
if first and 'extended_stats' in p and args.enable_process_extended:
|
||||
if args.cursor_position == 0 and 'extended_stats' in p and args.enable_process_extended:
|
||||
# Left padding
|
||||
xpad = ' ' * 13
|
||||
# First line is CPU affinity
|
||||
|
|
@ -429,11 +443,13 @@ class Plugin(GlancesPlugin):
|
|||
|
||||
# Process list
|
||||
# Loop over processes (sorted by the sort key previously compute)
|
||||
first = True
|
||||
i = 0
|
||||
for p in self.__sort_stats(process_sort_key):
|
||||
ret.extend(self.get_process_curses_data(p, first, args))
|
||||
# End of extended stats
|
||||
first = False
|
||||
ret.extend(self.get_process_curses_data(
|
||||
p, i == args.cursor_position, args))
|
||||
i += 1
|
||||
|
||||
# A filter is set Display the stats summaries
|
||||
if glances_processes.process_filter is not None:
|
||||
if args.reset_minmax_tag:
|
||||
args.reset_minmax_tag = not args.reset_minmax_tag
|
||||
|
|
@ -478,7 +494,8 @@ class Plugin(GlancesPlugin):
|
|||
ret.append(self.curse_add_line(msg, sort_style if process_sort_key == 'io_counters' else 'DEFAULT', optional=True, additional=True))
|
||||
msg = self.layout_header['iow'].format('W/s')
|
||||
ret.append(self.curse_add_line(msg, sort_style if process_sort_key == 'io_counters' else 'DEFAULT', optional=True, additional=True))
|
||||
msg = self.layout_header['command'].format('Command')
|
||||
msg = self.layout_header['command'].format('Command',
|
||||
"('k' to kill)" if args.is_standalone else "")
|
||||
ret.append(self.curse_add_line(msg, sort_style if process_sort_key == 'name' else 'DEFAULT'))
|
||||
|
||||
def __msg_curse_sum(self, ret, sep_char='_', mmm=None, args=None):
|
||||
|
|
|
|||
|
|
@ -81,7 +81,11 @@ class Plugin(GlancesPlugin):
|
|||
stats['percpu'] = cpu_percent.get(percpu=True)
|
||||
# Use the psutil lib for the memory (virtual and swap)
|
||||
stats['mem'] = psutil.virtual_memory().percent
|
||||
stats['swap'] = psutil.swap_memory().percent
|
||||
try:
|
||||
stats['swap'] = psutil.swap_memory().percent
|
||||
except RuntimeError:
|
||||
# Correct issue in Illumos OS (see #1767)
|
||||
stats['swap'] = None
|
||||
elif self.input_method == 'snmp':
|
||||
# Not available
|
||||
pass
|
||||
|
|
@ -99,8 +103,12 @@ class Plugin(GlancesPlugin):
|
|||
stats['cpu_name'] = cpu_info.get('brand', 'CPU')
|
||||
if 'hz_actual_raw' in cpu_info:
|
||||
stats['cpu_hz_current'] = cpu_info['hz_actual_raw'][0]
|
||||
elif 'hz_actual' in cpu_info:
|
||||
stats['cpu_hz_current'] = cpu_info['hz_actual'][0]
|
||||
if 'hz_advertised_raw' in cpu_info:
|
||||
stats['cpu_hz'] = cpu_info['hz_advertised_raw'][0]
|
||||
elif 'hz_advertised' in cpu_info:
|
||||
stats['cpu_hz'] = cpu_info['hz_advertised'][0]
|
||||
|
||||
# Update the stats
|
||||
self.stats = stats
|
||||
|
|
|
|||
|
|
@ -176,6 +176,11 @@ class GlancesProcesses(object):
|
|||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def processes_count(self):
|
||||
"""Get the current number of processes showed in the UI."""
|
||||
return min(self._max_processes - 2, glances_processes.processcount['total'] - 1)
|
||||
|
||||
@property
|
||||
def max_processes(self):
|
||||
"""Get the maximum number of processes showed in the UI."""
|
||||
|
|
@ -398,6 +403,14 @@ class GlancesProcesses(object):
|
|||
else:
|
||||
self.auto_sort = auto
|
||||
self._sort_key = key
|
||||
|
||||
def kill(self, pid, timeout=3):
|
||||
"""Kill process with pid"""
|
||||
assert pid != os.getpid(), "Glances can kill itself..."
|
||||
p = psutil.Process(pid)
|
||||
logger.debug('Send kill signal to process: {}'.format(p))
|
||||
p.kill()
|
||||
return p.wait(timeout)
|
||||
|
||||
|
||||
def weighted(value):
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class GlancesStaticServer(object):
|
|||
for s in ['name', 'port', 'alias']:
|
||||
new_server[s] = config.get_value(self._section, '%s%s' % (postfix, s))
|
||||
if new_server['name'] is not None:
|
||||
# Manage optionnal information
|
||||
# Manage optional information
|
||||
if new_server['port'] is None:
|
||||
new_server['port'] = '61209'
|
||||
new_server['username'] = 'glances'
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# install with base requirements file
|
||||
-r requirements.txt
|
||||
|
||||
bernhard
|
||||
bottle
|
||||
cassandra-driver
|
||||
|
|
@ -5,6 +8,7 @@ couchdb
|
|||
docker>=2.0.0
|
||||
elasticsearch
|
||||
influxdb
|
||||
influxdb-client; python_version >= "3.6"
|
||||
kafka-python
|
||||
netifaces
|
||||
py3nvml; python_version >= "3.0"
|
||||
|
|
@ -12,7 +16,7 @@ paho-mqtt
|
|||
pika
|
||||
potsdb
|
||||
prometheus_client
|
||||
py-cpuinfo
|
||||
py-cpuinfo<=4.0.0
|
||||
pygal
|
||||
pymdstat
|
||||
pysnmp
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
psutil==5.7.0
|
||||
psutil==5.8.0
|
||||
future
|
||||
|
|
|
|||
3
setup.py
3
setup.py
|
|
@ -55,7 +55,7 @@ def get_install_extras_require():
|
|||
# Zeroconf 0.19.1 is the latest one compatible with Python 2 (issue #1293)
|
||||
'browser': ['zeroconf==0.19.1' if PY2 else 'zeroconf>=0.19.1'],
|
||||
'cloud': ['requests'],
|
||||
'cpuinfo': ['py-cpuinfo'],
|
||||
'cpuinfo': ['py-cpuinfo<=4.0.0'],
|
||||
'docker': ['docker>=2.0.0'],
|
||||
'export': ['bernhard', 'cassandra-driver', 'couchdb', 'elasticsearch',
|
||||
'influxdb>=1.0.0', 'kafka-python', 'pika', 'paho-mqtt', 'potsdb',
|
||||
|
|
@ -135,6 +135,7 @@ setup(
|
|||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Programming Language :: Python :: 3.9',
|
||||
'Topic :: System :: Monitoring'
|
||||
]
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue