From e798fb4f6367c01115279a388795a1e4345933d7 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Tue, 13 Jul 2021 19:32:38 +0200 Subject: Add API doc for CPU (not completed) --- glances/__init__.py | 2 +- glances/main.py | 2 ++ glances/plugins/glances_cpu.py | 44 ++++++++++++++++++++++++++++++++++++++- glances/plugins/glances_plugin.py | 6 +++++- glances/standalone.py | 5 +++++ 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/glances/__init__.py b/glances/__init__.py index 1f270d50..40002a77 100644 --- a/glances/__init__.py +++ b/glances/__init__.py @@ -110,7 +110,7 @@ def start(config, args): # Start the main loop logger.debug("Glances started in {} seconds".format(start_duration.get())) - if args.stdout_issue: + if args.stdout_issue or args.stdout_fields: # Serve once for issue/test mode mode.serve_issue() else: diff --git a/glances/main.py b/glances/main.py index 88b27038..d7ba181e 100644 --- a/glances/main.py +++ b/glances/main.py @@ -230,6 +230,8 @@ Examples of use: dest='stdout_csv', help='display stats to stdout, csv format (comma separated list of plugins/plugins.attribute)') parser.add_argument('--issue', default=None, action='store_true', dest='stdout_issue', help='test all plugins and exit (please copy/paste the output if you open an issue)') + parser.add_argument('--fields', '--api-doc', default=None, action='store_true', + dest='stdout_fields', help='display fields descriptions') if not WINDOWS: parser.add_argument('--hide-kernel-threads', action='store_true', default=False, dest='no_kernel_threads', help='hide kernel threads in process list (not available on Windows)') diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 1e582dc3..781f89b3 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -29,6 +29,47 @@ from glances.plugins.glances_plugin import GlancesPlugin import psutil +# Fields description +# {'total': 19.7, 'user': 3.4, 'nice': 0.0, 'system': 2.6, 'idle': 93.0, 'iowait': 0.1, 'irq': 0.0, 'softirq': 0.8, 'steal': 0.0, 'guest': 0.0, 'guest_nice': 0.0, 'time_since_update': 2.1306779384613037, 'cpucore': 4, 'ctx_switches': 11636, 'interrupts': 4463, 'soft_interrupts': 3227, 'syscalls': 0} +fields_description = { + 'total': {'description': 'Sum of all CPU percentages (except idle).', + 'unit': 'percent'}, + 'system': {'description': 'percent time spent in kernel space. System CPU time is the \ +time spent running code in the Operating System kernel.', + 'unit': 'percent'}, + 'user': {'description': 'CPU percent time spent in user space. \ +User CPU time is the time spent on the processor running your program\'s code (or code in libraries).', + 'unit': 'percent'}, + 'iowait': {'description': '*(Linux)*: percent time spent by the CPU waiting for I/O \ +operations to complete.', + 'unit': 'percent'}, + 'idle': {'description': 'percent of CPU used by any program. Every program or task \ +that runs on a computer system occupies a certain amount of processing \ +time on the CPU. If the CPU has completed all tasks it is idle.', + 'unit': 'percent'}, + 'irq': {'description': '*(Linux and BSD)*: percent time spent servicing/handling \ +hardware/software interrupts. Time servicing interrupts (hardware + \ +software).', + 'unit': 'percent'}, + 'nice': {'description': '*(Unix)*: percent time occupied by user level processes with \ +a positive nice value. The time the CPU has spent running users\' \ +processes that have been *niced*.', + 'unit': 'percent'}, + 'steal': {'description': '*(Linux)*: percentage of time a virtual CPU waits for a real \ +CPU while the hypervisor is servicing another virtual processor.', + 'unit': 'percent'}, + 'ctx_sw': {'description': 'number of context switches (voluntary + involuntary) per \ +second. A context switch is a procedure that a computer\'s CPU (central \ +processing unit) follows to change from one task (or process) to \ +another while ensuring that the tasks do not conflict.', + 'unit': 'percent'}, + 'inter': {'description': 'number of interrupts per second.', + 'unit': 'percent'}, + 'sw_int': {'description': 'number of software interrupts per second. Always set to \ +0 on Windows and SunOS.', + 'unit': 'percent'}, +} + # SNMP OID # percentage of user CPU time: .1.3.6.1.4.1.2021.11.9.0 # percentages of system CPU time: .1.3.6.1.4.1.2021.11.10.0 @@ -64,7 +105,8 @@ class Plugin(GlancesPlugin): """Init the CPU plugin.""" super(Plugin, self).__init__(args=args, config=config, - items_history_list=items_history_list) + items_history_list=items_history_list, + fields_description=fields_description) # We want to display the stat in the curse interface self.display_curse = True diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py index 73cc7fd9..48bc9375 100644 --- a/glances/plugins/glances_plugin.py +++ b/glances/plugins/glances_plugin.py @@ -44,7 +44,8 @@ class GlancesPlugin(object): args=None, config=None, items_history_list=None, - stats_init_value={}): + stats_init_value={}, + fields_description=None): """Init the plugin of plugins class. All Glances' plugins should inherit from this class. Most of the @@ -107,6 +108,9 @@ class GlancesPlugin(object): # Set the initial refresh time to display stats the first time self.refresh_timer = Timer(0) + # Init stats description + self.fields_description = fields_description + # Init the stats self.stats_init_value = stats_init_value self.stats = None diff --git a/glances/standalone.py b/glances/standalone.py index d6a07f2f..f95d79ff 100644 --- a/glances/standalone.py +++ b/glances/standalone.py @@ -30,6 +30,7 @@ from glances.outputs.glances_curses import GlancesCursesStandalone from glances.outputs.glances_stdout import GlancesStdout from glances.outputs.glances_stdout_csv import GlancesStdoutCsv from glances.outputs.glances_stdout_issue import GlancesStdoutIssue +from glances.outputs.glances_stdout_fields import GlancesStdoutFieldsDescription from glances.outdated import Outdated from glances.timer import Counter @@ -87,6 +88,10 @@ class GlancesStandalone(object): logger.info("Issue mode is ON") # Init screen self.screen = GlancesStdoutIssue(config=config, args=args) + elif args.stdout_fields: + logger.info("Fields descriptions mode is ON") + # Init screen + self.screen = GlancesStdoutFieldsDescription(config=config, args=args) elif args.stdout: logger.info("Stdout mode is ON, following stats will be displayed: {}".format(args.stdout)) # Init screen -- cgit v1.2.3 From 2bae8cb79f3ebc92c61906c1b32d80e4415c9426 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Wed, 14 Jul 2021 19:00:11 +0200 Subject: Add API doc for CPU --- glances/outputs/glances_stdout_fields.py | 73 ++++++++++++++++++++++++++++++++ glances/plugins/glances_cpu.py | 17 +++++--- 2 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 glances/outputs/glances_stdout_fields.py diff --git a/glances/outputs/glances_stdout_fields.py b/glances/outputs/glances_stdout_fields.py new file mode 100644 index 00000000..de7a1391 --- /dev/null +++ b/glances/outputs/glances_stdout_fields.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Glances. +# +# Copyright (C) 2021 Nicolargo +# +# 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 . + +"""Fields description interface class.""" + +from pprint import pformat + +from glances.logger import logger +from glances.compat import iteritems + + +class GlancesStdoutFieldsDescription(object): + + """ + This class manages the fields description display. + """ + + def __init__(self, config=None, args=None): + # Init + self.config = config + self.args = args + + def end(self): + pass + + def update(self, + stats, + duration=3): + """Display issue + """ + print('.. _apidoc:') + print('') + print('API documentation') + print('=================') + print('') + for plugin in sorted(stats._plugins): + print('{}'.format(plugin)) + print('-' * len(plugin)) + if stats._plugins[plugin].fields_description: + print('') + for field, description in iteritems(stats._plugins[plugin].fields_description): + print('* **{}**: {} (unit is *{}*)'.format(field, + description['description'][:-1] if description['description'].endswith('.') else description['description'], + description['unit'])) + print('') + print('Output example:') + print('') + print('.. code-block:: json') + print('') + print(' # curl http://localhost:61208/api/3/{}'.format(plugin)) + print(' ' + pformat(stats._plugins[plugin].get_export()).replace('\n', '\n ')) + print('') + else: + logger.error('No fields_description variable defined for plugin {}'.format(plugin)) + + # Return True to exit directly (no refresh) + return True diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 781f89b3..90670123 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -30,7 +30,6 @@ from glances.plugins.glances_plugin import GlancesPlugin import psutil # Fields description -# {'total': 19.7, 'user': 3.4, 'nice': 0.0, 'system': 2.6, 'idle': 93.0, 'iowait': 0.1, 'irq': 0.0, 'softirq': 0.8, 'steal': 0.0, 'guest': 0.0, 'guest_nice': 0.0, 'time_since_update': 2.1306779384613037, 'cpucore': 4, 'ctx_switches': 11636, 'interrupts': 4463, 'soft_interrupts': 3227, 'syscalls': 0} fields_description = { 'total': {'description': 'Sum of all CPU percentages (except idle).', 'unit': 'percent'}, @@ -58,16 +57,20 @@ processes that have been *niced*.', 'steal': {'description': '*(Linux)*: percentage of time a virtual CPU waits for a real \ CPU while the hypervisor is servicing another virtual processor.', 'unit': 'percent'}, - 'ctx_sw': {'description': 'number of context switches (voluntary + involuntary) per \ + 'ctx_switches': {'description': 'number of context switches (voluntary + involuntary) per \ second. A context switch is a procedure that a computer\'s CPU (central \ processing unit) follows to change from one task (or process) to \ another while ensuring that the tasks do not conflict.', - 'unit': 'percent'}, - 'inter': {'description': 'number of interrupts per second.', - 'unit': 'percent'}, - 'sw_int': {'description': 'number of software interrupts per second. Always set to \ + 'unit': 'percent'}, + 'interrupts': {'description': 'number of interrupts per second.', + 'unit': 'percent'}, + 'soft_interrupts': {'description': 'number of software interrupts per second. Always set to \ 0 on Windows and SunOS.', - 'unit': 'percent'}, + 'unit': 'percent'}, + 'cpucore': {'description': 'Total number of CPU core.', + 'unit': 'count'}, + 'time_since_update': {'description': 'Number of seconds since last update.', + 'unit': 'seconds'}, } # SNMP OID -- cgit v1.2.3 From 9a3b3b6ac337c85fcf4f3f6c839b04b591228d3f Mon Sep 17 00:00:00 2001 From: nicolargo Date: Wed, 14 Jul 2021 19:16:09 +0200 Subject: Add API doc for MEM --- glances/plugins/glances_cpu.py | 2 +- glances/plugins/glances_mem.py | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 90670123..389c3563 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -84,7 +84,7 @@ snmp_oid = {'default': {'user': '1.3.6.1.4.1.2021.11.9.0', 'esxi': {'percent': '1.3.6.1.2.1.25.3.3.1.2'}, 'netapp': {'system': '1.3.6.1.4.1.789.1.2.1.3.0', 'idle': '1.3.6.1.4.1.789.1.2.1.5.0', - 'nb_log_core': '1.3.6.1.4.1.789.1.2.1.6.0'}} + 'cpucore': '1.3.6.1.4.1.789.1.2.1.6.0'}} # Define the history items list # - 'name' define the stat identifier diff --git a/glances/plugins/glances_mem.py b/glances/plugins/glances_mem.py index 417483a3..79c13c9c 100644 --- a/glances/plugins/glances_mem.py +++ b/glances/plugins/glances_mem.py @@ -25,6 +25,37 @@ from glances.plugins.glances_plugin import GlancesPlugin import psutil +# Fields description +fields_description = { + 'total': {'description': 'Total physical memory available.', + 'unit': 'bytes'}, + 'available': {'description': 'The actual amount of available memory that can be given instantly \ +to processes that request more memory in bytes; this is calculated by summing \ +different memory values depending on the platform (e.g. free + buffers + cached on Linux) \ +and it is supposed to be used to monitor actual memory usage in a cross platform fashion.', + 'unit': 'bytes'}, + 'percent': {'description': 'The percentage usage calculated as (total - available) / total * 100.', + 'unit': 'percent'}, + 'used': {'description': 'Memory used, calculated differently depending on the platform and \ +designed for informational purposes only.', + 'unit': 'bytes'}, + 'free': {'description': 'Memory not being used at all (zeroed) that is readily available; \ +note that this doesn\'t reflect the actual memory available (use \'available\' instead).', + 'unit': 'bytes'}, + 'active': {'description': '*(UNIX)*: memory currently in use or very recently used, and so it is in RAM.', + 'unit': 'bytes'}, + 'inactive': {'description': '*(UNIX)*: memory that is marked as not used.', + 'unit': 'bytes'}, + 'buffers': {'description': '*(Linux, BSD)*: cache for things like file system metadata.', + 'unit': 'bytes'}, + 'cached': {'description': '*(Linux, BSD)*: cache for various things.', + 'unit': 'bytes'}, + 'wired': {'description': '*(BSD, macOS)*: memory that is marked to always stay in RAM. It is never moved to disk.', + 'unit': 'bytes'}, + 'shared': {'description': '*(BSD)*: memory that may be simultaneously accessed by multiple processes.', + 'unit': 'bytes'}, +} + # SNMP OID # Total RAM in machine: .1.3.6.1.4.1.2021.4.5.0 # Total RAM used: .1.3.6.1.4.1.2021.4.6.0 @@ -64,7 +95,8 @@ class Plugin(GlancesPlugin): """Init the plugin.""" super(Plugin, self).__init__(args=args, config=config, - items_history_list=items_history_list) + items_history_list=items_history_list, + fields_description=fields_description) # We want to display the stat in the curse interface self.display_curse = True -- cgit v1.2.3 From dad4d2846d43489d6b0f8fb29afe923384a06170 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Thu, 15 Jul 2021 10:49:57 +0200 Subject: Add load and memswap --- glances/outputs/glances_stdout_fields.py | 16 +++++++++----- glances/plugins/glances_cpu.py | 2 +- glances/plugins/glances_load.py | 21 ++++++++++++++++++- glances/plugins/glances_memswap.py | 36 +++++++++++++++++++++++++++++--- 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/glances/outputs/glances_stdout_fields.py b/glances/outputs/glances_stdout_fields.py index de7a1391..9afe7db5 100644 --- a/glances/outputs/glances_stdout_fields.py +++ b/glances/outputs/glances_stdout_fields.py @@ -46,20 +46,26 @@ class GlancesStdoutFieldsDescription(object): """ print('.. _apidoc:') print('') - print('API documentation') - print('=================') + print('Restfull/API plugins documentation') + print('==================================') + print('') + print('The Glanes Restfull/API server could be ran using the following command line:') + print('') + print('.. code-block:: bash') + print('') + print(' # glances -w --disable-webui') print('') for plugin in sorted(stats._plugins): - print('{}'.format(plugin)) - print('-' * len(plugin)) if stats._plugins[plugin].fields_description: + print('{}'.format(plugin)) + print('-' * len(plugin)) print('') for field, description in iteritems(stats._plugins[plugin].fields_description): print('* **{}**: {} (unit is *{}*)'.format(field, description['description'][:-1] if description['description'].endswith('.') else description['description'], description['unit'])) print('') - print('Output example:') + print('GET {} plugin stats:'.format(plugin)) print('') print('.. code-block:: json') print('') diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 389c3563..acf0d6d2 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -68,7 +68,7 @@ another while ensuring that the tasks do not conflict.', 0 on Windows and SunOS.', 'unit': 'percent'}, 'cpucore': {'description': 'Total number of CPU core.', - 'unit': 'count'}, + 'unit': 'number'}, 'time_since_update': {'description': 'Number of seconds since last update.', 'unit': 'seconds'}, } diff --git a/glances/plugins/glances_load.py b/glances/plugins/glances_load.py index ab96ff0d..29a50cdf 100644 --- a/glances/plugins/glances_load.py +++ b/glances/plugins/glances_load.py @@ -27,6 +27,24 @@ from glances.plugins.glances_core import Plugin as CorePlugin from glances.plugins.glances_plugin import GlancesPlugin from glances.logger import logger +# Fields description +fields_description = { + 'min1': {'description': 'Average sum of the number of processes \ +waiting in the run-queue plus the number currently executing \ +over 1 minute.', + 'unit': 'number'}, + 'min5': {'description': 'Average sum of the number of processes \ +waiting in the run-queue plus the number currently executing \ +over 5 minutes.', + 'unit': 'number'}, + 'min15': {'description': 'Average sum of the number of processes \ +waiting in the run-queue plus the number currently executing \ +over 15 minutes.', + 'unit': 'number'}, + 'cpucore': {'description': 'Total number of CPU core.', + 'unit': 'number'}, +} + # SNMP OID # 1 minute Load: .1.3.6.1.4.1.2021.10.1.3.1 # 5 minute Load: .1.3.6.1.4.1.2021.10.1.3.2 @@ -55,7 +73,8 @@ class Plugin(GlancesPlugin): """Init the plugin.""" super(Plugin, self).__init__(args=args, config=config, - items_history_list=items_history_list) + items_history_list=items_history_list, + fields_description=fields_description) # We want to display the stat in the curse interface self.display_curse = True diff --git a/glances/plugins/glances_memswap.py b/glances/plugins/glances_memswap.py index 06924def..7f3f0726 100644 --- a/glances/plugins/glances_memswap.py +++ b/glances/plugins/glances_memswap.py @@ -20,10 +20,35 @@ """Swap memory plugin.""" from glances.compat import iterkeys +from glances.timer import getTimeSinceLastUpdate from glances.plugins.glances_plugin import GlancesPlugin import psutil +# Fields description + # 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) +fields_description = { + 'total': {'description': 'Total swap memory.', + 'unit': 'bytes'}, + 'used': {'description': 'Used swap memory.', + 'unit': 'bytes'}, + 'free': {'description': 'Free swap memory.', + 'unit': 'bytes'}, + 'percent': {'description': 'Used swap memory in percentage.', + 'unit': 'percent'}, + 'sin': {'description': 'The number of bytes the system has swapped in from disk (cumulative).', + 'unit': 'bytes'}, + 'sout': {'description': 'The number of bytes the system has swapped out from disk (cumulative).', + 'unit': 'bytes'}, + 'time_since_update': {'description': 'Number of seconds since last update.', + 'unit': 'seconds'}, +} + # SNMP OID # Total Swap Size: .1.3.6.1.4.1.2021.4.3.0 # Available Swap Space: .1.3.6.1.4.1.2021.4.4.0 @@ -51,7 +76,8 @@ class Plugin(GlancesPlugin): """Init the plugin.""" super(Plugin, self).__init__(args=args, config=config, - items_history_list=items_history_list) + items_history_list=items_history_list, + fields_description=fields_description) # We want to display the stat in the curse interface self.display_curse = True @@ -78,12 +104,16 @@ class Plugin(GlancesPlugin): # 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) + # 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) + + # By storing time data we enable sin/s and sout/s calculations in the + # XML/RPC API, which would otherwise be overly difficult work + # for users of the API + stats['time_since_update'] = getTimeSinceLastUpdate('memswap') elif self.input_method == 'snmp': # Update stats using SNMP if self.short_system_name == 'windows': -- cgit v1.2.3 From 1865384954cd640f719c1eee9607e6ddd637c1ff Mon Sep 17 00:00:00 2001 From: nicolargo Date: Thu, 15 Jul 2021 11:16:29 +0200 Subject: Add network --- glances/outputs/glances_stdout_fields.py | 9 +++++++-- glances/plugins/glances_network.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/glances/outputs/glances_stdout_fields.py b/glances/outputs/glances_stdout_fields.py index 9afe7db5..b61d89da 100644 --- a/glances/outputs/glances_stdout_fields.py +++ b/glances/outputs/glances_stdout_fields.py @@ -49,7 +49,7 @@ class GlancesStdoutFieldsDescription(object): print('Restfull/API plugins documentation') print('==================================') print('') - print('The Glanes Restfull/API server could be ran using the following command line:') + print('The Glances Restfull/API server could be ran using the following command line:') print('') print('.. code-block:: bash') print('') @@ -70,7 +70,12 @@ class GlancesStdoutFieldsDescription(object): print('.. code-block:: json') print('') print(' # curl http://localhost:61208/api/3/{}'.format(plugin)) - print(' ' + pformat(stats._plugins[plugin].get_export()).replace('\n', '\n ')) + stat = stats._plugins[plugin].get_export() + if isinstance(stat, list) and len(stat) > 1: + # Only display two first items + print(' ' + pformat(stat[0:2]).replace('\n', '\n ')) + else: + print(' ' + pformat(stat).replace('\n', '\n ')) print('') else: logger.error('No fields_description variable defined for plugin {}'.format(plugin)) diff --git a/glances/plugins/glances_network.py b/glances/plugins/glances_network.py index cde30510..46d19261 100644 --- a/glances/plugins/glances_network.py +++ b/glances/plugins/glances_network.py @@ -29,6 +29,36 @@ from glances.logger import logger import psutil +# {'interface_name': 'mpqemubr0-dummy', +# 'alias': None, +# 'time_since_update': 2.081636428833008, +# 'cumulative_rx': 0, +# 'rx': 0, 'cumulative_tx': 0, 'tx': 0, 'cumulative_cx': 0, 'cx': 0, +# 'is_up': False, +# 'speed': 0, +# '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'}, + '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'}, + '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'}, +} + # SNMP OID # http://www.net-snmp.org/docs/mibs/interfaces.html # Dict key = interface_name @@ -56,6 +86,7 @@ class Plugin(GlancesPlugin): super(Plugin, self).__init__(args=args, config=config, items_history_list=items_history_list, + fields_description=fields_description, stats_init_value=[]) # We want to display the stat in the curse interface -- cgit v1.2.3 From 11908c6a9f7b659b3801ebf713e3b2f506aa991c Mon Sep 17 00:00:00 2001 From: nicolargo Date: Fri, 16 Jul 2021 09:57:33 +0200 Subject: Add core docs --- glances/plugins/glances_core.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/glances/plugins/glances_core.py b/glances/plugins/glances_core.py index f731593c..5a56ac75 100644 --- a/glances/plugins/glances_core.py +++ b/glances/plugins/glances_core.py @@ -23,6 +23,17 @@ from glances.plugins.glances_plugin import GlancesPlugin import psutil +# Fields description + + # - phys: physical cores only (hyper thread CPUs are excluded) + # - log: logical CPUs in the system +fields_description = { + 'phys': {'description': 'Number of physical cores (hyper thread CPUs are excluded).', + 'unit': 'number'}, + 'log': {'description': 'Number of logical CPUs. A logical CPU is the number of \ +physical cores multiplied by the number of threads that can run on each core.', + 'unit': 'number'}, +} class Plugin(GlancesPlugin): """Glances CPU core plugin. @@ -34,7 +45,9 @@ class Plugin(GlancesPlugin): def __init__(self, args=None, config=None): """Init the plugin.""" - super(Plugin, self).__init__(args=args, config=config) + super(Plugin, self).__init__(args=args, + config=config, + fields_description=fields_description) # We dot not want to display the stat in the curse interface # The core number is displayed by the load plugin -- cgit v1.2.3 From 04bad352e6a054a9e001282f797c8e71608fe0b8 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Fri, 16 Jul 2021 15:39:24 +0200 Subject: Get specific item --- Makefile | 3 ++ glances/__init__.py | 2 +- glances/main.py | 4 +- glances/outputs/glances_stdout_fields.py | 84 -------------------------------- glances/plugins/glances_memswap.py | 6 --- glances/processes.py | 3 ++ glances/standalone.py | 6 +-- 7 files changed, 12 insertions(+), 96 deletions(-) delete mode 100644 glances/outputs/glances_stdout_fields.py diff --git a/Makefile b/Makefile index ebc54687..9f5a80b5 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,9 @@ run-debug: venv run-webserver: venv ./venv/bin/python -m glances -C ./conf/glances.conf -w +run-restapiserver: venv + ./venv/bin/python -m glances -C ./conf/glances.conf -w --disable-webui + run-server: venv ./venv/bin/python -m glances -C ./conf/glances.conf -s diff --git a/glances/__init__.py b/glances/__init__.py index 40002a77..dfe1591c 100644 --- a/glances/__init__.py +++ b/glances/__init__.py @@ -110,7 +110,7 @@ def start(config, args): # Start the main loop logger.debug("Glances started in {} seconds".format(start_duration.get())) - if args.stdout_issue or args.stdout_fields: + if args.stdout_issue or args.stdout_apidoc: # Serve once for issue/test mode mode.serve_issue() else: diff --git a/glances/main.py b/glances/main.py index d7ba181e..ae23dbf0 100644 --- a/glances/main.py +++ b/glances/main.py @@ -230,8 +230,8 @@ Examples of use: dest='stdout_csv', help='display stats to stdout, csv format (comma separated list of plugins/plugins.attribute)') parser.add_argument('--issue', default=None, action='store_true', dest='stdout_issue', help='test all plugins and exit (please copy/paste the output if you open an issue)') - parser.add_argument('--fields', '--api-doc', default=None, action='store_true', - dest='stdout_fields', help='display fields descriptions') + parser.add_argument('--api-doc', default=None, action='store_true', + dest='stdout_apidoc', help='display fields descriptions') if not WINDOWS: parser.add_argument('--hide-kernel-threads', action='store_true', default=False, dest='no_kernel_threads', help='hide kernel threads in process list (not available on Windows)') diff --git a/glances/outputs/glances_stdout_fields.py b/glances/outputs/glances_stdout_fields.py deleted file mode 100644 index b61d89da..00000000 --- a/glances/outputs/glances_stdout_fields.py +++ /dev/null @@ -1,84 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of Glances. -# -# Copyright (C) 2021 Nicolargo -# -# 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 . - -"""Fields description interface class.""" - -from pprint import pformat - -from glances.logger import logger -from glances.compat import iteritems - - -class GlancesStdoutFieldsDescription(object): - - """ - This class manages the fields description display. - """ - - def __init__(self, config=None, args=None): - # Init - self.config = config - self.args = args - - def end(self): - pass - - def update(self, - stats, - duration=3): - """Display issue - """ - print('.. _apidoc:') - print('') - print('Restfull/API plugins documentation') - print('==================================') - print('') - print('The Glances Restfull/API server could be ran using the following command line:') - print('') - print('.. code-block:: bash') - print('') - print(' # glances -w --disable-webui') - print('') - for plugin in sorted(stats._plugins): - if stats._plugins[plugin].fields_description: - print('{}'.format(plugin)) - print('-' * len(plugin)) - print('') - for field, description in iteritems(stats._plugins[plugin].fields_description): - print('* **{}**: {} (unit is *{}*)'.format(field, - description['description'][:-1] if description['description'].endswith('.') else description['description'], - description['unit'])) - print('') - print('GET {} plugin stats:'.format(plugin)) - print('') - print('.. code-block:: json') - print('') - print(' # curl http://localhost:61208/api/3/{}'.format(plugin)) - stat = stats._plugins[plugin].get_export() - if isinstance(stat, list) and len(stat) > 1: - # Only display two first items - print(' ' + pformat(stat[0:2]).replace('\n', '\n ')) - else: - print(' ' + pformat(stat).replace('\n', '\n ')) - print('') - else: - logger.error('No fields_description variable defined for plugin {}'.format(plugin)) - - # Return True to exit directly (no refresh) - return True diff --git a/glances/plugins/glances_memswap.py b/glances/plugins/glances_memswap.py index 7f3f0726..d305d0c3 100644 --- a/glances/plugins/glances_memswap.py +++ b/glances/plugins/glances_memswap.py @@ -26,12 +26,6 @@ from glances.plugins.glances_plugin import GlancesPlugin import psutil # Fields description - # 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) fields_description = { 'total': {'description': 'Total swap memory.', 'unit': 'bytes'}, diff --git a/glances/processes.py b/glances/processes.py index 84650588..8fcda569 100644 --- a/glances/processes.py +++ b/glances/processes.py @@ -363,6 +363,9 @@ class GlancesProcesses(object): first = False # /End of extended stats + # PID is the key + proc['key'] = 'pid' + # Time since last update (for disk_io rate computation) proc['time_since_update'] = time_since_update diff --git a/glances/standalone.py b/glances/standalone.py index f95d79ff..d042873f 100644 --- a/glances/standalone.py +++ b/glances/standalone.py @@ -30,7 +30,7 @@ from glances.outputs.glances_curses import GlancesCursesStandalone from glances.outputs.glances_stdout import GlancesStdout from glances.outputs.glances_stdout_csv import GlancesStdoutCsv from glances.outputs.glances_stdout_issue import GlancesStdoutIssue -from glances.outputs.glances_stdout_fields import GlancesStdoutFieldsDescription +from glances.outputs.glances_stdout_apidoc import GlancesStdoutApiDoc from glances.outdated import Outdated from glances.timer import Counter @@ -88,10 +88,10 @@ class GlancesStandalone(object): logger.info("Issue mode is ON") # Init screen self.screen = GlancesStdoutIssue(config=config, args=args) - elif args.stdout_fields: + elif args.stdout_apidoc: logger.info("Fields descriptions mode is ON") # Init screen - self.screen = GlancesStdoutFieldsDescription(config=config, args=args) + self.screen = GlancesStdoutApiDoc(config=config, args=args) elif args.stdout: logger.info("Stdout mode is ON, following stats will be displayed: {}".format(args.stdout)) # Init screen -- cgit v1.2.3 From 2c92670771061f7eb63588494032cb34cf4958bb Mon Sep 17 00:00:00 2001 From: nicolargo Date: Fri, 16 Jul 2021 16:43:39 +0200 Subject: Add field == value --- glances/plugins/glances_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py index 48bc9375..6a617c8c 100644 --- a/glances/plugins/glances_plugin.py +++ b/glances/plugins/glances_plugin.py @@ -434,7 +434,7 @@ class GlancesPlugin(object): if not isinstance(self.stats, list): return None else: - if value.isdigit(): + if not isinstance(value, int) and value.isdigit(): value = int(value) try: return self._json_dumps({value: [i for i in self.stats if i[item] == value]}) -- cgit v1.2.3 From 10ae52bea6153c00c1c0fbf6ce50b05e0fbd147c Mon Sep 17 00:00:00 2001 From: nicolargo Date: Fri, 16 Jul 2021 16:44:11 +0200 Subject: Rename stdout fields to apidoc --- glances/outputs/glances_stdout_apidoc.py | 159 +++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 glances/outputs/glances_stdout_apidoc.py diff --git a/glances/outputs/glances_stdout_apidoc.py b/glances/outputs/glances_stdout_apidoc.py new file mode 100644 index 00000000..63e98ee8 --- /dev/null +++ b/glances/outputs/glances_stdout_apidoc.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Glances. +# +# Copyright (C) 2021 Nicolargo +# +# 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 . + +"""Fields description interface class.""" + +from pprint import pformat +import json + +from glances.logger import logger +from glances.compat import iteritems + +API_URL = "http://localhost:61208/api/3" + +APIDOC_HEADER = """\ +.. _api: + +API (Restfull/JSON) documentation +================================= + +The Glances Restfull/API server could be ran using the following command line: + +.. code-block:: bash + + # glances -w --disable-webui + +Note: Change request URL api/3 by api/2 if you use Glances 2.x. +""" + + +def indent_stat(stat, indent=' '): + # Indent stats to pretty print it + if isinstance(stat, list) and len(stat) > 1 and isinstance(stat[0], dict): + # Only display two first items + return indent + pformat(stat[0:2]).replace('\n', '\n' + indent) + else: + return indent + pformat(stat).replace('\n', '\n' + indent) + + +def get_plugins_list(stat): + return """\ +GET Plugins list +---------------- + +.. code-block:: json + + # curl {}/pluginslist +{} + +""".format(API_URL, + indent_stat(stat)) + + +class GlancesStdoutApiDoc(object): + + """ + This class manages the fields description display. + """ + + def __init__(self, config=None, args=None): + # Init + self.config = config + self.args = args + + def end(self): + pass + + def update(self, + stats, + duration=3): + """Display issue + """ + + # Display header + print(APIDOC_HEADER) + + # Display plugins list + print(get_plugins_list(sorted(stats._plugins))) + + # Loop over plugins + for plugin in sorted(stats._plugins): + stat = stats.get_plugin(plugin) + stat_export = stat.get_export() + + if stat_export is None or stat_export == [] or stat_export == {}: + continue + + sub_title = 'GET {}'.format(plugin) + print(sub_title) + print('-' * len(sub_title)) + print('') + + print('.. code-block:: json') + print('') + print(' # curl {}/{}'.format(API_URL, plugin)) + print(indent_stat(stat_export)) + print('') + + if stat.fields_description: + # For each plugins with a description + print('Fields descriptions:') + print('') + for field, description in iteritems(stat.fields_description): + print('* **{}**: {} (unit is *{}*)'.format(field, + description['description'][:-1] if description['description'].endswith('.') else description['description'], + description['unit'])) + print('') + else: + logger.error('No fields_description variable defined for plugin {}'.format(plugin)) + + item = None + value = None + if isinstance(stat_export, dict): + item = list(stat_export.keys())[0] + value = None + elif isinstance(stat_export, list) and len(stat_export) > 0 and isinstance(stat_export[0], dict): + if 'key' in stat_export[0]: + item = stat_export[0]['key'] + else: + item = list(stat_export[0].keys())[0] + if item and stat.get_stats_item(item): + stat_item = json.loads(stat.get_stats_item(item)) + if isinstance(stat_item[item], list): + value = stat_item[item][0] + else: + value = stat_item[item] + print('Get a specific field:') + print('') + print('.. code-block:: json') + print('') + print(' # curl {}/{}/{}'.format(API_URL, plugin, item)) + print(indent_stat(stat_item)) + print('') + if item and value and stat.get_stats_value(item, value): + print('Get a specific item when field matchs the given value:') + print('') + print('.. code-block:: json') + print('') + print(' # curl {}/{}/{}/{}'.format(API_URL, plugin, item, value)) + print(indent_stat(json.loads(stat.get_stats_value(item, value)))) + print('') + + # Return True to exit directly (no refresh) + return True -- cgit v1.2.3 From 01d08462121e252a7e906fe78555789fac412c39 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Fri, 16 Jul 2021 16:47:27 +0200 Subject: Rename stdout fields to apidoc --- glances/outputs/glances_stdout_apidoc.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/glances/outputs/glances_stdout_apidoc.py b/glances/outputs/glances_stdout_apidoc.py index 63e98ee8..c89732fb 100644 --- a/glances/outputs/glances_stdout_apidoc.py +++ b/glances/outputs/glances_stdout_apidoc.py @@ -155,5 +155,17 @@ class GlancesStdoutApiDoc(object): print(indent_stat(json.loads(stat.get_stats_value(item, value)))) print('') + # Get all stats + sub_title = 'GET all stats' + print(sub_title) + print('-' * len(sub_title)) + print('') + + print('.. code-block:: json') + print('') + print(' # curl {}/all'.format(API_URL)) + print(indent_stat(json.loads(stat.getAllViewsAsDict()))) + print('') + # Return True to exit directly (no refresh) return True -- cgit v1.2.3 From 2726522b1ef77362026426e56310bc7b362218b2 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Fri, 16 Jul 2021 16:51:48 +0200 Subject: Add the all request, with warnings --- glances/outputs/glances_stdout_apidoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glances/outputs/glances_stdout_apidoc.py b/glances/outputs/glances_stdout_apidoc.py index c89732fb..50b6e4f4 100644 --- a/glances/outputs/glances_stdout_apidoc.py +++ b/glances/outputs/glances_stdout_apidoc.py @@ -164,7 +164,7 @@ class GlancesStdoutApiDoc(object): print('.. code-block:: json') print('') print(' # curl {}/all'.format(API_URL)) - print(indent_stat(json.loads(stat.getAllViewsAsDict()))) + print(' Return a very big dictionnary (avoid using this request, performances will be poor)...') print('') # Return True to exit directly (no refresh) -- cgit v1.2.3 From a24fab1b643a95c462e833fe53dc141fc12e4048 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Fri, 16 Jul 2021 19:41:42 +0200 Subject: Add history --- glances/outputs/glances_stdout_apidoc.py | 42 ++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/glances/outputs/glances_stdout_apidoc.py b/glances/outputs/glances_stdout_apidoc.py index 50b6e4f4..f584257d 100644 --- a/glances/outputs/glances_stdout_apidoc.py +++ b/glances/outputs/glances_stdout_apidoc.py @@ -21,6 +21,7 @@ from pprint import pformat import json +import time from glances.logger import logger from glances.compat import iteritems @@ -82,7 +83,7 @@ class GlancesStdoutApiDoc(object): def update(self, stats, - duration=3): + duration=1): """Display issue """ @@ -160,12 +161,49 @@ class GlancesStdoutApiDoc(object): print(sub_title) print('-' * len(sub_title)) print('') - print('.. code-block:: json') print('') print(' # curl {}/all'.format(API_URL)) print(' Return a very big dictionnary (avoid using this request, performances will be poor)...') print('') + # Get all stats + time.sleep(1) + stats.update() + time.sleep(1) + stats.update() + sub_title = 'GET stats history' + print(sub_title) + print('-' * len(sub_title)) + print('') + print('History of a plugin:') + print('') + print('.. code-block:: json') + print('') + print(' # curl {}/cpu/history'.format(API_URL)) + print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history(nb=3)))) + print('') + print('Limit history to last 2 values:') + print('') + print('.. code-block:: json') + print('') + print(' # curl {}/cpu/history/2'.format(API_URL)) + print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history(nb=2)))) + print('') + print('History for a specific field:') + print('') + print('.. code-block:: json') + print('') + print(' # curl {}/cpu/system/history'.format(API_URL)) + print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history('system')))) + print('') + print('Limit history for a specific field to last 2 values:') + print('') + print('.. code-block:: json') + print('') + print(' # curl {}/cpu/system/history'.format(API_URL)) + print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history('system', nb=2)))) + print('') + # Return True to exit directly (no refresh) return True -- cgit v1.2.3 From a9d5c0c1acb4834f8fe28ef48eab38d4bf92fddb Mon Sep 17 00:00:00 2001 From: nicolargo Date: Sat, 17 Jul 2021 09:31:07 +0200 Subject: Add limits --- Makefile | 3 +- docs/api.rst | 1431 +++++++++++++++++++++++++++++- docs/man/glances.1 | 2 +- glances/outputs/glances_stdout_apidoc.py | 252 +++--- 4 files changed, 1571 insertions(+), 117 deletions(-) diff --git a/Makefile b/Makefile index 9f5a80b5..7dd127b3 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,8 @@ test: venv ./venv/bin/python ./unitest-xmlrpc.py docs: venv-dev - cd docs && ./build.sh + ./venv/bin/python -m glances -C ./conf/glances.conf --api-doc > ./docs/api.rst + cd docs && ./build.sh && cd .. docs-server: docs (sleep 2 && sensible-browser "http://localhost:$(PORT)") & diff --git a/docs/api.rst b/docs/api.rst index 29dd5ade..1eb5f630 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,15 +1,1428 @@ .. _api: -API Documentation -================= +API (Restfull/JSON) documentation +================================= -Glances provides an `XML-RPC server`_ and a `RESTful-JSON`_ API which -can be used by other clients. +The Glances Restfull/API server could be ran using the following command line: -API documentation is available at: +.. code-block:: bash -- XML-RPC: https://github.com/nicolargo/glances/wiki/The-Glances-2.x-API-How-to -- RESTful-JSON: https://github.com/nicolargo/glances/wiki/The-Glances-RESTFULL-JSON-API + # glances -w --disable-webui + +Note: Change request URL api/3 by api/2 if you use Glances 2.x. + +GET Plugins list +---------------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/pluginslist + ['alert', + 'amps', + 'cloud', + 'connections', + 'core', + 'cpu', + 'diskio', + 'docker', + 'folders', + 'fs', + 'gpu', + 'help', + 'ip', + 'irq', + 'load', + 'mem', + 'memswap', + 'network', + 'now', + 'percpu', + 'ports', + 'processcount', + 'processlist', + 'psutilversion', + 'quicklook', + 'raid', + 'sensors', + 'smart', + 'system', + 'uptime', + 'wifi'] + + +GET alert +--------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/alert + [[1626506953.0, + -1, + 'WARNING', + 'MEM', + 73.75089692241458, + 73.75089692241458, + 73.75089692241458, + 73.75089692241458, + 1, + [], + '', + 'memory_percent']] + +GET amps +-------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/amps + [{'count': 0, + 'countmax': None, + 'countmin': 1.0, + 'key': 'name', + 'name': 'Dropbox', + 'refresh': 3.0, + 'regex': True, + 'result': None, + 'timer': 0.11381411552429199}, + {'count': 0, + 'countmax': 20.0, + 'countmin': None, + 'key': 'name', + 'name': 'Python', + 'refresh': 3.0, + 'regex': True, + 'result': None, + 'timer': 0.11371397972106934}] + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/amps/name + {'name': ['Dropbox', 'Python', 'Conntrack', 'Nginx', 'Systemd', 'SystemV']} + +Get a specific item when field matchs the given value: + +.. code-block:: json + + # curl http://localhost:61208/api/3/amps/name/Dropbox + {'Dropbox': [{'count': 0, + 'countmax': None, + 'countmin': 1.0, + 'key': 'name', + 'name': 'Dropbox', + 'refresh': 3.0, + 'regex': True, + 'result': None, + 'timer': 0.11381411552429199}]} + +GET core +-------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/core + {'log': 4, 'phys': 2} + +Fields descriptions: + +* **phys**: Number of physical cores (hyper thread CPUs are excluded) (unit is *number*) +* **log**: Number of logical CPUs. A logical CPU is the number of physical cores multiplied by the number of threads that can run on each core (unit is *number*) + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/core/phys + {'phys': 2} + +GET cpu +------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/cpu + {'cpucore': 4, + 'ctx_switches': 0, + 'guest': 0.0, + 'guest_nice': 0.0, + 'idle': 67.7, + 'interrupts': 0, + 'iowait': 0.0, + 'irq': 0.0, + 'nice': 0.0, + 'soft_interrupts': 0, + 'softirq': 8.9, + 'steal': 0.0, + 'syscalls': 0, + 'system': 7.0, + 'time_since_update': 1, + 'total': 32.7, + 'user': 16.5} + +Fields descriptions: + +* **total**: Sum of all CPU percentages (except idle) (unit is *percent*) +* **system**: percent time spent in kernel space. System CPU time is the time spent running code in the Operating System kernel (unit is *percent*) +* **user**: CPU percent time spent in user space. User CPU time is the time spent on the processor running your program's code (or code in libraries) (unit is *percent*) +* **iowait**: *(Linux)*: percent time spent by the CPU waiting for I/O operations to complete (unit is *percent*) +* **idle**: percent of CPU used by any program. Every program or task that runs on a computer system occupies a certain amount of processing time on the CPU. If the CPU has completed all tasks it is idle (unit is *percent*) +* **irq**: *(Linux and BSD)*: percent time spent servicing/handling hardware/software interrupts. Time servicing interrupts (hardware + software) (unit is *percent*) +* **nice**: *(Unix)*: percent time occupied by user level processes with a positive nice value. The time the CPU has spent running users' processes that have been *niced* (unit is *percent*) +* **steal**: *(Linux)*: percentage of time a virtual CPU waits for a real CPU while the hypervisor is servicing another virtual processor (unit is *percent*) +* **ctx_switches**: number of context switches (voluntary + involuntary) per second. A context switch is a procedure that a computer's CPU (central processing unit) follows to change from one task (or process) to another while ensuring that the tasks do not conflict (unit is *percent*) +* **interrupts**: number of interrupts per second (unit is *percent*) +* **soft_interrupts**: number of software interrupts per second. Always set to 0 on Windows and SunOS (unit is *percent*) +* **cpucore**: Total number of CPU core (unit is *number*) +* **time_since_update**: Number of seconds since last update (unit is *seconds*) + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/cpu/total + {'total': 32.7} + +GET diskio +---------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/diskio + [{'disk_name': 'sda', + 'key': 'disk_name', + 'read_bytes': 0, + 'read_count': 0, + 'time_since_update': 1, + 'write_bytes': 0, + 'write_count': 0}, + {'disk_name': 'sda1', + 'key': 'disk_name', + 'read_bytes': 0, + 'read_count': 0, + 'time_since_update': 1, + 'write_bytes': 0, + 'write_count': 0}] + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/diskio/disk_name + {'disk_name': ['sda', 'sda1', 'sda2', 'sda5', 'dm-0', 'dm-1', 'sdc', 'sdc1']} + +Get a specific item when field matchs the given value: + +.. code-block:: json + + # curl http://localhost:61208/api/3/diskio/disk_name/sda + {'sda': [{'disk_name': 'sda', + 'key': 'disk_name', + 'read_bytes': 0, + 'read_count': 0, + 'time_since_update': 1, + 'write_bytes': 0, + 'write_count': 0}]} + +GET fs +------ + +.. code-block:: json + + # curl http://localhost:61208/api/3/fs + [{'device_name': '/dev/mapper/ubuntu--gnome--vg-root', + 'free': 36254167040, + 'fs_type': 'ext4', + 'key': 'mnt_point', + 'mnt_point': '/', + 'percent': 84.3, + 'size': 243396149248, + 'used': 194754527232}, + {'device_name': '/dev/sdc1', + 'free': 3814915088384, + 'fs_type': 'fuseblk', + 'key': 'mnt_point', + 'mnt_point': '/media/nicolargo/Elements', + 'percent': 4.6, + 'size': 4000750497792, + 'used': 185835409408}] + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/fs/mnt_point + {'mnt_point': ['/', '/media/nicolargo/Elements']} + +Get a specific item when field matchs the given value: + +.. code-block:: json + + # curl http://localhost:61208/api/3/fs/mnt_point// + {'/': [{'device_name': '/dev/mapper/ubuntu--gnome--vg-root', + 'free': 36254167040, + 'fs_type': 'ext4', + 'key': 'mnt_point', + 'mnt_point': '/', + 'percent': 84.3, + 'size': 243396149248, + 'used': 194754527232}]} + +GET ip +------ + +.. code-block:: json + + # curl http://localhost:61208/api/3/ip + {'address': '192.168.43.139', + 'gateway': '192.168.43.136', + 'mask': '255.255.255.0', + 'mask_cidr': 24} + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/ip/address + {'address': '192.168.43.139'} + +GET load +-------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/load + {'cpucore': 4, 'min1': 0.44, 'min15': 1.1, 'min5': 0.83} + +Fields descriptions: + +* **min1**: Average sum of the number of processes waiting in the run-queue plus the number currently executing over 1 minute (unit is *number*) +* **min5**: Average sum of the number of processes waiting in the run-queue plus the number currently executing over 5 minutes (unit is *number*) +* **min15**: Average sum of the number of processes waiting in the run-queue plus the number currently executing over 15 minutes (unit is *number*) +* **cpucore**: Total number of CPU core (unit is *number*) + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/load/min1 + {'min1': 0.44} + +GET mem +------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/mem + {'active': 4698603520, + 'available': 2060308480, + 'buffers': 686833664, + 'cached': 1725063168, + 'free': 2060308480, + 'inactive': 1597227008, + 'percent': 73.8, + 'shared': 700612608, + 'total': 7849062400, + 'used': 5788753920} + +Fields descriptions: + +* **total**: Total physical memory available (unit is *bytes*) +* **available**: The actual amount of available memory that can be given instantly to processes that request more memory in bytes; this is calculated by summing different memory values depending on the platform (e.g. free + buffers + cached on Linux) and it is supposed to be used to monitor actual memory usage in a cross platform fashion (unit is *bytes*) +* **percent**: The percentage usage calculated as (total - available) / total * 100 (unit is *percent*) +* **used**: Memory used, calculated differently depending on the platform and designed for informational purposes only (unit is *bytes*) +* **free**: Memory not being used at all (zeroed) that is readily available; note that this doesn't reflect the actual memory available (use 'available' instead) (unit is *bytes*) +* **active**: *(UNIX)*: memory currently in use or very recently used, and so it is in RAM (unit is *bytes*) +* **inactive**: *(UNIX)*: memory that is marked as not used (unit is *bytes*) +* **buffers**: *(Linux, BSD)*: cache for things like file system metadata (unit is *bytes*) +* **cached**: *(Linux, BSD)*: cache for various things (unit is *bytes*) +* **wired**: *(BSD, macOS)*: memory that is marked to always stay in RAM. It is never moved to disk (unit is *bytes*) +* **shared**: *(BSD)*: memory that may be simultaneously accessed by multiple processes (unit is *bytes*) + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/mem/total + {'total': 7849062400} + +GET memswap +----------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/memswap + {'free': 6102118400, + 'percent': 24.5, + 'sin': 8697491456, + 'sout': 13157560320, + 'time_since_update': 1, + 'total': 8082419712, + 'used': 1980301312} + +Fields descriptions: + +* **total**: Total swap memory (unit is *bytes*) +* **used**: Used swap memory (unit is *bytes*) +* **free**: Free swap memory (unit is *bytes*) +* **percent**: Used swap memory in percentage (unit is *percent*) +* **sin**: The number of bytes the system has swapped in from disk (cumulative) (unit is *bytes*) +* **sout**: The number of bytes the system has swapped out from disk (cumulative) (unit is *bytes*) +* **time_since_update**: Number of seconds since last update (unit is *seconds*) + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/memswap/total + {'total': 8082419712} + +GET network +----------- + +.. code-block:: json + + # curl http://localhost:61208/api/3/network + [{'alias': None, + 'cumulative_cx': 0, + 'cumulative_rx': 0, + 'cumulative_tx': 0, + 'cx': 0, + 'interface_name': 'mpqemubr0-dummy', + 'is_up': False, + 'key': 'interface_name', + 'rx': 0, + 'speed': 0, + 'time_since_update': 1, + 'tx': 0}, + {'alias': None, + 'cumulative_cx': 3715365760, + 'cumulative_rx': 1857682880, + 'cumulative_tx': 1857682880, + 'cx': 200, + 'interface_name': 'lo', + 'is_up': True, + 'key': 'interface_name', + 'rx': 100, + 'speed': 0, + 'time_since_update': 1, + 'tx': 100}] + +Fields descriptions: + +* **interface_name**: Interface name (unit is *string*) +* **alias**: Interface alias name (optional) (unit is *string*) +* **rx**: The received/input rate (in bit per second) (unit is *bps*) +* **tx**: The sent/output rate (in bit per second) (unit is *bps*) +* **cumulative_rx**: The number of bytes received through the interface (cumulative) (unit is *bytes*) +* **cumulative_tx**: The number of bytes sent through the interface (cumulative) (unit is *bytes*) +* **speed**: Maximum interface speed (in bit per second). Can return 0 on some operating-system (unit is *bps*) +* **is_up**: Is the interface up ? (unit is *bool*) +* **time_since_update**: Number of seconds since last update (unit is *seconds*) + +Get a specific field: + +.. code-block:: json + + # curl http://localhost:61208/api/3/network/interface_name + {'interface_name': ['mpqemubr0-dummy', + 'lo', + 'mpqemubr0', +