mirror of https://github.com/nicolargo/glances
Implement a new API method to limit the number of returned list object #2491
parent
c5e11cef59
commit
ef2f949f04
|
@ -2,12 +2,12 @@
|
|||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <nicolas@nicolargo.com>
|
||||
# SPDX-FileCopyrightText: 2023 Nicolas Hennion <nicolas@nicolargo.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-only
|
||||
#
|
||||
|
||||
"""Web interface class."""
|
||||
"""RestFull API interface class."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -152,6 +152,7 @@ class GlancesBottle(object):
|
|||
self._app.route(
|
||||
'/api/%s/<plugin>/history/<nb:int>' % self.API_VERSION, method="GET", callback=self._api_history
|
||||
)
|
||||
self._app.route('/api/%s/<plugin>/top/<nb:int>' % self.API_VERSION, method="GET", callback=self._api_top)
|
||||
self._app.route('/api/%s/<plugin>/limits' % self.API_VERSION, method="GET", callback=self._api_limits)
|
||||
self._app.route('/api/%s/<plugin>/views' % self.API_VERSION, method="GET", callback=self._api_views)
|
||||
self._app.route('/api/%s/<plugin>/<item>' % self.API_VERSION, method="GET", callback=self._api_item)
|
||||
|
@ -393,6 +394,36 @@ class GlancesBottle(object):
|
|||
|
||||
return statval
|
||||
|
||||
@compress
|
||||
def _api_top(self, plugin, nb=0):
|
||||
"""Glances API RESTful implementation.
|
||||
|
||||
Return the JSON representation of a given plugin limited to the top nb items.
|
||||
It is used to reduce the payload of the HTTP response (example: processlist).
|
||||
|
||||
HTTP/200 if OK
|
||||
HTTP/400 if plugin is not found
|
||||
HTTP/404 if others error
|
||||
"""
|
||||
response.content_type = 'application/json; charset=utf-8'
|
||||
|
||||
if plugin not in self.plugins_list:
|
||||
abort(400, "Unknown plugin %s (available plugins: %s)" % (plugin, self.plugins_list))
|
||||
|
||||
# Update the stat
|
||||
self.__update__()
|
||||
|
||||
try:
|
||||
# Get the value of the stat ID
|
||||
statval = self.stats.get_plugin(plugin).get_export()
|
||||
except Exception as e:
|
||||
abort(404, "Cannot get plugin %s (%s)" % (plugin, str(e)))
|
||||
|
||||
if isinstance(statval, list):
|
||||
return json_dumps(statval[:nb])
|
||||
else:
|
||||
return json_dumps(statval)
|
||||
|
||||
@compress
|
||||
def _api_history(self, plugin, nb=0):
|
||||
"""Glances API RESTful implementation.
|
||||
|
|
|
@ -163,6 +163,22 @@ def print_all():
|
|||
print('')
|
||||
|
||||
|
||||
def print_top(stats):
|
||||
time.sleep(1)
|
||||
stats.update()
|
||||
sub_title = 'GET top n items of a specific plugin'
|
||||
print(sub_title)
|
||||
print('-' * len(sub_title))
|
||||
print('')
|
||||
print('Get top 2 processes of the processlist plugin::')
|
||||
print('')
|
||||
print(' # curl {}/processlist/top/2'.format(API_URL))
|
||||
print(indent_stat(stats.get_plugin('processlist').get_export()[:2]))
|
||||
print('')
|
||||
print('Note: Only work for plugin with a list of items')
|
||||
print('')
|
||||
|
||||
|
||||
def print_history(stats):
|
||||
time.sleep(1)
|
||||
stats.update()
|
||||
|
@ -248,6 +264,10 @@ class GlancesStdoutApiDoc(object):
|
|||
# Get all stats
|
||||
print_all()
|
||||
|
||||
# Get top stats (only for plugins with a list of items)
|
||||
# Example for processlist plugin: get top 2 processes
|
||||
print_top(stats)
|
||||
|
||||
# History
|
||||
print_history(stats)
|
||||
|
||||
|
|
|
@ -47,8 +47,7 @@ WIRELESS_FILE = '/proc/net/wireless'
|
|||
wireless_file_exists = file_exists(WIRELESS_FILE)
|
||||
|
||||
if not nmcli_command_exists and not wireless_file_exists:
|
||||
logger.debug("Wifi plugin is disabled (no %s command or %s file found)" % ('nmcli',
|
||||
WIRELESS_FILE))
|
||||
logger.debug("Wifi plugin is disabled (no %s command or %s file found)" % ('nmcli', WIRELESS_FILE))
|
||||
|
||||
|
||||
class PluginModel(GlancesPluginModel):
|
||||
|
@ -121,12 +120,14 @@ class PluginModel(GlancesPluginModel):
|
|||
# Extract the stats
|
||||
wifi_stats = wifi_stats.split()
|
||||
# Add the Wifi link to the list
|
||||
stats.append({
|
||||
'key': self.get_key(),
|
||||
'ssid': wifi_stats[0][:-1],
|
||||
'signal': float(wifi_stats[3]),
|
||||
'security': ''
|
||||
})
|
||||
stats.append(
|
||||
{
|
||||
'key': self.get_key(),
|
||||
'ssid': wifi_stats[0][:-1],
|
||||
'signal': float(wifi_stats[3]),
|
||||
'security': '',
|
||||
}
|
||||
)
|
||||
# Next line
|
||||
wifi_stats = f.readline()
|
||||
|
||||
|
@ -202,11 +203,11 @@ class PluginModel(GlancesPluginModel):
|
|||
hotspot_name = i['ssid']
|
||||
# Cut hotspot_name if it is too long
|
||||
if len(hotspot_name) > if_name_max_width:
|
||||
hotspot_name = '_' + hotspot_name[-if_name_max_width - len(i['security']) + 1:]
|
||||
hotspot_name = '_' + hotspot_name[-if_name_max_width - len(i['security']) + 1 :]
|
||||
# Add the new hotspot to the message
|
||||
msg = '{:{width}} {security}'.format(nativestr(hotspot_name),
|
||||
width=if_name_max_width - len(i['security']) - 1,
|
||||
security=i['security'])
|
||||
msg = '{:{width}} {security}'.format(
|
||||
nativestr(hotspot_name), width=if_name_max_width - len(i['security']) - 1, security=i['security']
|
||||
)
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:>7}'.format(
|
||||
i['signal'],
|
||||
|
@ -244,12 +245,7 @@ class ThreadHotspot(threading.Thread):
|
|||
if len(h) != 4 or h[0] != 'yes':
|
||||
# Do not process the line if it is not the active hotspot
|
||||
continue
|
||||
nmcli_result.append({
|
||||
'key': 'ssid',
|
||||
'ssid': h[1],
|
||||
'signal': -float(h[2]),
|
||||
'security': h[3]
|
||||
})
|
||||
nmcli_result.append({'key': 'ssid', 'ssid': h[1], 'signal': -float(h[2]), 'security': h[3]})
|
||||
self.thread_stats = nmcli_result
|
||||
# Wait refresh time until next scan
|
||||
# Note: nmcli cache the result for x seconds
|
||||
|
|
|
@ -231,6 +231,18 @@ class TestGlances(unittest.TestCase):
|
|||
self.assertTrue(req.ok)
|
||||
self.assertEqual(req.text, "Active")
|
||||
|
||||
def test_013_top(self):
|
||||
"""Values."""
|
||||
method = "processlist"
|
||||
request = "%s/%s/top/2" % (URL, method)
|
||||
print('INFO: [TEST_013] Top nb item of PROCESSLIST')
|
||||
print(request)
|
||||
req = self.http_get(request)
|
||||
|
||||
self.assertTrue(req.ok)
|
||||
self.assertIsInstance(req.json(), list)
|
||||
self.assertEqual(len(req.json()), 2)
|
||||
|
||||
def test_999_stop_server(self):
|
||||
"""Stop the Glances Web Server."""
|
||||
print('INFO: [TEST_999] Stop the Glances Web Server')
|
||||
|
|
Loading…
Reference in New Issue