mirror of
https://github.com/nicolargo/glances.git
synced 2024-11-24 13:23:12 +03:00
First running version. Need more test. And WebUI
This commit is contained in:
parent
7e2af7bd63
commit
6d9bac1867
@ -59,6 +59,9 @@ You can also set the sort key in the UI:
|
||||
* - i
|
||||
- --sort-processes io_counters
|
||||
- Sort by DISK I/O
|
||||
* - j
|
||||
- --programs
|
||||
- Processes are display per program name (not per thread)
|
||||
* - m
|
||||
- --sort-processes memory_percent
|
||||
- Sort by MEM
|
||||
|
1084
docs/api.rst
1084
docs/api.rst
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "GLANCES" "1" "Jan 15, 2022" "3.2.5_beta01" "Glances"
|
||||
.TH "GLANCES" "1" "Mar 12, 2022" "3.2.5_beta01" "Glances"
|
||||
.SH NAME
|
||||
glances \- An eye on your system
|
||||
.
|
||||
|
@ -253,6 +253,14 @@ Examples of use:
|
||||
choices=sort_processes_key_list,
|
||||
help='Sort processes by: {}'.format(', '.join(sort_processes_key_list)),
|
||||
)
|
||||
# Display processes list by program name and not by thread
|
||||
parser.add_argument(
|
||||
'--programs',
|
||||
action='store_true',
|
||||
default=False,
|
||||
dest='programs',
|
||||
help='Show processes as programs (not threads)',
|
||||
)
|
||||
# Export modules feature
|
||||
parser.add_argument('--export', dest='export', help='enable export module (comma separed list)')
|
||||
parser.add_argument(
|
||||
|
@ -77,6 +77,7 @@ class _GlancesCurses(object):
|
||||
'h': {'switch': 'help_tag'},
|
||||
'i': {'sort_key': 'io_counters'},
|
||||
'I': {'switch': 'disable_ip'},
|
||||
'j': {'switch': 'programs'},
|
||||
# 'k' > Kill selected process
|
||||
'K': {'switch': 'disable_connections'},
|
||||
'l': {'switch': 'disable_alert'},
|
||||
|
@ -46,6 +46,14 @@ export default function GlancesController($scope, GlancesStats, hotkeys, ARGUMEN
|
||||
}
|
||||
});
|
||||
|
||||
// j => Processes are display per program name (not per thread)
|
||||
hotkeys.add({
|
||||
combo: 'j',
|
||||
callback: function () {
|
||||
ARGUMENTS.programs = !ARGUMENTS.programs;
|
||||
}
|
||||
});
|
||||
|
||||
// k => Show/hide connections stats
|
||||
hotkeys.add({
|
||||
combo: 'k',
|
||||
|
8
glances/outputs/static/public/glances.js
vendored
8
glances/outputs/static/public/glances.js
vendored
@ -94,6 +94,14 @@ function GlancesController($scope, GlancesStats, hotkeys, ARGUMENTS) {
|
||||
}
|
||||
});
|
||||
|
||||
// j => Processes are display per program name (not per thread)
|
||||
hotkeys.add({
|
||||
combo: 'j',
|
||||
callback: function () {
|
||||
ARGUMENTS.programs = !ARGUMENTS.programs;
|
||||
}
|
||||
});
|
||||
|
||||
// k => Show/hide connections stats
|
||||
hotkeys.add({
|
||||
combo: 'k',
|
||||
|
2
glances/outputs/static/public/glances.map.js
vendored
2
glances/outputs/static/public/glances.map.js
vendored
File diff suppressed because one or more lines are too long
@ -110,6 +110,7 @@ class Plugin(GlancesPlugin):
|
||||
self.view_data['show_hide_raid_plugin'] = msg_col.format('R', 'Show/hide RAID plugin')
|
||||
self.view_data['show_hide_wifi_module'] = msg_col2.format('W', 'Show/hide Wifi module')
|
||||
self.view_data['enable_disable_all_but_quick_look_and_load_module'] = msg_col2.format('4', 'Enable/disable all but quick look and load module')
|
||||
self.view_data['programs'] = msg_col2.format('j', 'Show processes as programs')
|
||||
|
||||
|
||||
def get_view_data(self, args=None):
|
||||
@ -203,7 +204,8 @@ class Plugin(GlancesPlugin):
|
||||
ret.append(self.curse_add_line(self.view_data['enable_disable_all_but_quick_look_and_load_module']))
|
||||
ret.append(self.curse_new_line())
|
||||
ret.append(self.curse_add_line(self.view_data['quit']))
|
||||
|
||||
ret.append(self.curse_add_line(self.view_data['programs']))
|
||||
|
||||
ret.append(self.curse_new_line())
|
||||
ret.append(self.curse_new_line())
|
||||
|
||||
|
@ -141,16 +141,17 @@ class Plugin(GlancesPlugin):
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
||||
# Display sort information
|
||||
msg = 'Programs' if self.args.programs else 'Threads'
|
||||
try:
|
||||
sort_human = self.sort_for_human[glances_processes.sort_key]
|
||||
except KeyError:
|
||||
sort_human = glances_processes.sort_key
|
||||
if glances_processes.auto_sort:
|
||||
msg = 'sorted automatically'
|
||||
msg += ' sorted automatically'
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = ' by {}'.format(sort_human)
|
||||
else:
|
||||
msg = 'sorted by {}'.format(sort_human)
|
||||
msg += ' sorted by {}'.format(sort_human)
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
||||
# Return the message with decoration
|
||||
|
@ -29,6 +29,7 @@ from glances.processes import glances_processes, sort_stats
|
||||
from glances.outputs.glances_unicode import unicode_message
|
||||
from glances.plugins.glances_core import Plugin as CorePlugin
|
||||
from glances.plugins.glances_plugin import GlancesPlugin
|
||||
from glances.programs import processes_to_programs
|
||||
|
||||
|
||||
def seconds_to_hms(input_seconds):
|
||||
@ -156,6 +157,9 @@ class Plugin(GlancesPlugin):
|
||||
# Note: Update is done in the processcount plugin
|
||||
# Just return the processes list
|
||||
stats = glances_processes.getlist()
|
||||
if self.args.programs:
|
||||
stats = processes_to_programs(stats)
|
||||
|
||||
|
||||
elif self.input_method == 'snmp':
|
||||
# No SNMP grab for processes
|
||||
|
@ -23,6 +23,7 @@ from glances.compat import iterkeys
|
||||
from glances.globals import BSD, LINUX, MACOS, WINDOWS
|
||||
from glances.timer import Timer, getTimeSinceLastUpdate
|
||||
from glances.filter import GlancesFilter
|
||||
from glances.programs import processes_to_programs
|
||||
from glances.logger import logger
|
||||
|
||||
import psutil
|
||||
|
74
glances/programs.py
Normal file
74
glances/programs.py
Normal file
@ -0,0 +1,74 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# Copyright (C) 2022 Nicolargo <nicolas@nicolargo.com>
|
||||
#
|
||||
# Glances is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Glances is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# from glances.logger import logger
|
||||
|
||||
# This constant defines the list of available processes sort key
|
||||
sort_programs_key_list = ['cpu_percent', 'memory_percent', 'cpu_times', 'io_counters', 'name']
|
||||
|
||||
|
||||
def processes_to_programs(processes):
|
||||
"""Convert a list of processes to a list of programs.
|
||||
|
||||
Each program is a dict containing the following keys:
|
||||
- 'name': program name
|
||||
- 'cpu_percent': process cpu percent (sum of all processes)
|
||||
- 'memory_percent': process memory percent (sum of all processes)
|
||||
- 'cpu_times': process cpu times (sum of all processes)
|
||||
- 'memory_info': process memory info (sum of all processes)
|
||||
- 'io_counters': process io counters (sum of all processes)
|
||||
- 'children': list of children processes
|
||||
"""
|
||||
# Start to build a dict of programs (key is program name)
|
||||
programs_dict = {}
|
||||
for p in processes:
|
||||
if p['name'] not in programs_dict:
|
||||
# Create a new entry in the dict (new program)
|
||||
programs_dict[p['name']] = {
|
||||
'cpu_percent': p['cpu_percent'],
|
||||
'memory_percent': p['memory_percent'],
|
||||
'cpu_times': p['cpu_times'],
|
||||
'memory_info': p['memory_info'],
|
||||
'io_counters': p['io_counters'],
|
||||
'children': [p['pid']],
|
||||
'time_since_update': p['time_since_update'],
|
||||
# Others keys are not used
|
||||
# but should be set to be compliant with the existing process_list
|
||||
'name': p['name'],
|
||||
'cmdline': [p['name']],
|
||||
'pid': '_',
|
||||
'username': p['username'],
|
||||
'nice': p['nice'],
|
||||
'status': p['status'],
|
||||
}
|
||||
else:
|
||||
# Update a existing entry in the dict (existing program)
|
||||
programs_dict[p['name']]['cpu_percent'] += p['cpu_percent']
|
||||
programs_dict[p['name']]['memory_percent'] += p['memory_percent']
|
||||
programs_dict[p['name']]['cpu_times'] += p['cpu_times']
|
||||
programs_dict[p['name']]['memory_info'] += p['memory_info']
|
||||
programs_dict[p['name']]['io_counters'] += p['io_counters']
|
||||
programs_dict[p['name']]['children'].append(p['pid'])
|
||||
# If all the subprocess has the same value, display it
|
||||
programs_dict[p['name']]['username'] = p['username'] if p['username'] == programs_dict[p['name']]['username'] else '_'
|
||||
programs_dict[p['name']]['nice'] = p['nice'] if p['nice'] == programs_dict[p['name']]['nice'] else '_'
|
||||
programs_dict[p['name']]['status'] = p['status'] if p['status'] == programs_dict[p['name']]['status'] else '_'
|
||||
|
||||
# Convert the dict to a list of programs
|
||||
return [programs_dict[p] for p in programs_dict]
|
11
unitest.py
11
unitest.py
@ -34,6 +34,7 @@ from glances.thresholds import GlancesThresholdWarning
|
||||
from glances.thresholds import GlancesThresholdCritical
|
||||
from glances.thresholds import GlancesThresholds
|
||||
from glances.plugins.glances_plugin import GlancesPlugin
|
||||
from glances.programs import processes_to_programs
|
||||
from glances.compat import subsample, range
|
||||
from glances.secure import secure_popen
|
||||
from glances.compat import PY3
|
||||
@ -283,6 +284,16 @@ class TestGlances(unittest.TestCase):
|
||||
|
||||
print('INFO: SMART stats: %s' % stats_grab)
|
||||
|
||||
def test_017_programs(self):
|
||||
"""Check Programs function (it's not a plugin)."""
|
||||
# stats_to_check = [ ]
|
||||
print('INFO: [TEST_010] Check PROGRAM stats')
|
||||
stats_grab = processes_to_programs(stats.get_plugin('processlist').get_raw())
|
||||
self.assertTrue(type(stats_grab) is list, msg='Programs stats is not a list')
|
||||
print('INFO: PROGRAM list stats: %s items in the list' % len(stats_grab))
|
||||
# Check if number of processes in the list equal counter
|
||||
# self.assertEqual(total, len(stats_grab))
|
||||
|
||||
def test_094_thresholds(self):
|
||||
"""Test thresholds classes"""
|
||||
print('INFO: [TEST_094] Thresholds')
|
||||
|
Loading…
Reference in New Issue
Block a user