version 1.3.7

This commit is contained in:
nicolargo 2012-01-31 14:37:56 +01:00
parent 1a2626ed27
commit 1c2094998c
11 changed files with 391 additions and 352 deletions

2
NEWS
View File

@ -1,6 +1,8 @@
Version 1.3.7
=============
* Display (if terminal space is available) an alerts history (logs)
* Add a limits classe to manage stats limits
* Manage black and white console (issue #31)
Version 1.3.6

23
README
View File

@ -23,12 +23,12 @@ Packages exist for Arch, Fedora, Redhat ...
Get the latest version:
$ wget https://github.com/downloads/nicolargo/glances/glances-1.3.6.tar.gz
$ wget https://github.com/downloads/nicolargo/glances/glances-1.3.7.tar.gz
Glances use a standard GNU style installer:
$ tar zxvf glances-1.3.6.tar.gz
$ cd glances-1.3.6
$ tar zxvf glances-1.3.7.tar.gz
$ cd glances-1.3.7
$ ./configure
$ make
$ sudo make install
@ -85,6 +85,7 @@ When Glances is running, you can press:
* 'c' to sort the processes list by CPU consumption
* 'd' Disable or enable the disk IO stats
* 'f' Disable or enable the file system stats
* 'l' Disable or enable the logs
* 'm' to sort the processes list by process size
* 'n' Disable or enable the network interfaces stats
* 'q' Exit
@ -208,6 +209,22 @@ sorted by CPU of memory consumption.
The number of processes in the list is adapted to the screen size.
### Logs
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/logs.png)
A logs list is displayed in the bottom of the screen if (an only if):
* at least one WARNING or CRITICAL alert was occured.
* space is available in the bottom of the console/terminal
There is one line per alert with the following information:
* start date
* end date
* alert name
* (min/avg/max) values
### Footer
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/footer.png)

View File

@ -27,14 +27,14 @@ Le projet Glances est hébergé sur GitHUB: https://github.com/nicolargo/glances
Pour l'installer, il suffit de suivre les instructions suivantes depuis un
terminal.
Récupération de la dernière version (1.3.6):
Récupération de la dernière version (1.3.7):
$ wget https://github.com/downloads/nicolargo/glances/glances-1.3.6.tar.gz
$ wget https://github.com/downloads/nicolargo/glances/glances-1.3.7.tar.gz
Procédez ensuite à l'installation:
$ tar zxvf glances-1.3.6.tar.gz
$ cd glances-1.3.6
$ tar zxvf glances-1.3.7.tar.gz
$ cd glances-1.3.7
$ ./configure
$ make
$ sudo make install
@ -104,6 +104,7 @@ Quand Glances est lancé, il est possible d'utiliser les touches suivantes:
* 'c' pour forcer le tri par consommation CPU
* 'd' pour desactiver ou activer l'affichage des entrées/sorties disques
* 'f' pour desactiver ou activer l'affichage de l'occupation des FS
* 'l' pour desactiver ou activer l'affichage des logs
* 'm' pour forcer le tri par consommation MEMOIRE
* 'n' pour desactiver ou activer l'affichage des interfaces réseau
* 'q' sortir de Glances (il est également possible d'utiliser CTRL-C)
@ -229,6 +230,22 @@ détaillée.
Le nombre des processus affichés est adapté à la taille de la fenêtre.
### Logs
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/logs.png)
Une liste des dernières alertes relevées par Glances est affichée si:
* au moins une alerte de type WARNING ou CRITICAL est arrivée
* la console/fenêtre dispose de la place nécessaire
Glances affiche une ligne par alerte:
* date de début
* date de fin
* description de l'alerte
* valeur (min/moyenne/max) lors de l'alerte
### Pied de page
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/footer.png)
@ -254,6 +271,4 @@ Notamment:
* Packaging pour Debian, Ubuntu, BSD et toutes autres distributions
* Controle de la présence des librairie dans le fichier configure.ac
* Inclure les stats de FS directement dans python-statgrab
* Ajout d'une fenêtre d'aide
* Optimisation du code

231
README.md
View File

@ -1,231 +0,0 @@
[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=nicolargo&url=https://github.com/nicolargo/glances&title=Glances&language=&tags=github&category=software)
=============================
Glances -- Eye on your system
=============================
## Description
Glances is a CLI curses based monitoring tool for GNU/Linux or BSD OS.
Glances uses the libstatgrab library to get information from your system.
It is developed in Python and uses the python-statgrab lib.
![screenshot](https://github.com/nicolargo/glances/raw/master/screenshot.png)
## Installation
### From package manager
Packages exist for Arch, Fedora, Redhat ...
### From source
Get the latest version:
$ wget https://github.com/downloads/nicolargo/glances/glances-1.3.6.tar.gz
Glances use a standard GNU style installer:
$ tar zxvf glances-1.3.6.tar.gz
$ cd glances-1.3.6
$ ./configure
$ make
$ sudo make install
Pre-requisites:
* Python 2.6+ (not tested with Python 3+)
* python-statgrab 0.5+ (did NOT work with python-statgrab 0.4)
Notes: For Debian.
The Debian Squeeze repos only include the python-statgrab 0.4.
You had to install the version 0.5 using the following commands:
$ sudo apt-get install libstatgrab-dev pkg-config python-dev make
$ wget http://ftp.uk.i-scream.org/sites/ftp.i-scream.org/pub/i-scream/pystatgrab/pystatgrab-0.5.tar.gz
$ tar zxvf pystatgrab-0.5.tar.gz
$ cd pystatgrab-0.5/
$ ./setup.py build
$ sudo ./setup.py install
Notes: For Ubuntu 10.04 and 10.10.
The instruction to install the version 0.5 are here:
https://github.com/nicolargo/glances/issues/5#issuecomment-3033194
## Running
Easy:
$ glances.py
## User guide
By default, stats are refreshed every second, to change this setting, you can
use the -t option. For exemple to set the refrech rate to 5 seconds:
$ glances.py -t 5
Importants stats are colored:
* GREEN: stat counter is "OK"
* BLUE: stat counter is "CAREFUL"
* MAGENTA: stat counter is "WARNING"
* RED: stat counter is "CRITICAL"
When Glances is running, you can press:
* 'h' to display an help message whith the keys you can press
* 'a' to set the automatic mode. The processes are sorted automatically
If CPU > 70%, sort by process "CPU consumption"
If MEM > 70%, sort by process "memory size"
* 'c' to sort the processes list by CPU consumption
* 'd' Disable or enable the disk IO stats
* 'f' Disable or enable the file system stats
* 'm' to sort the processes list by process size
* 'n' Disable or enable the network interfaces stats
* 'q' Exit
### Header
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/header.png)
The header shows the Glances version, the host name and the operating
system name, version and architecture.
### CPU
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/cpu.png)
The CPU states are shown as a percentage and for the configured refresh
time.
If user|kernel|nice CPU is < 50%, then status is set to "OK".
If user|kernel|nice CPU is > 50%, then status is set to "CAREFUL".
If user|kernel|nice CPU is > 70%, then status is set to "WARNING".
If user|kernel|nice CPU is > 90%, then status is set to "CRITICAL".
### Load
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/load.png)
On the Nosheep blog, Zach defines the average load: "In short it is the
average sum of the number of processes waiting in the run-queue plus the
number currently executing over 1, 5, and 15 minute time periods."
Glances gets the number of CPU cores to adapt the alerts. With Glances,
alerts on average load are only set on 5 and 15 mins.
If average load is < O.7*Core, then status is set to "OK".
If average load is > O.7*Core, then status is set to "CAREFUL".
If average load is > 1*Core, then status is set to "WARNING".
If average load is > 5*Core, then status is set to "CRITICAL".
### Memory
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/mem.png)
Glances uses tree columns: memory (RAM), swap and "real".
Real used memory is: used - cache.
Real free memory is: free + cache.
With Glances, alerts are only set for on used swap and real memory.
If memory is < 50%, then status is set to "OK".
If memory is > 50%, then status is set to "CAREFUL".
If memory is > 70%, then status is set to "WARNING".
If memory is > 90%, then status is set to "CRITICAL".
### Network bit rate
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/network.png)
Glances display the network interface bit rate. The unit is adapted
dynamicaly (bits per second, Kbits per second, Mbits per second...).
Alerts are set only if the network interface maximum speed is available.
If bitrate is < 50%, then status is set to "OK".
If bitrate is > 50%, then status is set to "CAREFUL".
If bitrate is > 70%, then status is set to "WARNING".
If bitrate is > 90%, then status is set to "CRITICAL".
For exemple, on a 100 Mbps Ethernet interface, the warning status is set
if the bit rate is higher than 70 Mbps.
### Disk I/O
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/diskio.png)
Glances display the disk I/O throughput. The unit is adapted dynamicaly
(bytes per second, Kbytes per second, Mbytes per second...).
There is no alert on this information.
### Filesystem
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/fs.png)
Glances display the total and used filesytem disk space. The unit is
adapted dynamicaly (bytes per second, Kbytes per second, Mbytes per
second...).
Alerts are set for used disk space:
If disk used is < 50%, then status is set to "OK".
If disk used is > 50%, then status is set to "CAREFUL".
If disk used is > 70%, then status is set to "WARNING".
If disk used is > 90%, then status is set to "CRITICAL".
### Processes
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/processlist.png)
Glances displays a summary and a list of processes.
By default (or if you hit the 'a' key) the process list is automaticaly
sorted by CPU of memory consumption.
The number of processes in the list is adapted to the screen size.
### Footer
![screenshot](https://github.com/nicolargo/glances/raw/master/doc/footer.png)
Glances displays a caption and the current time/date.
## Localisation
To generate french locale execute as root or sudo :
i18n_francais_generate.sh
To generate spanish locale execute as root or sudo :
i18n_espanol_generate.sh
## Todo
You are welcome to contribute to this software.
* Packaging for Debian, Ubuntu, BSD...
* Check the needed Python library in the configure.ac
* Add file system stats when the python-statgrab is corrected

1
README.md Symbolic link
View File

@ -0,0 +1 @@
README

2
TODO
View File

@ -1,4 +1,4 @@
- Packaging for .deb (Debian|Ubuntu|Mint) Linux distributions (contributors needed)
- Test/coding for xBSD
- Add control to check the libstatgrab version in the script
- Add thermal information for CPU (issue #26)
- Add a limit class to manage the OK ,CAREFUL,WARNING,CRITICAL limits

View File

@ -30,7 +30,7 @@ include-site-packages = false
allowed-eggs-from-site-packages = false
[config]
glances_version = 1.3.6
glances_version = 1.3.7
pystatgrab_version = 0.5
pystatgrab_download_url = http://ftp.uk.i-scream.org/sites/ftp.i-scream.org/pub/i-scream/pystatgrab

BIN
doc/logs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,4 +1,4 @@
.TH glances 1 "January, 2012" "version 1.3.6" "USER COMMANDS"
.TH glances 1 "January, 2012" "version 1.3.7" "USER COMMANDS"
.SH NAME
glances \- CLI curses based monitoring tool
.SH SYNOPSIS
@ -22,6 +22,8 @@ You can use the following keys to sort the processesi list:
'f' Disable or enable the file system stats
.PP
'h' Hide or show the help message
.PP
'l' Hide or show the logs
.PP
'm' the processes list is sorted by process size
.PP

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 100 KiB

View File

@ -11,8 +11,8 @@ def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
setup( name='Glances',
version='1.3.6',
download_url='https://github.com/downloads/nicolargo/glances/glances-1.3.6.tar.gz',
version='1.3.7',
download_url='https://github.com/downloads/nicolargo/glances/glances-1.3.7.tar.gz',
url='https://github.com/nicolargo/glances',
description='CLI curses-based monitoring tool',
author='Nicolas Hennion',

View File

@ -10,7 +10,7 @@
# 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
# 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.
@ -19,26 +19,33 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.";
#
import os
import getopt
import sys
import signal
import time
import datetime
import multiprocessing
import gettext
from __future__ import generators
#i18n
#====
try:
import os
import getopt
import sys
import signal
import time
import datetime
import multiprocessing
import gettext
except KeyboardInterrupt:
pass
# i18n
#=====
application = 'glances'
__version__ = "1.3.7"
gettext.install(application)
try:
import statgrab
except:
print 'Statgrab initialization failed, Glances cannot start.'
print ''
print _('Statgrab initialization failed, Glances cannot start.')
print
sys.exit(1)
try:
@ -49,14 +56,9 @@ except:
print
sys.exit(1)
# Globals variables
#==================
# The glances version id
__version__ = "1.3.6"
# Class
#======
# Classes
#========
class Timer():
"""
@ -64,12 +66,147 @@ class Timer():
"""
def __init__(self, duration):
self.started(duration)
def started(self, duration):
self.target = time.time() + duration
def finished(self):
return time.time() > self.target
class glancesLimits():
"""
Manage the limit OK,CAREFUL,WARNING,CRITICAL for each stats
"""
# The limit list is stored in an hash table:
# limits_list[STAT] = [ CAREFUL , WARNING , CRITICAL ]
# Exemple:
# limits_list['STD'] = [ 50, 70 , 90 ]
__limits_list = { # CAREFUL WARNING CRITICAL
'STD': [50, 70, 90],
'LOAD': [0.7, 1.0, 5.0]
}
def getSTDCareful(self):
return self.__limits_list['STD'][0]
def getSTDWarning(self):
return self.__limits_list['STD'][1]
def getSTDCritical(self):
return self.__limits_list['STD'][2]
def getLOADCareful(self, core = 1):
return self.__limits_list['LOAD'][0] * core
def getLOADWarning(self, core = 1):
return self.__limits_list['LOAD'][1] * core
def getLOADCritical(self, core = 1):
return self.__limits_list['LOAD'][2] * core
class glancesLogs():
"""
The main class to manage logs inside the Glances software
Logs is a list of list:
[["begin", "end", "WARNING|CRITICAL", "CPU|LOAD|MEM", MAX, AVG, MIN, SUM, COUNT],...]
"""
def __init__(self):
"""
Init the logs classe
"""
# Maximum size of the logs list
self.logs_max = 10
# Init the logs list
self.logs_list = []
def get(self):
"""
Return the logs list (RAW)
"""
return self.logs_list
def len(self):
"""
Return the number of item in the log list
"""
return self.logs_list.__len__()
def __itemexist__(self, item_type):
"""
An item exist in the list if:
* end is < 0
* item_type is matching
"""
for i in range(self.len()):
if ((self.logs_list[i][1] < 0) and
(self.logs_list[i][3] == item_type)):
return i
return -1
def add(self, item_state, item_type, item_value):
"""
item_state = "OK|CAREFUL|WARNING|CRITICAL"
item_type = "CPU|LOAD|MEM"
item_value = value
Item is defined by:
["begin", "end", "WARNING|CRITICAL", "CPU|LOAD|MEM", MAX, AVG, MIN, SUM, COUNT]
If item is a 'new one':
Add the new item at the beginning of the logs list
Else:
Update the existing item
"""
item_index = self.__itemexist__(item_type)
if (item_index < 0):
# Item did not exist, add if WARNING or CRITICAL
if ((item_state == "WARNING") or
(item_state == "CRITICAL")):
# Time is stored in Epoch format
# Epoch -> DMYHMS = datetime.datetime.fromtimestamp(epoch)
item = []
item.append(time.mktime(datetime.datetime.now().timetuple()))
item.append(-1)
item.append(item_state) # STATE: WARNING|CRITICAL
item.append(item_type) # TYPE: CPU, LOAD, MEM...
item.append(item_value) # MAX
item.append(item_value) # AVG
item.append(item_value) # MIN
item.append(item_value) # SUM
item.append(1) # COUNT
self.logs_list.insert(0, item)
if (self.len() > self.logs_max):
self.logs_list.pop()
else:
# Item exist, update
if ((item_state == "OK") or
(item_state == "CAREFUL")):
# Close the item
self.logs_list[item_index][1] = time.mktime(datetime.datetime.now().timetuple())
else:
# Update the item
# State
if (item_state == "CRITICAL"):
self.logs_list[item_index][2] = item_state
# Value
if (item_value > self.logs_list[item_index][4]):
# MAX
self.logs_list[item_index][4] = item_value
elif (item_value < self.logs_list[item_index][6]):
# MIN
self.logs_list[item_index][6] = item_value
# AVG
self.logs_list[item_index][7] += item_value
self.logs_list[item_index][8] += 1
self.logs_list[item_index][5] = self.logs_list[item_index][7] / self.logs_list[item_index][8]
return self.len()
class glancesGrabFs():
"""
Get FS stats: idem as structure http://www.i-scream.org/libstatgrab/docs/sg_get_fs_stats.3.html
@ -281,7 +418,7 @@ class glancesStats():
# Else sort by cpu comsoption
sortedby = 'cpu_percent'
if ( self.mem['total'] != 0):
if ( ( (self.mem['used'] - self.mem['cache']) * 100 / self.mem['total']) > 70):
if ( ( (self.mem['used'] - self.mem['cache']) * 100 / self.mem['total']) > limits.getSTDWarning()):
sortedby = 'proc_size'
return sorted(self.process, key=lambda process: process[sortedby], reverse=True)
@ -296,8 +433,8 @@ class glancesScreen():
"""
# By default the process list is automaticaly sorted
# If global CPU > 75% => Sorted by process Cpu consomption
# If global used MEM > 75% => Sorted by process size
# If global CPU > WANRING => Sorted by process Cpu consomption
# If global used MEM > WARINING => Sorted by process size
__process_sortedby = 'auto'
def __init__(self, refresh_time = 1):
@ -315,6 +452,7 @@ class glancesScreen():
self.diskio_x = 0 ; self.diskio_y = -1
self.fs_x = 0 ; self.fs_y = -1
self.process_x = 30; self.process_y = 9
self.log_x = 0 ; self.log_y = -1
self.help_x = 30; self.help_y = 12
self.now_x = 79; self.now_y = 3
self.caption_x = 0 ; self.caption_y = 3
@ -355,29 +493,45 @@ class glancesScreen():
# Colors text styles
self.no_color = curses.color_pair(1)
self.default_color = curses.color_pair(3)|curses.A_BOLD
self.if50pc_color = curses.color_pair(4)|curses.A_BOLD
self.if70pc_color = curses.color_pair(5)|curses.A_BOLD
self.if90pc_color = curses.color_pair(2)|curses.A_BOLD
self.ifCAREFUL_color = curses.color_pair(4)|curses.A_BOLD
self.ifWARNING_color = curses.color_pair(5)|curses.A_BOLD
self.ifCRITICAL_color = curses.color_pair(2)|curses.A_BOLD
else:
# B&W text styles
self.no_color = curses.A_NORMAL
self.default_color = curses.A_NORMAL
self.if50pc_color = curses.A_UNDERLINE
self.if70pc_color = curses.A_BOLD
self.if90pc_color = curses.A_REVERSE
self.ifCAREFUL_color = curses.A_UNDERLINE
self.ifWARNING_color = curses.A_BOLD
self.ifCRITICAL_color = curses.A_REVERSE
# Define the colors list (hash table)
self.__colors_list = {
# CAREFUL WARNING CRITICAL
'DEFAULT': self.no_color,
'OK': self.default_color,
'CAREFUL': self.ifCAREFUL_color,
'WARNING': self.ifWARNING_color,
'CRITICAL': self.ifCRITICAL_color
}
# By default all the stats are displayed
self.network_tag = True
self.diskio_tag = True
self.fs_tag = True
self.log_tag = True
# Init main window
self.term_window = self.screen.subwin(0, 0)
# Init help panel
term_help = self.screen.subwin(self.term_h-self.help_y-2, self.term_w-self.help_x, self.help_y, self.help_x)
self.panel_help = curses.panel.new_panel(term_help)
self.hideHelp()
# TODO: pb when size of the screen < 22 lines
screen_x = self.screen.getmaxyx()[1]
screen_y = self.screen.getmaxyx()[0]
if (screen_x > (self.term_w-self.help_x) and
(screen_y > (self.term_h-self.help_y-2))):
term_help = self.screen.subwin(self.term_h-self.help_y-2, self.term_w-self.help_x, self.help_y, self.help_x)
self.panel_help = curses.panel.new_panel(term_help)
self.hideHelp()
# Init refresh time
self.__refresh_time = refresh_time
@ -413,69 +567,76 @@ class glancesScreen():
else:
return str(int(val))
def __getColor(self, current = 0, max = 100):
# If current > 50% of max then color = self.if50pc_color / A_DIM
# If current > 70% of max then color = self.if70pc_color / A_BOLD
# If current > 90% of max then color = self.if90pc_color / A_REVERSE
# By default: color = self.default_color / 0
def __getAlert(self, current = 0, max = 100):
# If current < CAREFUL of max then alert = OK
# If current > CAREFUL of max then alert = CAREFUL
# If current > WARNING of max then alert = WARNING
# If current > CRITICAL of max then alert = CRITICAL
try:
(current * 100) / max
except ZeroDivisionError:
return 0
return 'DEFAULT'
variable = (current * 100) / max
if variable > 90:
if self.hascolors:
return self.if90pc_color
else:
return curses.A_REVERSE
elif variable > 70:
if self.hascolors:
return self.if70pc_color
else:
return curses.A_BOLD
elif variable > 50:
if self.hascolors:
return self.if50pc_color
else:
return curses.A_DIM
else:
if self.hascolors:
return self.default_color
else:
return 0
if variable > limits.getSTDCritical():
return 'CRITICAL'
elif variable > limits.getSTDWarning():
return 'WARNING'
elif variable > limits.getSTDCareful():
return 'CAREFUL'
return 'OK'
def __getColor(self, current = 0, max = 100):
return self.__colors_list[self.__getAlert(current, max)]
def __getCpuAlert(self, current = 0, max = 100):
return self.__getAlert(current, max)
def __getCpuColor(self, current = 0, max = 100):
return self.__getColor(current, max)
def __getLoadAlert(self, current = 0, core = 1):
# If current < CAREFUL*core of max then alert = OK
# If current > CAREFUL*core of max then alert = CAREFUL
# If current > WARNING*core of max then alert = WARNING
# If current > CRITICAL*core of max then alert = CRITICAL
if current > limits.getLOADCritical(core):
return 'CRITICAL'
elif current > limits.getLOADWarning(core):
return 'WARNING'
elif current > limits.getLOADCareful(core):
return 'CAREFUL'
return 'OK'
def __getLoadColor(self, current = 0, core = 1):
# core is the number of CPU core
# If current > 0.7*core then color = self.if50pc_color / A_DIM
# If current > 1.0*core then color = self.if70pc_color / A_BOLD
# If current > 5.0*core then color = self.if90pc_color / A_REVERSE
# By default: color = self.default_color / 0
if current > (5.0 * core):
if self.hascolors:
return self.if90pc_color
else:
return curses.A_REVERSE
elif current > (1.0 * core):
if self.hascolors:
return self.if70pc_color
else:
return curses.A_BOLD
elif current > (0.7 * core):
if self.hascolors:
return self.if50pc_color
else:
return curses.A_DIM
else:
if self.hascolors:
return self.default_color
else:
return 0
return self.__colors_list[self.__getLoadAlert(current, core)]
def __getMemAlert(self, current = 0, max = 100):
return self.__getAlert(current, max)
def __getMemColor(self, current = 0, max = 100):
return self.__getColor(current, max)
def __getNetColor(self, current = 0, max = 100):
return self.__getColor(current, max)
def __getFsColor(self, current = 0, max = 100):
return self.__getColor(current, max)
def __catchKey(self):
# Get key
self.pressedkey = self.term_window.getch();
@ -504,6 +665,9 @@ class glancesScreen():
self.showHelp()
else:
self.hideHelp()
elif (self.pressedkey == 108):
# 'l' > Enable/Disable logs list
self.log_tag = not self.log_tag
elif (self.pressedkey == 109):
# 'm' > Sort process list by Mem usage
self.setProcessSortedBy('proc_size')
@ -530,8 +694,9 @@ class glancesScreen():
self.displayMem(stats.getMem(), stats.getMemSwap())
network_count = self.displayNetwork(stats.getNetwork(), stats.getNetworkInterface())
diskio_count = self.displayDiskIO(stats.getDiskIO(), self.network_y + network_count)
self.displayFs(stats.getFs(), self.network_y + network_count + diskio_count)
self.displayProcess(stats.getProcessCount(), stats.getProcessList(screen.getProcessSortedBy()))
fs_count = self.displayFs(stats.getFs(), self.network_y + network_count + diskio_count)
log_count = self.displayLog(self.network_y + network_count + diskio_count + fs_count)
self.displayProcess(stats.getProcessCount(), stats.getProcessList(screen.getProcessSortedBy()), log_count)
self.displayCaption()
self.displayNow(stats.getNow())
@ -580,11 +745,11 @@ class glancesScreen():
helpWindow.resize(self.term_h-self.help_y-2, self.term_w-self.help_x)
helpWindow.clear()
msg = _("Glances help (press 'h' to hide)")
helpWindow.addnstr(1, 2,_("'h'\tto display|hide this help message"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(2, 2,_("'a'\tto sort processes automatically"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(3, 2, _("'c'\tto sort processes by CPU consumption"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(4, 2, _("'d'\tto disable|enable the disk IO stats"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(5, 2, _("'f'\tto disable|enable the file system stats"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(1, 2, _("'a'\tto sort processes automatically"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(2, 2, _("'c'\tto sort processes by CPU consumption"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(3, 2, _("'d'\tto disable|enable the disk IO stats"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(4, 2, _("'f'\tto disable|enable the file system stats"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(5, 2, _("'l'\tto display|hide the logs messages"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(6, 2, _("'m'\tto sort processes by process size"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(7, 2, _("'n'\tto disable|enable the network interfaces stats"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
helpWindow.addnstr(8, 2, _("'q'\tto exit Glances"), self.term_w-self.help_x-4, self.help_color if self.hascolors else 0)
@ -643,9 +808,19 @@ class glancesScreen():
self.term_window.addnstr(self.cpu_y+2, self.cpu_x, _("Kernel:"), 8)
self.term_window.addnstr(self.cpu_y+3, self.cpu_x, _("Nice:"), 8)
self.term_window.addnstr(self.cpu_y+4, self.cpu_x, _("Idle:"), 8)
self.term_window.addnstr(self.cpu_y+1, self.cpu_x+10, "%.1f" % cpu['user'], 8, self.__getColor(cpu['user']))
self.term_window.addnstr(self.cpu_y+2, self.cpu_x+10, "%.1f" % cpu['kernel'], 8, self.__getColor(cpu['kernel']))
self.term_window.addnstr(self.cpu_y+3, self.cpu_x+10, "%.1f" % cpu['nice'], 8, self.__getColor(cpu['nice']))
alert = self.__getCpuAlert(cpu['user'])
logs.add(alert, "CPU user", cpu['user'])
self.term_window.addnstr(self.cpu_y+1, self.cpu_x+10, "%.1f" % cpu['user'], 8, self.__colors_list[alert])
alert = self.__getCpuAlert(cpu['kernel'])
logs.add(alert, "CPU kernel", cpu['kernel'])
self.term_window.addnstr(self.cpu_y+2, self.cpu_x+10, "%.1f" % cpu['kernel'], 8, self.__colors_list[alert])
alert = self.__getCpuAlert(cpu['nice'])
logs.add(alert, "CPU nice", cpu['nice'])
self.term_window.addnstr(self.cpu_y+3, self.cpu_x+10, "%.1f" % cpu['nice'], 8, self.__colors_list[alert])
self.term_window.addnstr(self.cpu_y+4, self.cpu_x+10, "%.1f" % cpu['idle'], 8)
@ -662,9 +837,16 @@ class glancesScreen():
self.term_window.addnstr(self.load_y+1, self.load_x, _("1 min:"), 8)
self.term_window.addnstr(self.load_y+2, self.load_x, _("5 mins:"), 8)
self.term_window.addnstr(self.load_y+3, self.load_x, _("15 mins:"), 8)
self.term_window.addnstr(self.load_y+1, self.load_x+10, str(load['min1']), 8)
self.term_window.addnstr(self.load_y+2, self.load_x+10, str(load['min5']), 8, self.__getLoadColor(load['min5'], core))
self.term_window.addnstr(self.load_y+3, self.load_x+10, str(load['min15']), 8, self.__getLoadColor(load['min15'], core))
alert = self.__getLoadAlert(load['min5'], core)
logs.add(alert, "LOAD 5-mins", load['min5'])
self.term_window.addnstr(self.load_y+2, self.load_x+10, str(load['min5']), 8, self.__colors_list[alert])
alert = self.__getLoadAlert(load['min15'], core)
logs.add(alert, "LOAD 15-mins", load['min15'])
self.term_window.addnstr(self.load_y+3, self.load_x+10, str(load['min15']), 8, self.__colors_list[alert])
def displayMem(self, mem, memswap):
@ -682,14 +864,21 @@ class glancesScreen():
self.term_window.addnstr(self.mem_y+1, self.mem_x, _("Total:"), 8)
self.term_window.addnstr(self.mem_y+2, self.mem_x, _("Used:"), 8)
self.term_window.addnstr(self.mem_y+3, self.mem_x, _("Free:"), 8)
self.term_window.addnstr(self.mem_y+1, self.mem_x+10, str(mem['total']/1048576), 8)
self.term_window.addnstr(self.mem_y+2, self.mem_x+10, str(mem['used']/1048576), 8)
self.term_window.addnstr(self.mem_y+3, self.mem_x+10, str(mem['free']/1048576), 8)
alert = self.__getMemAlert(memswap['used'], memswap['total'])
logs.add(alert, "MEM swap", memswap['used']/1048576)
self.term_window.addnstr(self.mem_y+1, self.mem_x+20, str(memswap['total']/1048576), 8)
self.term_window.addnstr(self.mem_y+2, self.mem_x+20, str(memswap['used']/1048576), 8, self.__getColor(memswap['used'], memswap['total']))
self.term_window.addnstr(self.mem_y+2, self.mem_x+20, str(memswap['used']/1048576), 8, self.__colors_list[alert])
self.term_window.addnstr(self.mem_y+3, self.mem_x+20, str(memswap['free']/1048576), 8)
alert = self.__getMemAlert(mem['used']-mem['cache'], mem['total'])
logs.add(alert, "MEM real", (mem['used']-mem['cache'])/1048576)
self.term_window.addnstr(self.mem_y+1, self.mem_x+30, "-", 8)
self.term_window.addnstr(self.mem_y+2, self.mem_x+30, str((mem['used']-mem['cache'])/1048576), 8, self.__getColor(mem['used']-mem['cache'], mem['total']))
self.term_window.addnstr(self.mem_y+2, self.mem_x+30, str((mem['used']-mem['cache'])/1048576), 8, self.__colors_list[alert])
self.term_window.addnstr(self.mem_y+3, self.mem_x+30, str((mem['free']+mem['cache'])/1048576), 8)
@ -727,8 +916,8 @@ class glancesScreen():
break
elapsed_time = max (1, network[i]['systime'])
self.term_window.addnstr(self.network_y+1+i, self.network_x, network[i]['interface_name']+':', 8)
self.term_window.addnstr(self.network_y+1+i, self.network_x+10, self.__autoUnit(network[i]['rx']/elapsed_time*8) + "b", 8, self.__getColor(network[i]['rx']/elapsed_time*8, speed[network[i]['interface_name']]))
self.term_window.addnstr(self.network_y+1+i, self.network_x+20, self.__autoUnit(network[i]['tx']/elapsed_time*8) + "b", 8, self.__getColor(network[i]['tx']/elapsed_time*8, speed[network[i]['interface_name']]))
self.term_window.addnstr(self.network_y+1+i, self.network_x+10, self.__autoUnit(network[i]['rx']/elapsed_time*8) + "b", 8, self.__getNetColor(network[i]['rx']/elapsed_time*8, speed[network[i]['interface_name']]))
self.term_window.addnstr(self.network_y+1+i, self.network_x+20, self.__autoUnit(network[i]['tx']/elapsed_time*8) + "b", 8, self.__getNetColor(network[i]['tx']/elapsed_time*8, speed[network[i]['interface_name']]))
ret = ret + 1
return ret
return 0
@ -774,12 +963,47 @@ class glancesScreen():
for mounted in range(0, min(screen_y-self.fs_y-3, len(fs))):
self.term_window.addnstr(self.fs_y+1+mounted, self.fs_x, fs[mounted]['mnt_point'], 8)
self.term_window.addnstr(self.fs_y+1+mounted, self.fs_x+10, self.__autoUnit(fs[mounted]['size']), 8)
self.term_window.addnstr(self.fs_y+1+mounted, self.fs_x+20, self.__autoUnit(fs[mounted]['used']), 8, self.__getColor(fs[mounted]['used'], fs[mounted]['size']))
self.term_window.addnstr(self.fs_y+1+mounted, self.fs_x+20, self.__autoUnit(fs[mounted]['used']), 8, self.__getFsColor(fs[mounted]['used'], fs[mounted]['size']))
return mounted+3
return 0
def displayProcess(self, processcount, processlist):
def displayLog(self, offset_y = 0):
# Logs
if ((logs.len() == 0) or not self.log_tag):
return 0
screen_x = self.screen.getmaxyx()[1]
screen_y = self.screen.getmaxyx()[0]
self.log_y = offset_y
if ((screen_y > self.log_y+3)
and (screen_x > self.log_x+79)):
self.log_y = max(offset_y, screen_y-3-min(offset_y-3, screen_y-self.log_y, logs.len()))
logtodisplay_count = min(screen_y-self.log_y-3, logs.len())
logmsg = _("Warning and Critical logs for CPU|LOAD|MEM")
if (logtodisplay_count > 1):
logmsg += _(" (lasts ") + str(logtodisplay_count) + _(" entries)")
else:
logmsg += _(" (one entry)")
self.term_window.addnstr(self.log_y, self.log_x, logmsg, 79, self.title_color if self.hascolors else curses.A_UNDERLINE)
# Adapt the maximum log to the screen
logcount = 0
log = logs.get()
for logcount in range(0, logtodisplay_count):
logmsg = " "+str(datetime.datetime.fromtimestamp(log[logcount][0]))
if (log[logcount][1] > 0):
logmark = ' '
logmsg += " > " +str(datetime.datetime.fromtimestamp(log[logcount][1]))
else:
logmark = '~'
logmsg += " > " +"%19s" % "___________________"
logmsg += " " +log[logcount][3] + " (%.1f/" % log[logcount][6] + "%.1f/" % log[logcount][5] + "%.1f)" % log[logcount][4]
self.term_window.addnstr(self.log_y+1+logcount, self.log_x, logmsg, 79)
self.term_window.addnstr(self.log_y+1+logcount, self.log_x, logmark, 1, self.__colors_list[log[logcount][2]])
return logcount+3
return 0
def displayProcess(self, processcount, processlist, log_count = 0):
# Process
if (not processcount or not processlist):
return 0
@ -821,7 +1045,7 @@ class glancesScreen():
self.term_window.addnstr(self.process_y+3, process_x+10,_("Size MB")+sortchar, 8)
self.term_window.addnstr(self.process_y+3, process_x+20,_("Res MB"), 8)
self.term_window.addnstr(self.process_y+3, process_x+30,_("Name"), 8)
for processes in range(0, min(screen_y-self.term_h+self.process_y, len(processlist))):
for processes in range(0, min(screen_y-self.term_h+self.process_y-log_count, len(processlist))):
self.term_window.addnstr(self.process_y+4+processes, process_x, "%.1f" % processlist[processes]['cpu_percent'], 8, self.__getColor(processlist[processes]['cpu_percent']))
self.term_window.addnstr(self.process_y+4+processes, process_x+10, str((processlist[processes]['proc_size'])/1048576), 8)
self.term_window.addnstr(self.process_y+4+processes, process_x+20, str((processlist[processes]['proc_resident'])/1048576), 8)
@ -842,9 +1066,9 @@ class glancesScreen():
if ((screen_y > self.caption_y)
and (screen_x > self.caption_x+32)):
self.term_window.addnstr(max(self.caption_y, screen_y-1), self.caption_x, _(" OK "), 8, self.default_color)
self.term_window.addnstr(max(self.caption_y, screen_y-1), self.caption_x+8, _("CAREFUL "), 8, self.if50pc_color)
self.term_window.addnstr(max(self.caption_y, screen_y-1), self.caption_x+16, _("WARNING "), 8, self.if70pc_color)
self.term_window.addnstr(max(self.caption_y, screen_y-1), self.caption_x+24, _("CRITICAL"), 8, self.if90pc_color)
self.term_window.addnstr(max(self.caption_y, screen_y-1), self.caption_x+8, _("CAREFUL "), 8, self.ifCAREFUL_color)
self.term_window.addnstr(max(self.caption_y, screen_y-1), self.caption_x+16, _("WARNING "), 8, self.ifWARNING_color)
self.term_window.addnstr(max(self.caption_y, screen_y-1), self.caption_x+24, _("CRITICAL"), 8, self.ifCRITICAL_color)
def displayNow(self, now):
@ -880,6 +1104,7 @@ def printSyntax():
print _("'d' to disable or enable the disk IO stats")
print _("'f' to disable or enable the file system stats")
print _("'h' to hide or show the help message")
print _("'l' to hide or show the logs messages")
print _("'m' to sort the processes list by process size")
print _("'n' to disable or enable the network interfaces stats")
print _("'q' to exit")
@ -887,7 +1112,7 @@ def printSyntax():
def init():
global stats, screen
global limits, logs, stats, screen
global refresh_time
refresh_time = 1
@ -917,6 +1142,12 @@ def init():
# Catch CTRL-C
signal.signal(signal.SIGINT, signal_handler)
# Init Limits
limits = glancesLimits()
# Init Logs
logs = glancesLogs()
# Init stats
stats = glancesStats()
@ -925,6 +1156,7 @@ def init():
def main():
# Init stuff
init()
@ -940,6 +1172,7 @@ def main():
def end():
stats.end()
screen.end()
sys.exit(0)