mirror of
https://github.com/nicolargo/glances.git
synced 2024-09-21 01:28:04 +03:00
Correct merge conflict
This commit is contained in:
commit
40864d35e1
@ -244,7 +244,7 @@ To install the binary package:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# pkg install py37-glances
|
||||
# pkg install py38-glances
|
||||
|
||||
To install Glances from ports:
|
||||
|
||||
|
@ -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
|
||||
- Accumulate processes by program
|
||||
* - m
|
||||
- --sort-processes memory_percent
|
||||
- Sort by MEM
|
||||
@ -108,7 +111,7 @@ Columns display
|
||||
|
||||
The non-swapped physical memory a process is
|
||||
using (what's currently in the physical memory).
|
||||
``PID`` Process ID
|
||||
``PID`` Process ID (column is replaced by NPROCS in accumulated mode)
|
||||
``USER`` User ID
|
||||
``THR`` Threads number of the process
|
||||
``TIME+`` Cumulative CPU time used by the process
|
||||
@ -133,8 +136,6 @@ Columns display
|
||||
pressing on the ``'/'`` key
|
||||
========================= ==============================================
|
||||
|
||||
Source: Thanks to the Peteris Ņikiforovs's blog.
|
||||
|
||||
Process filtering
|
||||
-----------------
|
||||
|
||||
@ -180,3 +181,11 @@ In curses/standalone mode, you can select a process using ``UP`` and ``DOWN`` an
|
||||
configuration file under the ``[processlist]`` section. It is also
|
||||
possible to define limit for Nice values (comma separated list).
|
||||
For example: nice_warning=-20,-19,-18
|
||||
|
||||
Accumulated per program — key 'j'
|
||||
---------------------------------
|
||||
|
||||
When activated ('j' hotkey or --programs option in the command line), processes are merged
|
||||
to display which programs are active. The columns show the accumulated cpu consumption, the
|
||||
accumulated virtual and resident memory consumption, the accumulated transferred data I/O.
|
||||
The PID columns is replaced by a NPROCS column which is the number of processes.
|
1071
docs/api.rst
1071
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 13, 2022" "3.2.5_beta01" "Glances"
|
||||
.SH NAME
|
||||
glances \- An eye on your system
|
||||
.
|
||||
|
@ -29,6 +29,7 @@ import unicodedata
|
||||
import types
|
||||
import subprocess
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
from glances.logger import logger
|
||||
|
||||
@ -311,3 +312,47 @@ def enable(class_name, var):
|
||||
"""Set disable_<var> to False in the class class_name."""
|
||||
setattr(class_name, 'enable_' + var, True)
|
||||
setattr(class_name, 'disable_' + var, False)
|
||||
|
||||
|
||||
def pretty_date(time=False):
|
||||
"""
|
||||
Get a datetime object or a int() Epoch timestamp and return a
|
||||
pretty string like 'an hour ago', 'Yesterday', '3 months ago',
|
||||
'just now', etc
|
||||
Source: https://stackoverflow.com/questions/1551382/user-friendly-time-format-in-python
|
||||
"""
|
||||
now = datetime.now()
|
||||
if type(time) is int:
|
||||
diff = now - datetime.fromtimestamp(time)
|
||||
elif isinstance(time, datetime):
|
||||
diff = now - time
|
||||
elif not time:
|
||||
diff = 0
|
||||
second_diff = diff.seconds
|
||||
day_diff = diff.days
|
||||
|
||||
if day_diff < 0:
|
||||
return ''
|
||||
|
||||
if day_diff == 0:
|
||||
if second_diff < 10:
|
||||
return "just now"
|
||||
if second_diff < 60:
|
||||
return str(second_diff) + " seconds"
|
||||
if second_diff < 120:
|
||||
return "a minute"
|
||||
if second_diff < 3600:
|
||||
return str(second_diff // 60) + " minutes"
|
||||
if second_diff < 7200:
|
||||
return "an hour"
|
||||
if second_diff < 86400:
|
||||
return str(second_diff // 3600) + " hours"
|
||||
if day_diff == 1:
|
||||
return "Yesterday"
|
||||
if day_diff < 7:
|
||||
return str(day_diff) + " days"
|
||||
if day_diff < 31:
|
||||
return str(day_diff // 7) + " weeks"
|
||||
if day_diff < 365:
|
||||
return str(day_diff // 30) + " months"
|
||||
return str(day_diff // 365) + " years"
|
||||
|
@ -252,6 +252,15 @@ 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',
|
||||
'--program',
|
||||
action='store_true',
|
||||
default=False,
|
||||
dest='programs',
|
||||
help='Accumulate processes by program',
|
||||
)
|
||||
# Export modules feature
|
||||
parser.add_argument('--export', dest='export', help='enable export module (comma separed list)')
|
||||
parser.add_argument(
|
||||
@ -340,7 +349,7 @@ Examples of use:
|
||||
default=self.DEFAULT_REFRESH_TIME,
|
||||
type=float,
|
||||
dest='time',
|
||||
help='set minumum refresh rate in seconds [default: {} sec]'.format(self.DEFAULT_REFRESH_TIME),
|
||||
help='set minimum refresh rate in seconds [default: {} sec]'.format(self.DEFAULT_REFRESH_TIME),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-w',
|
||||
|
@ -76,6 +76,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'},
|
||||
@ -691,27 +692,10 @@ class _GlancesCurses(object):
|
||||
# Display kill process confirmation popup
|
||||
# Only in standalone mode (cs_status is None)
|
||||
if self.kill_process and cs_status is None:
|
||||
selected_process_raw = stats.get_plugin('processlist').get_raw()[self.args.cursor_position]
|
||||
confirm = self.display_popup(
|
||||
'Kill process: {} (pid: {}) ?\n\nConfirm ([y]es/[n]o): '.format(
|
||||
selected_process_raw['name'], selected_process_raw['pid']
|
||||
),
|
||||
popup_type='yesno',
|
||||
)
|
||||
if confirm.lower().startswith('y'):
|
||||
try:
|
||||
ret_kill = glances_processes.kill(selected_process_raw['pid'])
|
||||
except Exception as e:
|
||||
logger.error('Can not kill process {} ({})'.format(selected_process_raw['name'], e))
|
||||
else:
|
||||
logger.info(
|
||||
'Kill signal has been sent to process {} (return code: {})'.format(
|
||||
selected_process_raw['name'], ret_kill
|
||||
)
|
||||
)
|
||||
|
||||
logger.info(stats.get_plugin('processlist').get_raw()[self.args.cursor_position])
|
||||
self.kill(stats.get_plugin('processlist').get_raw()[self.args.cursor_position])
|
||||
elif self.kill_process and cs_status is not None:
|
||||
self.display_popup('Kill process only available in standalone mode')
|
||||
self.display_popup('Kill process only available for local processes')
|
||||
self.kill_process = False
|
||||
|
||||
# Display graph generation popup
|
||||
@ -720,6 +704,40 @@ class _GlancesCurses(object):
|
||||
|
||||
return True
|
||||
|
||||
def kill(self, process):
|
||||
"""Kill a process, or a list of process if the process has a childrens field.
|
||||
|
||||
:param process
|
||||
:return: None
|
||||
"""
|
||||
logger.debug("Selected process to kill: {}".format(process))
|
||||
|
||||
if 'childrens' in process:
|
||||
pid_to_kill = process['childrens']
|
||||
else:
|
||||
pid_to_kill = [process['pid']]
|
||||
|
||||
confirm = self.display_popup(
|
||||
'Kill process: {} (pid: {}) ?\n\nConfirm ([y]es/[n]o): '.format(
|
||||
process['name'],
|
||||
', '.join(map(str,pid_to_kill)),
|
||||
),
|
||||
popup_type='yesno',
|
||||
)
|
||||
|
||||
if confirm.lower().startswith('y'):
|
||||
for pid in pid_to_kill:
|
||||
try:
|
||||
ret_kill = glances_processes.kill(pid)
|
||||
except Exception as e:
|
||||
logger.error('Can not kill process {} ({})'.format(pid, e))
|
||||
else:
|
||||
logger.info(
|
||||
'Kill signal has been sent to process {} (return code: {})'.format(
|
||||
pid, ret_kill
|
||||
)
|
||||
)
|
||||
|
||||
def __display_header(self, stat_display):
|
||||
"""Display the firsts lines (header) in the Curses interface.
|
||||
|
||||
|
@ -46,6 +46,14 @@ export default function GlancesController($scope, GlancesStats, hotkeys, ARGUMEN
|
||||
}
|
||||
});
|
||||
|
||||
// j => Accumulate processes by program
|
||||
hotkeys.add({
|
||||
combo: 'j',
|
||||
callback: function () {
|
||||
ARGUMENTS.programs = !ARGUMENTS.programs;
|
||||
}
|
||||
});
|
||||
|
||||
// k => Show/hide connections stats
|
||||
hotkeys.add({
|
||||
combo: 'k',
|
||||
|
@ -17,6 +17,7 @@ export default function GlancesPluginDockerController($scope, GlancesStats) {
|
||||
'id': containerData.Id,
|
||||
'name': containerData.name,
|
||||
'status': containerData.Status,
|
||||
'uptime': containerData.Uptime,
|
||||
'cpu': containerData.cpu.total,
|
||||
'memory': containerData.memory.usage != undefined ? containerData.memory.usage : '?',
|
||||
'rss': containerData.memory.rss != undefined ? containerData.memory.rss : '?',
|
||||
|
@ -5,6 +5,7 @@
|
||||
<div class="table-row">
|
||||
<div class="table-cell text-left">Name</div>
|
||||
<div class="table-cell">Status</div>
|
||||
<div class="table-cell">Uptime</div>
|
||||
<div class="table-cell">CPU%</div>
|
||||
<div class="table-cell">MEM</div>
|
||||
<div class="table-cell">RSS</div>
|
||||
@ -18,6 +19,8 @@
|
||||
<div class="table-cell text-left">{{ container.name }}</div>
|
||||
<div class="table-cell" ng-class="container.status == 'Paused' ? 'careful' : 'ok'">{{ container.status }}
|
||||
</div>
|
||||
<div class="table-cell" ng-class="container.status == 'Paused' ? 'careful' : 'ok'">{{ container.uptime }}
|
||||
</div>
|
||||
<div class="table-cell">{{ container.cpu | number:1 }}</div>
|
||||
<div class="table-cell">{{ container.memory | bytes }}</div>
|
||||
<div class="table-cell">{{ container.rss | bytes }}</div>
|
||||
|
BIN
glances/outputs/static/public/glances.js
vendored
BIN
glances/outputs/static/public/glances.js
vendored
Binary file not shown.
BIN
glances/outputs/static/public/glances.map.js
vendored
BIN
glances/outputs/static/public/glances.map.js
vendored
Binary file not shown.
@ -189,4 +189,4 @@ class ThreadOpenStack(threading.Thread):
|
||||
|
||||
def stopped(self):
|
||||
"""Return True is the thread is stopped."""
|
||||
return self._stopper.isSet()
|
||||
return self._stopper.is_set()
|
||||
|
@ -23,7 +23,9 @@ import os
|
||||
import threading
|
||||
import time
|
||||
from copy import deepcopy
|
||||
from dateutil import parser
|
||||
|
||||
from glances.compat import iterkeys, itervalues, nativestr, pretty_date
|
||||
from glances.logger import logger
|
||||
from glances.globals import iterkeys, itervalues, nativestr
|
||||
from glances.timer import getTimeSinceLastUpdate
|
||||
@ -291,6 +293,8 @@ class PluginModel(GlancesPluginModel):
|
||||
)
|
||||
container_stats['network_rx'] = container_stats['network'].get('rx', None)
|
||||
container_stats['network_tx'] = container_stats['network'].get('tx', None)
|
||||
# Uptime
|
||||
container_stats['Uptime'] = pretty_date(parser.parse(container.attrs['State']['StartedAt']).replace(tzinfo=None))
|
||||
else:
|
||||
container_stats['cpu'] = {}
|
||||
container_stats['cpu_percent'] = None
|
||||
@ -302,6 +306,7 @@ class PluginModel(GlancesPluginModel):
|
||||
container_stats['network'] = {}
|
||||
container_stats['network_rx'] = None
|
||||
container_stats['network_tx'] = None
|
||||
container_stats['Uptime'] = None
|
||||
# Add current container stats to the stats list
|
||||
stats['containers'].append(container_stats)
|
||||
|
||||
@ -556,6 +561,8 @@ class PluginModel(GlancesPluginModel):
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:>10}'.format('Status')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:>10}'.format('Uptime')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:>6}'.format('CPU%')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:>7}'.format('MEM')
|
||||
@ -581,6 +588,12 @@ class PluginModel(GlancesPluginModel):
|
||||
status = self.container_alert(container['Status'])
|
||||
msg = '{:>10}'.format(container['Status'][0:10])
|
||||
ret.append(self.curse_add_line(msg, status))
|
||||
# Uptime
|
||||
if container['Uptime']:
|
||||
msg = '{:>10}'.format(container['Uptime'])
|
||||
else:
|
||||
msg = '{:>10}'.format('_')
|
||||
ret.append(self.curse_add_line(msg, status))
|
||||
# CPU
|
||||
try:
|
||||
msg = '{:>6.1f}'.format(container['cpu']['total'])
|
||||
@ -712,7 +725,7 @@ class ThreadDockerGrabber(threading.Thread):
|
||||
|
||||
def stopped(self):
|
||||
"""Return True is the thread is stopped."""
|
||||
return self._stopper.isSet()
|
||||
return self._stopper.is_set()
|
||||
|
||||
|
||||
def sort_stats(stats):
|
||||
|
@ -110,6 +110,7 @@ class PluginModel(GlancesPluginModel):
|
||||
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', 'Accumulate processes by program')
|
||||
|
||||
|
||||
def get_view_data(self, args=None):
|
||||
@ -203,7 +204,8 @@ class PluginModel(GlancesPluginModel):
|
||||
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())
|
||||
|
||||
|
@ -255,7 +255,7 @@ class ThreadScanner(threading.Thread):
|
||||
|
||||
def stopped(self):
|
||||
"""Return True is the thread is stopped."""
|
||||
return self._stopper.isSet()
|
||||
return self._stopper.is_set()
|
||||
|
||||
def _web_scan(self, web):
|
||||
"""Scan the Web/URL (dict) and update the status key."""
|
||||
|
@ -141,16 +141,17 @@ class PluginModel(GlancesPluginModel):
|
||||
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
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com>
|
||||
# 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
|
||||
@ -28,6 +28,7 @@ from glances.processes import glances_processes, sort_stats
|
||||
from glances.outputs.glances_unicode import unicode_message
|
||||
from glances.plugins.core.model import PluginModel as CorePluginModel
|
||||
from glances.plugins.plugin.model import GlancesPluginModel
|
||||
from glances.programs import processes_to_programs
|
||||
|
||||
|
||||
def seconds_to_hms(input_seconds):
|
||||
@ -155,6 +156,9 @@ class PluginModel(GlancesPluginModel):
|
||||
# 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
|
||||
@ -375,7 +379,15 @@ class PluginModel(GlancesPluginModel):
|
||||
ret.append(self._get_process_curses_rss(p, selected, args))
|
||||
|
||||
# PID
|
||||
msg = self.layout_stat['pid'].format(p['pid'], width=self.__max_pid_size())
|
||||
if not self.args.programs:
|
||||
# Display processes, so the PID should be displayed
|
||||
msg = self.layout_stat['pid'].format(p['pid'],
|
||||
width=self.__max_pid_size())
|
||||
else:
|
||||
# Display programs, so the PID should not be displayed
|
||||
# Instead displays the number of childrens
|
||||
msg = self.layout_stat['pid'].format(len(p['childrens']) if 'childrens' in p else '_',
|
||||
width=self.__max_pid_size())
|
||||
ret.append(self.curse_add_line(msg))
|
||||
|
||||
# USER
|
||||
@ -546,7 +558,10 @@ class PluginModel(GlancesPluginModel):
|
||||
ret.append(self.curse_add_line(msg, optional=True))
|
||||
msg = self.layout_header['res'].format('RES')
|
||||
ret.append(self.curse_add_line(msg, optional=True))
|
||||
msg = self.layout_header['pid'].format('PID', width=self.__max_pid_size())
|
||||
if not self.args.programs:
|
||||
msg = self.layout_header['pid'].format('PID', width=self.__max_pid_size())
|
||||
else:
|
||||
msg = self.layout_header['pid'].format('NPROCS', width=self.__max_pid_size())
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = self.layout_header['user'].format('USER')
|
||||
ret.append(self.curse_add_line(msg, sort_style if process_sort_key == 'username' else 'DEFAULT'))
|
||||
@ -572,7 +587,10 @@ class PluginModel(GlancesPluginModel):
|
||||
msg, sort_style if process_sort_key == 'io_counters' else 'DEFAULT', optional=True, additional=True
|
||||
)
|
||||
)
|
||||
msg = self.layout_header['command'].format('Command', "('k' to kill)" if args.is_standalone else "")
|
||||
if not self.args.programs:
|
||||
msg = self.layout_header['command'].format('Command', "('k' to kill)" if args.is_standalone else "")
|
||||
else:
|
||||
msg = self.layout_header['command'].format('Programs', "('k' to kill)" if args.is_standalone else "")
|
||||
ret.append(self.curse_add_line(msg, sort_style if process_sort_key == 'name' else 'DEFAULT'))
|
||||
|
||||
def __msg_curse_sum(self, ret, sep_char='_', mmm=None, args=None):
|
||||
|
67
glances/programs.py
Normal file
67
glances/programs.py
Normal file
@ -0,0 +1,67 @@
|
||||
# -*- 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."""
|
||||
# Start to build a dict of programs (key is program name)
|
||||
programs_dict = {}
|
||||
key = 'name'
|
||||
for p in processes:
|
||||
if p[key] not in programs_dict:
|
||||
# Create a new entry in the dict (new program)
|
||||
programs_dict[p[key]] = {
|
||||
'time_since_update': p['time_since_update'],
|
||||
'num_threads': p['num_threads'],
|
||||
'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'],
|
||||
'childrens': [p['pid']],
|
||||
# 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[key]]['num_threads'] += p['num_threads']
|
||||
programs_dict[p[key]]['cpu_percent'] += p['cpu_percent']
|
||||
programs_dict[p[key]]['memory_percent'] += p['memory_percent']
|
||||
programs_dict[p[key]]['cpu_times'] += p['cpu_times']
|
||||
programs_dict[p[key]]['memory_info'] += p['memory_info']
|
||||
programs_dict[p[key]]['io_counters'] += p['io_counters']
|
||||
programs_dict[p[key]]['childrens'].append(p['pid'])
|
||||
# If all the subprocess has the same value, display it
|
||||
programs_dict[p[key]]['username'] = p['username'] if p['username'] == programs_dict[p[key]]['username'] else '_'
|
||||
programs_dict[p[key]]['nice'] = p['nice'] if p['nice'] == programs_dict[p[key]]['nice'] else '_'
|
||||
programs_dict[p[key]]['status'] = p['status'] if p['status'] == programs_dict[p[key]]['status'] else '_'
|
||||
|
||||
# Convert the dict to a list of programs
|
||||
return [programs_dict[p] for p in programs_dict]
|
19
unitest.py
19
unitest.py
@ -21,7 +21,6 @@
|
||||
"""Glances unitary tests suite."""
|
||||
|
||||
import time
|
||||
from tracemalloc import Snapshot
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
@ -41,8 +40,11 @@ from glances.thresholds import GlancesThresholdWarning
|
||||
from glances.thresholds import GlancesThresholdCritical
|
||||
from glances.thresholds import GlancesThresholds
|
||||
from glances.plugins.plugin.model import GlancesPluginModel
|
||||
from glances.programs import processes_to_programs
|
||||
from glances.compat import subsample, range
|
||||
from glances.secure import secure_popen
|
||||
from glances.compat import PY3
|
||||
|
||||
from tracemalloc import Snapshot
|
||||
|
||||
# Global variables
|
||||
# =================
|
||||
@ -286,6 +288,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')
|
||||
@ -394,9 +406,6 @@ class TestGlances(unittest.TestCase):
|
||||
|
||||
def test_200_memory_leak(self):
|
||||
"""Memory leak check"""
|
||||
# Only available in PY3
|
||||
if not PY3:
|
||||
return
|
||||
import tracemalloc
|
||||
print('INFO: [TEST_200] Memory leak check')
|
||||
tracemalloc.start()
|
||||
|
Loading…
Reference in New Issue
Block a user