mirror of
https://github.com/nicolargo/glances.git
synced 2024-12-23 01:01:31 +03:00
Merge branch 'develop' into issue2225
This commit is contained in:
commit
25c0a1c9a7
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -104,7 +104,7 @@ jobs:
|
||||
|
||||
- name: Retrieve Repository Docker metadata
|
||||
id: docker_meta
|
||||
uses: crazy-max/ghaction-docker-meta@v4.1.1
|
||||
uses: crazy-max/ghaction-docker-meta@v4.3.0
|
||||
with:
|
||||
images: ${{ env.DEFAULT_DOCKER_IMAGE }}
|
||||
labels: |
|
||||
@ -136,7 +136,7 @@ jobs:
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Build and push image
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
push: ${{ env.PUSH_BRANCH == 'true' }}
|
||||
tags: "${{ env.DEFAULT_DOCKER_IMAGE }}:${{ matrix.os != 'alpine' && format('{0}-', matrix.os) || '' }}${{ matrix.tag.tag }}"
|
||||
|
14
Makefile
14
Makefile
@ -137,6 +137,11 @@ docker-alpine: ## Generate local docker images (Alpine)
|
||||
docker build --target minimal -f ./docker-files/alpine.Dockerfile -t glances:local-alpine-minimal .
|
||||
docker build --target dev -f ./docker-files/alpine.Dockerfile -t glances:local-alpine-dev .
|
||||
|
||||
docker-ubuntu: ## Generate local docker images (Ubuntu)
|
||||
docker build --target full -f ./docker-files/ubuntu.Dockerfile -t glances:local-ubuntu-full .
|
||||
docker build --target minimal -f ./docker-files/ubuntu.Dockerfile -t glances:local-ubuntu-minimal .
|
||||
docker build --target dev -f ./docker-files/ubuntu.Dockerfile -t glances:local-ubuntu-dev .
|
||||
|
||||
# ===================================================================
|
||||
# Run
|
||||
# ===================================================================
|
||||
@ -159,6 +164,15 @@ run-docker-alpine-full: ## Start Glances Alpine Docker full in console mode
|
||||
run-docker-alpine-dev: ## Start Glances Alpine Docker dev in console mode
|
||||
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-alpine-dev
|
||||
|
||||
run-docker-ubuntu-minimal: ## Start Glances Ubuntu Docker minimal in console mode
|
||||
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-ubuntu-minimal
|
||||
|
||||
run-docker-ubuntu-full: ## Start Glances Ubuntu Docker full in console mode
|
||||
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-ubuntu-full
|
||||
|
||||
run-docker-ubuntu-dev: ## Start Glances Ubuntu Docker dev in console mode
|
||||
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-ubuntu-dev
|
||||
|
||||
run-webserver: ## Start Glances in Web server mode
|
||||
./venv/bin/python -m glances -C ./conf/glances.conf -w
|
||||
|
||||
|
73
NEWS.rst
73
NEWS.rst
@ -2,11 +2,82 @@
|
||||
Glances changelog
|
||||
==============================================================================
|
||||
|
||||
===============
|
||||
Version 3.4.0
|
||||
===============
|
||||
|
||||
See roadmap here: https://github.com/nicolargo/glances/issues?q=is%3Aopen+is%3Aissue+milestone%3A%22Glances+3.4.0%22
|
||||
|
||||
===============
|
||||
Version 3.3.1.1
|
||||
===============
|
||||
|
||||
Hard patch on the master branch.
|
||||
|
||||
Bug corrected:
|
||||
|
||||
* "ModuleNotFoundError: No module named 'ujson'" #2246
|
||||
* Remove surrounding quotes for quoted command arguments #2247 (related to #2239)
|
||||
|
||||
===============
|
||||
Version 3.3.1
|
||||
===============
|
||||
|
||||
Under development, see milestone https://github.com/nicolargo/glances/milestone/61
|
||||
Enhancements:
|
||||
|
||||
* Minor change on the help screen
|
||||
* Refactor some loop in the processes function
|
||||
* Replace json by ujson #2201
|
||||
|
||||
Bug corrected:
|
||||
|
||||
* Unable to see docker related information #2180
|
||||
* CSV export dependent on sort order for docker container cpu #2156
|
||||
* Error when process list is displayed in Programs mode #2209
|
||||
* Console formatting permanently messed up when other text printed #2211
|
||||
* API GET uptime returns formatted string, not seconds as the doc says #2158
|
||||
* Glances UI is breaking for multiline commands #2189
|
||||
|
||||
Documentation and CI:
|
||||
|
||||
* Add unitary test for memory profiling
|
||||
* Update memory profile chart
|
||||
* Add run-docker-ubuntu-* in Makefile
|
||||
* The open-web-browser option was missing dashes #2219
|
||||
* Correct regexp in glances.conf file example
|
||||
* What is CW from network #2222 (related to discussion #2221)
|
||||
* Change Glances repology URL
|
||||
* Add example for the date format
|
||||
* Correct Flake8 configuration file
|
||||
* Drop UT for Python 3.5 and 3.6 (no more available in Ubuntu 22.04)
|
||||
* Correct unitary test with Python 3.5
|
||||
* Update Makefile with comments
|
||||
* Update Python minimal requirement for py3nvlm
|
||||
* Update security policy (user can open private issue directly in Github)
|
||||
* Add a simple run script. Entry point for IDE debuger
|
||||
|
||||
Cyber security update:
|
||||
|
||||
* Security alert on ujson < 5.4
|
||||
* Merge pull request #2243 from nicolargo/renovate/nvidia-cuda-12.x
|
||||
* Merge pull request #2244 from nicolargo/renovate/crazy-max-ghaction-docker-meta-4.x
|
||||
* Merge pull request #2228 from nicolargo/renovate/zeroconf-0.x
|
||||
* Merge pull request #2242 from nicolargo/renovate/crazy-max-ghaction-docker-meta-4.x
|
||||
* Merge pull request #2239 from mfridge/action-command-split
|
||||
* Merge pull request #2165 from nicolargo/renovate/zeroconf-0.x
|
||||
* Merge pull request #2199 from nicolargo/renovate/alpine-3.x
|
||||
* Merge pull request #2202 from chncaption/oscs_fix_cdr0ts8au51t49so8c6g
|
||||
* Bump loader-utils from 2.0.0 to 2.0.3 in /glances/outputs/static #2187 - Update Web lib
|
||||
|
||||
Contributors for this version:
|
||||
|
||||
* Nicolargo
|
||||
* renovate[bot]
|
||||
* chncaption
|
||||
* fkwong
|
||||
* *mfridge
|
||||
|
||||
And also a big thanks to @RazCrimson (https://github.com/RazCrimson) for the support to the Glances community !
|
||||
|
||||
===============
|
||||
Version 3.3.0.4
|
||||
|
21
README.rst
21
README.rst
@ -40,16 +40,22 @@ Glances - An eye on your system
|
||||
Summary
|
||||
=======
|
||||
|
||||
**Glances** is a cross-platform monitoring tool which aims to present a
|
||||
large amount of monitoring information through a curses or Web
|
||||
based interface. The information dynamically adapts depending on the
|
||||
size of the user interface.
|
||||
**Glances** is an open-source system cross-platform monitoring tool.
|
||||
It allows real-time monitoring of various aspects of your system such as
|
||||
CPU, memory, disk, network usage etc. It also allows monitoring of running processes,
|
||||
logged in users, temperatures, voltages, fan speeds etc.
|
||||
It also supports container monitoring, it supports different container management
|
||||
systems such as Docker, LXC. The information is presented in an easy to read dashboard
|
||||
and can also be used for remote monitoring of systems via a web interface or command
|
||||
line interface. It is easy to install and use and can be customized to show only
|
||||
the information that you are interested in.
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/nicolargo/glances/develop/docs/_static/glances-summary.png
|
||||
|
||||
It can also work in client/server mode. Remote monitoring could be done
|
||||
via terminal, Web interface or API (XML-RPC and RESTful). Stats can also
|
||||
be exported to files or external time/value databases.
|
||||
In client/server mode, remote monitoring could be done via terminal,
|
||||
Web interface or API (XML-RPC and RESTful).
|
||||
Stats can also be exported to files or external time/value databases, CSV or direct
|
||||
output to STDOUT.
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/nicolargo/glances/develop/docs/_static/glances-responsive-webdesign.png
|
||||
|
||||
@ -111,6 +117,7 @@ Optional dependencies:
|
||||
- ``py-cpuinfo`` (for the Quicklook CPU info module)
|
||||
- ``pygal`` (for the graph export module)
|
||||
- ``pymdstat`` (for RAID support) [Linux-only]
|
||||
- ``pymongo`` (for the MongoDB export module) [Only for Python >= 3.7]
|
||||
- ``pysnmp`` (for SNMP support)
|
||||
- ``pySMART.smartx`` (for HDD Smart support) [Linux-only]
|
||||
- ``pyzmq`` (for the ZeroMQ export module)
|
||||
|
@ -307,6 +307,7 @@ battery_critical=95
|
||||
#core 0_fans_speed_alias=CPU Core 0 fan
|
||||
#or
|
||||
#core 0_alias=CPU Core 0
|
||||
#core 1_alias=CPU Core 1
|
||||
|
||||
[processcount]
|
||||
disable=False
|
||||
@ -583,6 +584,15 @@ db=glances
|
||||
#user=root
|
||||
#password=root
|
||||
|
||||
[mongodb]
|
||||
# Configuration for the --export mongodb option
|
||||
# https://www.mongodb.com
|
||||
host=localhost
|
||||
port=27017
|
||||
db=glances
|
||||
user=root
|
||||
password=example
|
||||
|
||||
[kafka]
|
||||
# Configuration for the --export kafka option
|
||||
# http://kafka.apache.org/
|
||||
|
@ -9,3 +9,4 @@ codespell
|
||||
memory-profiler
|
||||
matplotlib
|
||||
setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
|
||||
numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability
|
@ -10,8 +10,10 @@ refresh=2
|
||||
# Does Glances should check if a newer version is available on PyPI ?
|
||||
check_update=false
|
||||
# History size (maximum number of values)
|
||||
# Default is 3600 seconds (1 hour)
|
||||
history_size=3600
|
||||
# Default is 1200 values (~1h with the default refresh rate)
|
||||
history_size=1200
|
||||
# Set the way Glances should display the date (default is %Y-%m-%d %H:%M:%S %Z)
|
||||
#strftime_format="%Y-%m-%d %H:%M:%S %Z"
|
||||
|
||||
##############################################################################
|
||||
# User interface
|
||||
@ -212,7 +214,7 @@ critical=-85
|
||||
disable=False
|
||||
# Define the list of hidden disks (comma-separated regexp)
|
||||
#hide=sda2,sda5,loop.*
|
||||
hide=loop.*,/dev/loop*
|
||||
hide=loop.*,/dev/loop.*
|
||||
# Define the list of disks to be show (comma-separated)
|
||||
#show=sda.*
|
||||
# Alias for sda1
|
||||
@ -582,6 +584,15 @@ db=glances
|
||||
#user=root
|
||||
#password=root
|
||||
|
||||
[mongodb]
|
||||
# Configuration for the --export mongodb option
|
||||
# https://www.mongodb.com
|
||||
host=localhost
|
||||
port=27017
|
||||
db=glances
|
||||
user=root
|
||||
password=example
|
||||
|
||||
[kafka]
|
||||
# Configuration for the --export kafka option
|
||||
# http://kafka.apache.org/
|
||||
|
@ -26,6 +26,7 @@ RUN apk add --no-cache \
|
||||
curl \
|
||||
lm-sensors \
|
||||
wireless-tools \
|
||||
smartmontools \
|
||||
iputils
|
||||
|
||||
##############################################################################
|
||||
@ -89,9 +90,11 @@ RUN apk add --no-cache \
|
||||
python3 \
|
||||
py3-packaging \
|
||||
py3-dateutil \
|
||||
py3-requests \
|
||||
curl \
|
||||
lm-sensors \
|
||||
wireless-tools \
|
||||
smartmontools \
|
||||
iputils
|
||||
|
||||
COPY --from=buildRequirements /root/.local/bin /usr/local/bin/
|
||||
|
146
docker-files/ubuntu.Dockerfile
Normal file
146
docker-files/ubuntu.Dockerfile
Normal file
@ -0,0 +1,146 @@
|
||||
#
|
||||
# Glances Dockerfile (based on Ubuntu)
|
||||
#
|
||||
# https://github.com/nicolargo/glances
|
||||
#
|
||||
|
||||
# WARNING: the versions should be set.
|
||||
# Ex: Python 3.10 for Ubuntu 22.04
|
||||
# Note: ENV is for future running containers. ARG for building your Docker image.
|
||||
|
||||
ARG IMAGE_VERSION=12.0.1-base-ubuntu22.04
|
||||
ARG PYTHON_VERSION=3.10
|
||||
ARG PIP_MIRROR=https://mirrors.aliyun.com/pypi/simple/
|
||||
FROM nvidia/cuda:${IMAGE_VERSION} as build
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
python3 \
|
||||
python3-dev \
|
||||
python3-pip \
|
||||
python3-wheel \
|
||||
musl-dev \
|
||||
build-essential \
|
||||
libzmq5 \
|
||||
curl \
|
||||
lm-sensors \
|
||||
wireless-tools \
|
||||
smartmontools \
|
||||
net-tools \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
##############################################################################
|
||||
# Install the dependencies beforehand to make them cacheable
|
||||
|
||||
FROM build as buildRequirements
|
||||
ARG PYTHON_VERSION
|
||||
ARG PIP_MIRROR
|
||||
|
||||
ARG PIP_MIRROR=https://mirrors.aliyun.com/pypi/simple/
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN python${PYTHON_VERSION} -m pip install --no-cache-dir --user -r requirements.txt -i ${PIP_MIRROR}
|
||||
|
||||
# Minimal means no webui, but it break what is done previously (see #2155)
|
||||
# So install the webui requirements...
|
||||
COPY webui-requirements.txt .
|
||||
RUN python${PYTHON_VERSION} -m pip install --no-cache-dir --user -r webui-requirements.txt -i ${PIP_MIRROR}
|
||||
|
||||
# As minimal image we want to monitor others docker containers
|
||||
RUN python${PYTHON_VERSION} -m pip install --no-cache-dir --user docker -i ${PIP_MIRROR}
|
||||
|
||||
# Force install otherwise it could be cached without rerun
|
||||
ARG CHANGING_ARG
|
||||
RUN python${PYTHON_VERSION} -m pip install --no-cache-dir --user glances -i ${PIP_MIRROR}
|
||||
|
||||
##############################################################################
|
||||
|
||||
FROM build as buildOptionalRequirements
|
||||
ARG PYTHON_VERSION
|
||||
ARG PIP_MIRROR
|
||||
|
||||
COPY requirements.txt .
|
||||
COPY optional-requirements.txt .
|
||||
RUN CASS_DRIVER_NO_CYTHON=1 pip3 install --no-cache-dir --user -r optional-requirements.txt -i ${PIP_MIRROR}
|
||||
|
||||
##############################################################################
|
||||
# full image
|
||||
##############################################################################
|
||||
|
||||
FROM build as full
|
||||
ARG PYTHON_VERSION
|
||||
|
||||
COPY --from=buildRequirements /root/.local/bin /root/.local/bin/
|
||||
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
|
||||
COPY --from=buildOptionalRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
|
||||
COPY ./docker-compose/glances.conf /etc/glances.conf
|
||||
|
||||
# EXPOSE PORT (XMLRPC / WebUI)
|
||||
EXPOSE 61209 61208
|
||||
|
||||
# Define default command.
|
||||
WORKDIR /glances
|
||||
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT
|
||||
|
||||
##############################################################################
|
||||
# minimal image
|
||||
##############################################################################
|
||||
|
||||
# Create running images without any building dependency
|
||||
FROM nvidia/cuda:${IMAGE_VERSION} as minimal
|
||||
ARG PYTHON_VERSION
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
python3 \
|
||||
python3-packaging \
|
||||
python3-dateutil \
|
||||
python3-requests \
|
||||
curl \
|
||||
lm-sensors \
|
||||
wireless-tools \
|
||||
smartmontools \
|
||||
net-tools \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=buildRequirements /root/.local/bin /root/.local/bin/
|
||||
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
|
||||
COPY ./docker-compose/glances.conf /etc/glances.conf
|
||||
|
||||
# EXPOSE PORT (XMLRPC / WebUI)
|
||||
EXPOSE 61209 61208
|
||||
|
||||
# Define default command.
|
||||
WORKDIR /glances
|
||||
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT
|
||||
|
||||
##############################################################################
|
||||
# dev image
|
||||
##############################################################################
|
||||
|
||||
FROM full as dev
|
||||
ARG PYTHON_VERSION
|
||||
|
||||
COPY --from=buildRequirements /root/.local/bin /root/.local/bin/
|
||||
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
|
||||
COPY --from=buildOptionalRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
|
||||
COPY ./docker-compose/glances.conf /etc/glances.conf
|
||||
|
||||
# Copy the current Glances source code
|
||||
COPY . /glances
|
||||
|
||||
# EXPOSE PORT (XMLRPC / WebUI)
|
||||
EXPOSE 61209 61208
|
||||
|
||||
# Forward access and error logs to Docker's log collector
|
||||
RUN ln -sf /dev/stdout /tmp/glances-root.log \
|
||||
&& ln -sf /dev/stderr /var/log/error.log
|
||||
|
||||
# Define default command.
|
||||
WORKDIR /glances
|
||||
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT
|
Binary file not shown.
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 33 KiB |
Binary file not shown.
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@ -37,3 +37,9 @@ or another example:
|
||||
|
||||
[diskio]
|
||||
show=sda.*
|
||||
|
||||
Filtering is based on regular expression. Please be sure that your regular
|
||||
expression works as expected. You can use an online tool like `regex101`_ in
|
||||
order to test your regular expression.
|
||||
|
||||
.. _regex101: https://regex101.com/
|
@ -47,4 +47,9 @@ under the ``[docker]`` section:
|
||||
|
||||
You can use all the variables ({{foo}}) available in the Docker plugin.
|
||||
|
||||
Filtering (for hide or show) is based on regular expression. Please be sure that your regular
|
||||
expression works as expected. You can use an online tool like `regex101`_ in
|
||||
order to test your regular expression.
|
||||
|
||||
.. _regex101: https://regex101.com/
|
||||
.. _docker-py: https://github.com/docker/docker-py
|
||||
|
@ -53,3 +53,9 @@ Example to only show /dev/sdb mount points:
|
||||
|
||||
[fs]
|
||||
show=/dev/sdb.*
|
||||
|
||||
Filtering is based on regular expression. Please be sure that your regular
|
||||
expression works as expected. You can use an online tool like `regex101`_ in
|
||||
order to test your regular expression.
|
||||
|
||||
.. _regex101: https://regex101.com/
|
@ -22,7 +22,9 @@ file under the ``[ip]`` section:
|
||||
|
||||
|
||||
**NOTE:** Setting low values for `public_refresh_interval` will result in frequent
|
||||
HTTP requests to the IP detection servers. Recommended range: 120-600 seconds
|
||||
HTTP requests to the IP detection servers. Recommended range: 120-600 seconds.
|
||||
Glances uses online services in order to get the IP addresses. Your IP address could be
|
||||
blocked if too many requests are done.
|
||||
|
||||
If the Censys options are configured, the public IP address is also analysed (with the same interval)
|
||||
and additional information is displayed.
|
||||
|
@ -53,3 +53,9 @@ virtual docker interface (docker0, docker1, ...):
|
||||
wlan0_tx_warning=900000
|
||||
wlan0_tx_critical=1000000
|
||||
wlan0_tx_log=True
|
||||
|
||||
Filtering is based on regular expression. Please be sure that your regular
|
||||
expression works as expected. You can use an online tool like `regex101`_ in
|
||||
order to test your regular expression.
|
||||
|
||||
.. _regex101: https://regex101.com/
|
1282
docs/api.rst
1282
docs/api.rst
File diff suppressed because it is too large
Load Diff
@ -9,42 +9,35 @@ following:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[couchdb]
|
||||
[mongodb]
|
||||
host=localhost
|
||||
port=5984
|
||||
user=root
|
||||
password=root
|
||||
port=27017
|
||||
db=glances
|
||||
user=root
|
||||
password=example
|
||||
|
||||
and run Glances with:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ glances --export couchdb
|
||||
$ glances --export mongodb
|
||||
|
||||
Documents are stored in native ``JSON`` format. Glances adds ``"type"``
|
||||
and ``"time"`` entries:
|
||||
Documents are stored in native the configured database (glances by default)
|
||||
with one collection per plugin.
|
||||
|
||||
- ``type``: plugin name
|
||||
- ``time``: timestamp (format: "2016-09-24T16:39:08.524828Z")
|
||||
|
||||
Example of Couch Document for the load stats:
|
||||
Example of MongoDB Document for the load stats:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"_id": "36cbbad81453c53ef08804cb2612d5b6",
|
||||
"_rev": "1-382400899bec5615cabb99aa34df49fb",
|
||||
"min15": 0.33,
|
||||
"time": "2016-09-24T16:39:08.524828Z",
|
||||
"min5": 0.4,
|
||||
"cpucore": 4,
|
||||
"load_warning": 1,
|
||||
"min1": 0.5,
|
||||
"history_size": 28800,
|
||||
"load_critical": 5,
|
||||
"type": "load",
|
||||
"load_careful": 0.7
|
||||
_id: ObjectId('63d78ffee5528e543ce5af3a'),
|
||||
min1: 1.46337890625,
|
||||
min5: 1.09619140625,
|
||||
min15: 1.07275390625,
|
||||
cpucore: 4,
|
||||
history_size: 1200,
|
||||
load_disable: 'False',
|
||||
load_careful: 0.7,
|
||||
load_warning: 1,
|
||||
load_critical: 5
|
||||
}
|
||||
|
||||
You can view the result using the CouchDB utils URL: http://127.0.0.1:5984/_utils/database.html?glances.
|
||||
|
@ -18,6 +18,7 @@ to providing stats to multiple services (see list below).
|
||||
json
|
||||
kafka
|
||||
mqtt
|
||||
mongodb
|
||||
opentsdb
|
||||
prometheus
|
||||
rabbitmq
|
||||
|
50
docs/gw/mongodb.rst
Normal file
50
docs/gw/mongodb.rst
Normal file
@ -0,0 +1,50 @@
|
||||
.. _couchdb:
|
||||
|
||||
MongoDB
|
||||
=======
|
||||
|
||||
You can export statistics to a ``MongoDB`` server.
|
||||
The connection should be defined in the Glances configuration file as
|
||||
following:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[couchdb]
|
||||
host=localhost
|
||||
port=
|
||||
user=root
|
||||
password=example
|
||||
db=glances
|
||||
|
||||
and run Glances with:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ glances --export couchdb
|
||||
|
||||
Documents are stored in native ``JSON`` format. Glances adds ``"type"``
|
||||
and ``"time"`` entries:
|
||||
|
||||
- ``type``: plugin name
|
||||
- ``time``: timestamp (format: "2016-09-24T16:39:08.524828Z")
|
||||
|
||||
Example of Couch Document for the load stats:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"_id": "36cbbad81453c53ef08804cb2612d5b6",
|
||||
"_rev": "1-382400899bec5615cabb99aa34df49fb",
|
||||
"min15": 0.33,
|
||||
"time": "2016-09-24T16:39:08.524828Z",
|
||||
"min5": 0.4,
|
||||
"cpucore": 4,
|
||||
"load_warning": 1,
|
||||
"min1": 0.5,
|
||||
"history_size": 28800,
|
||||
"load_critical": 5,
|
||||
"type": "load",
|
||||
"load_careful": 0.7
|
||||
}
|
||||
|
||||
You can view the result using the CouchDB utils URL: http://127.0.0.1:5984/_utils/database.html?glances.
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "GLANCES" "1" "Dec 21, 2022" "3.3.1_beta1" "Glances"
|
||||
.TH "GLANCES" "1" "Jan 30, 2023" "3.4.0_beta1" "Glances"
|
||||
.SH NAME
|
||||
glances \- An eye on your system
|
||||
.SH SYNOPSIS
|
||||
@ -258,7 +258,7 @@ set the server cache time [default: 1 sec]
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B open\-web\-browser
|
||||
.B \-\-open\-web\-browser
|
||||
try to open the Web UI in the default Web browser
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
@ -732,60 +732,60 @@ format):
|
||||
.nf
|
||||
.ft C
|
||||
{
|
||||
"version": 1,
|
||||
"disable_existing_loggers": "False",
|
||||
"root": {
|
||||
"level": "INFO",
|
||||
"handlers": ["file", "console"]
|
||||
\(dqversion\(dq: 1,
|
||||
\(dqdisable_existing_loggers\(dq: \(dqFalse\(dq,
|
||||
\(dqroot\(dq: {
|
||||
\(dqlevel\(dq: \(dqINFO\(dq,
|
||||
\(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq]
|
||||
},
|
||||
"formatters": {
|
||||
"standard": {
|
||||
"format": "%(asctime)s \-\- %(levelname)s \-\- %(message)s"
|
||||
\(dqformatters\(dq: {
|
||||
\(dqstandard\(dq: {
|
||||
\(dqformat\(dq: \(dq%(asctime)s \-\- %(levelname)s \-\- %(message)s\(dq
|
||||
},
|
||||
"short": {
|
||||
"format": "%(levelname)s: %(message)s"
|
||||
\(dqshort\(dq: {
|
||||
\(dqformat\(dq: \(dq%(levelname)s: %(message)s\(dq
|
||||
},
|
||||
"free": {
|
||||
"format": "%(message)s"
|
||||
\(dqfree\(dq: {
|
||||
\(dqformat\(dq: \(dq%(message)s\(dq
|
||||
}
|
||||
},
|
||||
"handlers": {
|
||||
"file": {
|
||||
"level": "DEBUG",
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"formatter": "standard",
|
||||
"filename": "/var/tmp/glances.log"
|
||||
\(dqhandlers\(dq: {
|
||||
\(dqfile\(dq: {
|
||||
\(dqlevel\(dq: \(dqDEBUG\(dq,
|
||||
\(dqclass\(dq: \(dqlogging.handlers.RotatingFileHandler\(dq,
|
||||
\(dqformatter\(dq: \(dqstandard\(dq,
|
||||
\(dqfilename\(dq: \(dq/var/tmp/glances.log\(dq
|
||||
},
|
||||
"console": {
|
||||
"level": "CRITICAL",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "free"
|
||||
\(dqconsole\(dq: {
|
||||
\(dqlevel\(dq: \(dqCRITICAL\(dq,
|
||||
\(dqclass\(dq: \(dqlogging.StreamHandler\(dq,
|
||||
\(dqformatter\(dq: \(dqfree\(dq
|
||||
}
|
||||
},
|
||||
"loggers": {
|
||||
"debug": {
|
||||
"handlers": ["file", "console"],
|
||||
"level": "DEBUG"
|
||||
\(dqloggers\(dq: {
|
||||
\(dqdebug\(dq: {
|
||||
\(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
|
||||
\(dqlevel\(dq: \(dqDEBUG\(dq
|
||||
},
|
||||
"verbose": {
|
||||
"handlers": ["file", "console"],
|
||||
"level": "INFO"
|
||||
\(dqverbose\(dq: {
|
||||
\(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
|
||||
\(dqlevel\(dq: \(dqINFO\(dq
|
||||
},
|
||||
"standard": {
|
||||
"handlers": ["file"],
|
||||
"level": "INFO"
|
||||
\(dqstandard\(dq: {
|
||||
\(dqhandlers\(dq: [\(dqfile\(dq],
|
||||
\(dqlevel\(dq: \(dqINFO\(dq
|
||||
},
|
||||
"requests": {
|
||||
"handlers": ["file", "console"],
|
||||
"level": "ERROR"
|
||||
\(dqrequests\(dq: {
|
||||
\(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
|
||||
\(dqlevel\(dq: \(dqERROR\(dq
|
||||
},
|
||||
"elasticsearch": {
|
||||
"handlers": ["file", "console"],
|
||||
"level": "ERROR"
|
||||
\(dqelasticsearch\(dq: {
|
||||
\(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
|
||||
\(dqlevel\(dq: \(dqERROR\(dq
|
||||
},
|
||||
"elasticsearch.trace": {
|
||||
"handlers": ["file", "console"],
|
||||
"level": "ERROR"
|
||||
\(dqelasticsearch.trace\(dq: {
|
||||
\(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
|
||||
\(dqlevel\(dq: \(dqERROR\(dq
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -885,6 +885,6 @@ $ glances –browser
|
||||
.sp
|
||||
Nicolas Hennion aka Nicolargo <\fI\%contact@nicolargo.com\fP>
|
||||
.SH COPYRIGHT
|
||||
2022, Nicolas Hennion
|
||||
2023, Nicolas Hennion
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
@ -19,7 +19,7 @@ import sys
|
||||
# Global name
|
||||
# Version should start and end with a numerical char
|
||||
# See https://packaging.python.org/specifications/core-metadata/#version
|
||||
__version__ = '3.3.1_beta1'
|
||||
__version__ = '3.4.0_beta1'
|
||||
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
|
||||
__license__ = 'LGPLv3'
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances - An eye on your system
|
||||
|
@ -75,7 +75,7 @@ class GlancesClientBrowser(object):
|
||||
# Try with the preconfigure password (only if status is PROTECTED)
|
||||
clear_password = self.password.get_password(server['name'])
|
||||
if clear_password is not None:
|
||||
server['password'] = self.password.sha256_hash(clear_password)
|
||||
server['password'] = self.password.get_hash(clear_password)
|
||||
return 'http://{}:{}@{}:{}'.format(server['username'], server['password'], server['ip'], server['port'])
|
||||
else:
|
||||
return 'http://{}:{}'.format(server['ip'], server['port'])
|
||||
@ -151,7 +151,7 @@ class GlancesClientBrowser(object):
|
||||
)
|
||||
# Store the password for the selected server
|
||||
if clear_password is not None:
|
||||
self.set_in_selected('password', self.password.sha256_hash(clear_password))
|
||||
self.set_in_selected('password', self.password.get_hash(clear_password))
|
||||
|
||||
# Display the Glance client on the selected server
|
||||
logger.info("Connect Glances client to the {} server".format(server['key']))
|
||||
|
@ -68,6 +68,10 @@ if PY3:
|
||||
return s.decode()
|
||||
return s.encode('ascii', 'ignore').decode()
|
||||
|
||||
def to_hex(s):
|
||||
"""Convert the bytes string to a hex string"""
|
||||
return s.hex()
|
||||
|
||||
def listitems(d):
|
||||
return list(d.items())
|
||||
|
||||
@ -166,6 +170,10 @@ else:
|
||||
return s
|
||||
return unicodedata.normalize('NFKD', s).encode('ascii', 'ignore')
|
||||
|
||||
def to_hex(s):
|
||||
"""Convert the string to a hex string in Python 2"""
|
||||
return s.encode('hex')
|
||||
|
||||
def listitems(d):
|
||||
return d.items()
|
||||
|
||||
|
@ -81,10 +81,10 @@ class Export(GlancesExport):
|
||||
# Loop over plugins to export
|
||||
for plugin in self.plugins_to_export(stats):
|
||||
if isinstance(all_stats[plugin], list):
|
||||
for stat in all_stats[plugin]:
|
||||
for stat in sorted(all_stats[plugin], key=lambda x: x['key']):
|
||||
# First line: header
|
||||
if self.first_line:
|
||||
csv_header += ('{}_{}_{}'.format(plugin, self.get_item_key(stat), item) for item in stat)
|
||||
csv_header += ['{}_{}_{}'.format(plugin, self.get_item_key(stat), item) for item in stat]
|
||||
# Others lines: stats
|
||||
csv_data += itervalues(stat)
|
||||
elif isinstance(all_stats[plugin], dict):
|
||||
|
81
glances/exports/glances_mongodb.py
Normal file
81
glances/exports/glances_mongodb.py
Normal file
@ -0,0 +1,81 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2023 Nicolas Hennion <nicolas@nicolargo.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-only
|
||||
#
|
||||
|
||||
"""MongoDB interface class."""
|
||||
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.exports.glances_export import GlancesExport
|
||||
|
||||
import pymongo
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
|
||||
class Export(GlancesExport):
|
||||
|
||||
"""This class manages the MongoDB export module."""
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
"""Init the MongoDB export IF."""
|
||||
super(Export, self).__init__(config=config, args=args)
|
||||
|
||||
# Mandatory configuration keys (additional to host and port)
|
||||
self.db = None
|
||||
|
||||
# Optional configuration keys
|
||||
self.user = None
|
||||
self.password = None
|
||||
|
||||
# Load the Cassandra configuration file section
|
||||
self.export_enable = self.load_conf('mongodb', mandatories=['host', 'port', 'db'], options=['user', 'password'])
|
||||
if not self.export_enable:
|
||||
sys.exit(2)
|
||||
|
||||
# Init the CouchDB client
|
||||
self.client = self.init()
|
||||
|
||||
def init(self):
|
||||
"""Init the connection to the CouchDB server."""
|
||||
if not self.export_enable:
|
||||
return None
|
||||
|
||||
server_uri = 'mongodb://%s:%s@%s:%s' % (quote_plus(self.user),
|
||||
quote_plus(self.password),
|
||||
self.host,
|
||||
self.port)
|
||||
|
||||
try:
|
||||
client = pymongo.MongoClient(server_uri)
|
||||
client.admin.command('ping')
|
||||
except Exception as e:
|
||||
logger.critical("Cannot connect to MongoDB server %s:%s (%s)" % (self.host, self.port, e))
|
||||
sys.exit(2)
|
||||
else:
|
||||
logger.info("Connected to the MongoDB server")
|
||||
|
||||
return client
|
||||
|
||||
def database(self):
|
||||
"""Return the CouchDB database object"""
|
||||
return self.client[self.db]
|
||||
|
||||
def export(self, name, columns, points):
|
||||
"""Write the points to the MongoDB server."""
|
||||
logger.debug("Export {} stats to MongoDB".format(name))
|
||||
|
||||
# Create DB input
|
||||
data = dict(zip(columns, points))
|
||||
|
||||
# Write data to the MongoDB database
|
||||
try:
|
||||
self.database()[name].insert_one(data)
|
||||
except Exception as e:
|
||||
logger.error("Cannot export {} stats to MongoDB ({})".format(name, e))
|
@ -127,8 +127,10 @@ class GlancesBottle(object):
|
||||
if username == self.args.username:
|
||||
from glances.password import GlancesPassword
|
||||
|
||||
pwd = GlancesPassword(username=username, config=self.config)
|
||||
return pwd.check_password(self.args.password, pwd.sha256_hash(password))
|
||||
pwd = GlancesPassword(username=username,
|
||||
config=self.config)
|
||||
return pwd.check_password(self.args.password,
|
||||
pwd.get_hash(password))
|
||||
else:
|
||||
return False
|
||||
|
||||
@ -160,6 +162,7 @@ class GlancesBottle(object):
|
||||
'/api/%s/<plugin>/<item>/history/<nb:int>' % self.API_VERSION, method="GET", callback=self._api_item_history
|
||||
)
|
||||
self._app.route('/api/%s/<plugin>/<item>/<value>' % self.API_VERSION, method="GET", callback=self._api_value)
|
||||
self._app.route('/api/%s/<plugin>/<item>/<value:path>' % self.API_VERSION, method="GET", callback=self._api_value)
|
||||
bindmsg = 'Glances RESTful API Server started on {}api/{}/'.format(self.bind_url, self.API_VERSION)
|
||||
logger.info(bindmsg)
|
||||
|
||||
|
@ -123,6 +123,7 @@
|
||||
v-if="!args.disable_sensors"
|
||||
:data="data"
|
||||
></glances-plugin-sensors>
|
||||
<glances-plugin-now :data="data"></glances-plugin-now>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-18">
|
||||
@ -138,13 +139,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-24">
|
||||
<glances-plugin-now :data="data"></glances-plugin-now>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
|
869
glances/outputs/static/package-lock.json
generated
869
glances/outputs/static/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,27 +3,27 @@
|
||||
"dependencies": {
|
||||
"bootstrap": "^3.4.1",
|
||||
"favico.js": "^0.3.10",
|
||||
"hotkeys-js": "^3.10.0",
|
||||
"hotkeys-js": "^3.10.1",
|
||||
"lodash": "^4.17.21",
|
||||
"sanitize-html": "^2.7.2",
|
||||
"vue": "^3.2.41"
|
||||
"sanitize-html": "^2.8.1",
|
||||
"vue": "^3.2.45"
|
||||
},
|
||||
"devDependencies": {
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"css-loader": "^6.7.3",
|
||||
"del": "^7.0.0",
|
||||
"eslint": "^8.25.0",
|
||||
"eslint-plugin-vue": "^9.6.0",
|
||||
"eslint": "^8.32.0",
|
||||
"eslint-plugin-vue": "^9.9.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"less": "^4.1.3",
|
||||
"less-loader": "^11.1.0",
|
||||
"sass": "^1.55.0",
|
||||
"sass-loader": "^13.1.0",
|
||||
"sass": "^1.57.1",
|
||||
"sass-loader": "^13.2.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"url-loader": "^4.1.1",
|
||||
"vue-loader": "^17.0.0",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"vue-loader": "^17.0.1",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack-dev-server": "^4.11.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
12
glances/outputs/static/public/glances.js
vendored
12
glances/outputs/static/public/glances.js
vendored
File diff suppressed because one or more lines are too long
@ -16,7 +16,7 @@ import sys
|
||||
import uuid
|
||||
from io import open
|
||||
|
||||
from glances.compat import b, input
|
||||
from glances.compat import b, input, to_hex
|
||||
from glances.config import user_config_dir
|
||||
from glances.globals import safe_makedirs
|
||||
from glances.logger import logger
|
||||
@ -36,25 +36,26 @@ class GlancesPassword(object):
|
||||
|
||||
def local_password_path(self):
|
||||
"""Return the local password path.
|
||||
Related toissue: Password files in same configuration dir in effect #2143
|
||||
Related to issue: Password files in same configuration dir in effect #2143
|
||||
"""
|
||||
if self.config is None:
|
||||
return user_config_dir()
|
||||
else:
|
||||
return self.config.get_value('passwords', 'local_password_path', default=user_config_dir())
|
||||
|
||||
def sha256_hash(self, plain_password):
|
||||
"""Return the SHA-256 of the given password."""
|
||||
return hashlib.sha256(b(plain_password)).hexdigest()
|
||||
|
||||
def get_hash(self, salt, plain_password):
|
||||
"""Return the hashed password, salt + SHA-256."""
|
||||
return hashlib.sha256(salt.encode() + plain_password.encode()).hexdigest()
|
||||
def get_hash(self, plain_password, salt=''):
|
||||
"""Return the hashed password, salt + pbkdf2_hmac."""
|
||||
return to_hex(hashlib.pbkdf2_hmac('sha256',
|
||||
plain_password.encode(),
|
||||
salt.encode(),
|
||||
100000,
|
||||
dklen=128))
|
||||
|
||||
def hash_password(self, plain_password):
|
||||
"""Hash password with a salt based on UUID (universally unique identifier)."""
|
||||
salt = uuid.uuid4().hex
|
||||
encrypted_password = self.get_hash(salt, plain_password)
|
||||
encrypted_password = self.get_hash(plain_password,
|
||||
salt=salt)
|
||||
return salt + '$' + encrypted_password
|
||||
|
||||
def check_password(self, hashed_password, plain_password):
|
||||
@ -63,7 +64,8 @@ class GlancesPassword(object):
|
||||
Return the comparison with the encrypted_password.
|
||||
"""
|
||||
salt, encrypted_password = hashed_password.split('$')
|
||||
re_encrypted_password = self.get_hash(salt, plain_password)
|
||||
re_encrypted_password = self.get_hash(plain_password,
|
||||
salt = salt)
|
||||
return encrypted_password == re_encrypted_password
|
||||
|
||||
def get_password(self, description='', confirm=False, clear=False):
|
||||
@ -72,11 +74,11 @@ class GlancesPassword(object):
|
||||
For Glances server, get the password (confirm=True, clear=False):
|
||||
1) from the password file (if it exists)
|
||||
2) from the CLI
|
||||
Optionally: save the password to a file (hashed with salt + SHA-256)
|
||||
Optionally: save the password to a file (hashed with salt + SHA-pbkdf2_hmac)
|
||||
|
||||
For Glances client, get the password (confirm=False, clear=True):
|
||||
1) from the CLI
|
||||
2) the password is hashed with SHA-256 (only SHA string transit
|
||||
2) the password is hashed with SHA-pbkdf2_hmac (only SHA string transit
|
||||
through the network)
|
||||
"""
|
||||
if os.path.exists(self.password_file) and not clear:
|
||||
@ -84,21 +86,21 @@ class GlancesPassword(object):
|
||||
logger.info("Read password from file {}".format(self.password_file))
|
||||
password = self.load_password()
|
||||
else:
|
||||
# password_sha256 is the plain SHA-256 password
|
||||
# password_hashed is the salt + SHA-256 password
|
||||
password_sha256 = self.sha256_hash(getpass.getpass(description))
|
||||
password_hashed = self.hash_password(password_sha256)
|
||||
# password_hash is the plain SHA-pbkdf2_hmac password
|
||||
# password_hashed is the salt + SHA-pbkdf2_hmac password
|
||||
password_hash = self.get_hash(getpass.getpass(description))
|
||||
password_hashed = self.hash_password(password_hash)
|
||||
if confirm:
|
||||
# password_confirm is the clear password (only used to compare)
|
||||
password_confirm = self.sha256_hash(getpass.getpass('Password (confirm): '))
|
||||
password_confirm = self.get_hash(getpass.getpass('Password (confirm): '))
|
||||
|
||||
if not self.check_password(password_hashed, password_confirm):
|
||||
logger.critical("Sorry, passwords do not match. Exit.")
|
||||
sys.exit(1)
|
||||
|
||||
# Return the plain SHA-256 or the salted password
|
||||
# Return the plain SHA-pbkdf2_hmac or the salted password
|
||||
if clear:
|
||||
password = password_sha256
|
||||
password = password_hash
|
||||
else:
|
||||
password = password_hashed
|
||||
|
||||
|
@ -29,50 +29,26 @@ import psutil
|
||||
# 'key': 'interface_name'}
|
||||
# Fields description
|
||||
fields_description = {
|
||||
'interface_name': {
|
||||
'description': 'Interface name.',
|
||||
'unit': 'string'
|
||||
},
|
||||
'alias': {
|
||||
'description': 'Interface alias name (optional).',
|
||||
'unit': 'string'
|
||||
},
|
||||
'rx': {
|
||||
'description': 'The received/input rate (in bit per second).',
|
||||
'unit': 'bps'
|
||||
},
|
||||
'tx': {
|
||||
'description': 'The sent/output rate (in bit per second).',
|
||||
'unit': 'bps'
|
||||
},
|
||||
'cx': {
|
||||
'description': 'The cumulative received+sent rate (in bit per second).',
|
||||
'unit': 'bps'
|
||||
},
|
||||
'interface_name': {'description': 'Interface name.', 'unit': 'string'},
|
||||
'alias': {'description': 'Interface alias name (optional).', 'unit': 'string'},
|
||||
'rx': {'description': 'The received/input rate (in bit per second).', 'unit': 'bps'},
|
||||
'tx': {'description': 'The sent/output rate (in bit per second).', 'unit': 'bps'},
|
||||
'cx': {'description': 'The cumulative received+sent rate (in bit per second).', 'unit': 'bps'},
|
||||
'cumulative_rx': {
|
||||
'description': 'The number of bytes received through the interface (cumulative).',
|
||||
'unit': 'bytes',
|
||||
},
|
||||
'cumulative_tx': {
|
||||
'description': 'The number of bytes sent through the interface (cumulative).',
|
||||
'unit': 'bytes'
|
||||
},
|
||||
'cumulative_tx': {'description': 'The number of bytes sent through the interface (cumulative).', 'unit': 'bytes'},
|
||||
'cumulative_cx': {
|
||||
'description': 'The cumulative number of bytes reveived and sent through the interface (cumulative).',
|
||||
'unit': 'bytes'
|
||||
'unit': 'bytes',
|
||||
},
|
||||
'speed': {
|
||||
'description': 'Maximum interface speed (in bit per second). Can return 0 on some operating-system.',
|
||||
'unit': 'bps',
|
||||
},
|
||||
'is_up': {
|
||||
'description': 'Is the interface up ?',
|
||||
'unit': 'bool'
|
||||
},
|
||||
'time_since_update': {
|
||||
'description': 'Number of seconds since last update.',
|
||||
'unit': 'seconds'
|
||||
},
|
||||
'is_up': {'description': 'Is the interface up ?', 'unit': 'bool'},
|
||||
'time_since_update': {'description': 'Number of seconds since last update.', 'unit': 'seconds'},
|
||||
}
|
||||
|
||||
# SNMP OID
|
||||
|
@ -383,17 +383,19 @@ class GlancesProcesses(object):
|
||||
# Build the processes stats list (it is why we need psutil>=5.3.0)
|
||||
# This is one of the main bottleneck of Glances (see flame graph)
|
||||
# Filter processes
|
||||
self.processlist = list(filter(lambda p: not (BSD and p.info['name'] == 'idle') and
|
||||
not (WINDOWS and p.info['name'] == 'System Idle Process') and
|
||||
not (MACOS and p.info['name'] == 'kernel_task') and
|
||||
not (self.no_kernel_threads and LINUX and p.info['gids'].real == 0),
|
||||
psutil.process_iter(attrs=sorted_attrs, ad_value=None)))
|
||||
self.processlist = list(
|
||||
filter(
|
||||
lambda p: not (BSD and p.info['name'] == 'idle')
|
||||
and not (WINDOWS and p.info['name'] == 'System Idle Process')
|
||||
and not (MACOS and p.info['name'] == 'kernel_task')
|
||||
and not (self.no_kernel_threads and LINUX and p.info['gids'].real == 0),
|
||||
psutil.process_iter(attrs=sorted_attrs, ad_value=None),
|
||||
)
|
||||
)
|
||||
# Only get the info key
|
||||
self.processlist = [p.info for p in self.processlist]
|
||||
# Sort the processes list by the current sort_key
|
||||
self.processlist = sort_stats(self.processlist,
|
||||
sorted_by=self.sort_key,
|
||||
reverse=True)
|
||||
self.processlist = sort_stats(self.processlist, sorted_by=self.sort_key, reverse=True)
|
||||
|
||||
# Update the processcount
|
||||
self.update_processcount(self.processlist)
|
||||
@ -470,8 +472,7 @@ class GlancesProcesses(object):
|
||||
self.processlist_cache[proc['pid']] = {cached: proc[cached] for cached in cached_attrs}
|
||||
|
||||
# Apply user filter
|
||||
self.processlist = list(filter(lambda p: not self._filter.is_filtered(p),
|
||||
self.processlist))
|
||||
self.processlist = list(filter(lambda p: not self._filter.is_filtered(p), self.processlist))
|
||||
|
||||
# Compute the maximum value for keys in self._max_values_list: CPU, MEM
|
||||
# Useful to highlight the processes with maximum values
|
||||
|
@ -36,7 +36,7 @@ def processes_to_programs(processes):
|
||||
'name': p['name'],
|
||||
'cmdline': [p['name']],
|
||||
'pid': '_',
|
||||
'username': p['username'],
|
||||
'username': p['username'] if 'username' in p else '_',
|
||||
'nice': p['nice'],
|
||||
'status': p['status'],
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
from glances.compat import nativestr
|
||||
from subprocess import Popen, PIPE
|
||||
import re
|
||||
|
||||
|
||||
def secure_popen(cmd):
|
||||
@ -48,8 +49,9 @@ def __secure_popen(cmd):
|
||||
p_last = None
|
||||
# Split by pipe '|'
|
||||
for sub_cmd in cmd.split('|'):
|
||||
# Split by space ' '
|
||||
sub_cmd_split = [i for i in sub_cmd.split(' ') if i]
|
||||
# Split by space character, but do no split spaces within quotes (remove surrounding quotes, though)
|
||||
tmp_split = [_ for _ in list(filter(None, re.split(r'(\s+)|(".*?"+?)|(\'.*?\'+?)', sub_cmd))) if _ != ' ']
|
||||
sub_cmd_split = [_[1:-1] if (_[0]==_[-1]=='"') or (_[0]==_[-1]=='\'') else _ for _ in tmp_split]
|
||||
p = Popen(sub_cmd_split, shell=False, stdin=sub_cmd_stdin, stdout=PIPE, stderr=PIPE)
|
||||
if p_last is not None:
|
||||
# Allow p_last to receive a SIGPIPE if p exits.
|
||||
|
@ -118,7 +118,7 @@ class GlancesStats(object):
|
||||
if args is not None:
|
||||
# If the all key is set in the disable_plugin option then look in the enable_plugin option
|
||||
if getattr(args, 'disable_all', False):
|
||||
logger.info('%s => %s', name, getattr(args, 'enable_' + name, False))
|
||||
logger.debug('%s => %s', name, getattr(args, 'enable_' + name, False))
|
||||
setattr(args, 'disable_' + name, not getattr(args, 'enable_' + name, False))
|
||||
else:
|
||||
setattr(args, 'disable_' + name, getattr(args, 'disable_' + name, False))
|
||||
|
@ -22,6 +22,7 @@ potsdb
|
||||
prometheus_client
|
||||
pygal
|
||||
pymdstat
|
||||
pymongo; python_version >= "3.7"
|
||||
pysnmp
|
||||
pySMART.smartx
|
||||
python-dateutil
|
||||
@ -32,5 +33,5 @@ six
|
||||
sparklines
|
||||
statsd
|
||||
wifi
|
||||
zeroconf==0.47.0; python_version < "3.7"
|
||||
zeroconf==0.47.1; python_version < "3.7"
|
||||
zeroconf; python_version >= "3.7"
|
||||
|
17
setup.py
17
setup.py
@ -41,7 +41,16 @@ def get_data_files():
|
||||
|
||||
|
||||
def get_install_requires():
|
||||
requires = ['psutil>=5.3.0', 'defusedxml', 'future', 'packaging']
|
||||
requires = [
|
||||
'psutil>=5.6.7',
|
||||
'defusedxml',
|
||||
'packaging',
|
||||
'future; python_version < "3.0"',
|
||||
'ujson<3; python_version < "3.0"',
|
||||
'ujson<4; python_version >= "3.5" and python_version < "3.6"',
|
||||
'ujson<5; python_version >= "3.6" and python_version < "3.7"',
|
||||
'ujson>=5.4.0; python_version >= "3.7"',
|
||||
]
|
||||
if sys.platform.startswith('win'):
|
||||
requires.append('bottle')
|
||||
requires.append('requests')
|
||||
@ -52,12 +61,12 @@ def get_install_requires():
|
||||
def get_install_extras_require():
|
||||
extras_require = {
|
||||
'action': ['chevron'],
|
||||
'browser': ['zeroconf==0.47.0' if PY2 else 'zeroconf>=0.19.1'],
|
||||
'browser': ['zeroconf==0.47.1' if PY2 else 'zeroconf>=0.19.1'],
|
||||
'cloud': ['requests'],
|
||||
'docker': ['docker>=2.0.0', 'python-dateutil', 'six'],
|
||||
'export': ['bernhard', 'cassandra-driver', 'couchdb', 'elasticsearch',
|
||||
'graphitesender', 'influxdb>=1.0.0', 'kafka-python', 'pika',
|
||||
'paho-mqtt', 'potsdb', 'prometheus_client', 'pyzmq',
|
||||
'graphitesender', 'influxdb>=1.0.0', 'kafka-python', 'pymongo',
|
||||
'pika', 'paho-mqtt', 'potsdb', 'prometheus_client', 'pyzmq',
|
||||
'statsd'],
|
||||
'folders': ['scandir'], # python_version<"3.5"
|
||||
'graph': ['pygal'],
|
||||
|
Loading…
Reference in New Issue
Block a user