Merge branch 'develop' of https://github.com/nicolargo/glances into issue1182

This commit is contained in:
nicolargo 2017-12-02 10:59:42 +01:00
commit eef4fd7e32
8 changed files with 65 additions and 52 deletions

View File

@ -7,8 +7,8 @@ http://blog.nicolargo.com
https://twitter.com/nicolargo
https://github.com/nicolargo
nicolashennion@gmail.com
PGP Fingerprint: 835F C447 3BCD 60E9 9200 2778 ABA4 D1AB 9731 6A3C
PGP Public key: gpg --keyserver pgp.mit.edu --recv-keys 0xaba4d1ab97316a3c
PGP Fingerprint: A0D9 628F 5A83 A879 48EA B1FE BA43 C11F 2C8B 4347
PGP Public key: gpg --keyserver pgp.mit.edu --recv-keys 0xba43c11f2c8b4347
Alessio Sergi (aka) Al3hex
https://twitter.com/al3hex

2
NEWS
View File

@ -25,6 +25,8 @@ Bugs corrected:
* Add missing mount-observe and system-observe interfaces #1179
* OS specific arguments should be documented and reported #1180
* 'ascii' codec can't encode character u'\U0001f4a9' in position 4: ordinal not in range(128) #1185
* KeyError: 'memory_info' on stats sum #1188
* Electron/Atom processes displayed wrong in process list #1192
Backward-incompatible changes:

View File

@ -92,7 +92,7 @@ if PY3:
def b(s):
if isinstance(s, binary_type):
return s
return s.encode('latin-1')
return s.encode('utf-8')
def nativestr(s):
if isinstance(s, text_type):

View File

@ -135,6 +135,7 @@ class Config(object):
def read(self):
"""Read the config file, if it exists. Using defaults otherwise."""
for config_file in self.config_file_paths():
logger.info('Search glances.conf file in {}'.format(config_file))
if os.path.exists(config_file):
try:
with open(config_file, encoding='utf-8') as f:
@ -142,7 +143,7 @@ class Config(object):
self.parser.read(f)
logger.info("Read configuration file '{}'".format(config_file))
except UnicodeDecodeError as err:
logger.error("Cannot decode configuration file '{}': {}".format(config_file, err))
logger.error("Can not read configuration file '{}': {}".format(config_file, err))
sys.exit(1)
# Save the loaded configuration file path (issue #374)
self._loaded_config_file = config_file

View File

@ -95,7 +95,7 @@ class _GlancesCurses(object):
_left_sidebar = ['network', 'wifi', 'ports', 'diskio', 'fs',
'irq', 'folders', 'raid', 'sensors', 'now']
_left_sidebar_min_width = 23
_left_sidebar_max_width = 84
_left_sidebar_max_width = 64
# Define right sidebar
_right_sidebar = ['docker', 'processcount', 'amps', 'processlist', 'alert']
@ -135,9 +135,6 @@ class _GlancesCurses(object):
# Init main window
self.term_window = self.screen.subwin(0, 0)
# Init refresh time
self.__refresh_time = args.time
# Init edit filter tag
self.edit_filter = False
@ -498,7 +495,9 @@ class _GlancesCurses(object):
ret = {}
for p in stats.getAllPlugins(enable=False):
if p == 'quicklook':
if p == 'quicklook' or p == 'processlist':
# processlist is done later
# because we need to know how many processes could be displayed
continue
# Compute the plugin max size
@ -538,7 +537,7 @@ class _GlancesCurses(object):
# Update the stats messages
###########################
# Update the client server status
# Get all the plugins but quicklook and proceslist
self.args.cs_status = cs_status
__stat_display = self.__get_stat_display(stats, layer=cs_status)
@ -560,6 +559,7 @@ class _GlancesCurses(object):
logger.debug("Set number of displayed processes to {}".format(max_processes_displayed))
glances_processes.max_processes = max_processes_displayed
# Get the processlist
__stat_display["processlist"] = stats.get_plugin(
'processlist').get_stats_display(args=self.args)
@ -694,7 +694,8 @@ class _GlancesCurses(object):
if self.args.full_quicklook:
quicklook_width = self.screen.getmaxyx()[1] - (stats_width + 8 + stats_number * self.space_between_column)
else:
quicklook_width = min(self.screen.getmaxyx()[1] - (stats_width + 8 + stats_number * self.space_between_column), 79)
quicklook_width = min(self.screen.getmaxyx()[1] - (stats_width + 8 + stats_number * self.space_between_column),
self._left_sidebar_max_width - 5)
try:
stat_display["quicklook"] = stats.get_plugin(
'quicklook').get_stats_display(max_width=quicklook_width, args=self.args)
@ -961,13 +962,18 @@ class _GlancesCurses(object):
self.erase()
self.display(stats, cs_status=cs_status)
def update(self, stats, cs_status=None, return_to_browser=False):
def update(self,
stats,
duration=3,
cs_status=None,
return_to_browser=False):
"""Update the screen.
Wait for __refresh_time sec / catch key every 100 ms.
Catch key every 100 ms.
INPUT
stats: Stats database to display
duration: duration of the loop
cs_status:
"None": standalone or server mode
"Connected": Client is connected to the server
@ -983,9 +989,15 @@ class _GlancesCurses(object):
# Flush display
self.flush(stats, cs_status=cs_status)
# If the duration is < 0 (update + export time > refresh_time)
# Then display the interface and log a message
if duration <= 0:
logger.debug('Update and export time higher than refresh_time.')
duration = 0.1
# Wait
exitkey = False
countdown = Timer(self.__refresh_time)
countdown = Timer(duration)
while not countdown.finished() and not exitkey:
# Getkey
pressedkey = self.__catch_key(return_to_browser=return_to_browser)

View File

@ -20,10 +20,11 @@
"""Process list plugin."""
import os
import shlex
from datetime import timedelta
from glances.compat import iteritems
from glances.globals import LINUX, WINDOWS
from glances.globals import WINDOWS
from glances.logger import logger
from glances.processes import glances_processes, sort_stats
from glances.plugins.glances_core import Plugin as CorePlugin
@ -43,16 +44,16 @@ def convert_timedelta(delta):
def split_cmdline(cmdline):
"""Return path, cmd and arguments for a process cmdline."""
path, cmd = os.path.split(cmdline[0])
arguments = ' '.join(cmdline[1:]).replace('\n', ' ')
# XXX: workaround for psutil issue #742
if LINUX and any(x in cmdline[0] for x in ('chrome', 'chromium')):
try:
exe, arguments = cmdline[0].split(' ', 1)
path, cmd = os.path.split(exe)
except ValueError:
arguments = None
# There is an issue in PsUtil for Electron/Atom processes (maybe others...)
# Tracked by https://github.com/nicolargo/glances/issues/1192
# https://github.com/giampaolo/psutil/issues/1179
# Add this dirty workarround (to be removed when the PsUtil is solved)
if len(cmdline) == 1:
cmdline = shlex.split(cmdline[0])
# /End of the direty workarround
path, cmd = os.path.split(cmdline[0])
arguments = ' '.join(cmdline[1:])
return path, cmd, arguments
@ -605,6 +606,9 @@ class Plugin(GlancesPlugin):
# Compute stats summary
ret = 0
for p in self.stats:
if key not in p:
# Correct issue #1188
continue
if indice is None:
ret += p[key]
else:

View File

@ -21,7 +21,7 @@
import operator
from glances.compat import u
from glances.compat import b
from glances.logger import logger
from glances.plugins.glances_plugin import GlancesPlugin
@ -101,8 +101,9 @@ class Plugin(GlancesPlugin):
# Grab the stats using the Wifi Python lib
try:
wifi_cells = Cell.all(net)
except InterfaceError:
except InterfaceError as e:
# Not a Wifi interface
logger.debug("WIFI plugin: Scan InterfaceError ({})".format(e))
pass
except Exception as e:
# Other error
@ -195,7 +196,7 @@ class Plugin(GlancesPlugin):
if len(hotspotname) > ifname_max_width:
hotspotname = '_' + hotspotname[-ifname_max_width + 1:]
# Add the new hotspot to the message
msg = '{:{width}}'.format(u(hotspotname),
msg = '{:{width}}'.format(b(hotspotname),
width=ifname_max_width)
ret.append(self.curse_add_line(msg))
msg = '{:>7}'.format(i['signal'], width=ifname_max_width)

View File

@ -19,8 +19,6 @@
"""Manage the Glances standalone session."""
import sched
import time
from glances.globals import WINDOWS
from glances.logger import logger
@ -28,6 +26,7 @@ from glances.processes import glances_processes
from glances.stats import GlancesStats
from glances.outputs.glances_curses import GlancesCursesStandalone
from glances.outdated import Outdated
from glances.timer import Counter
class GlancesStandalone(object):
@ -82,41 +81,35 @@ class GlancesStandalone(object):
# Check the latest Glances version
self.outdated = Outdated(config=config, args=args)
# Create the schedule instance
self.schedule = sched.scheduler(
timefunc=time.time, delayfunc=time.sleep)
@property
def quiet(self):
return self._quiet
def __serve_forever(self):
"""Main loop for the CLI."""
# Reschedule the function inside itself
self.schedule.enter(self.refresh_time, priority=0,
action=self.__serve_forever, argument=())
# Start a counter used to compute the time needed for
# update and export the stats
counter = Counter()
# Update system informations
# Update stats
self.stats.update()
logger.debug('Stats updated in {} seconds'.format(counter.get()))
# Update the screen
if not self.quiet:
self.screen.update(self.stats)
# Export stats using export modules
# Export stats
counter_export = Counter()
self.stats.export(self.stats)
logger.debug('Stats exported in {} seconds'.format(counter_export.get()))
# Display stats
# and wait refresh_time - counter
if not self.quiet:
self.screen.update(self.stats,
duration=self.refresh_time - counter.get())
def serve_forever(self):
"""Wrapper to the serve_forever function.
This function will restore the terminal to a sane state
before re-raising the exception and generating a traceback.
"""
self.__serve_forever()
try:
self.schedule.run()
finally:
self.end()
"""Wrapper to the serve_forever function."""
while True:
self.__serve_forever()
def end(self):
"""End of the standalone CLI."""