dstat (dstat-0.7.3) | : | dstat (dstat-0.7.4) | ||
---|---|---|---|---|
#!/usr/bin/env python2 | #!/usr/bin/env python | |||
### This program is free software; you can redistribute it and/or | ### This program is free software; you can redistribute it and/or | |||
### modify it under the terms of the GNU General Public License | ### modify it under the terms of the GNU General Public License | |||
### as published by the Free Software Foundation; either version 2 | ### as published by the Free Software Foundation; either version 2 | |||
### of the License, or (at your option) any later version. | ### of the License, or (at your option) any later version. | |||
### | ### | |||
### This program is distributed in the hope that it will be useful, | ### This program is distributed in the hope that it will be useful, | |||
### but WITHOUT ANY WARRANTY; without even the implied warranty of | ### but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
### GNU General Public License for more details. | ### GNU General Public License for more details. | |||
### | ### | |||
### You should have received a copy of the GNU General Public License | ### You should have received a copy of the GNU General Public License | |||
### along with this program; if not, write to the Free Software | ### along with this program; if not, write to the Free Software | |||
### Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA. | ### Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U SA. | |||
### Copyright 2004-2016 Dag Wieers <dag@wieers.com> | ### Copyright 2004-2019 Dag Wieers <dag@wieers.com> | |||
from __future__ import generators | from __future__ import absolute_import, division, generators, print_function | |||
__metaclass__ = type | ||||
try: | import collections | |||
import sys, os, time, sched, re, getopt, fnmatch | import fnmatch | |||
import types, resource, getpass, glob, linecache | import getopt | |||
except KeyboardInterrupt: | import getpass | |||
pass | import glob | |||
import linecache | ||||
import os | ||||
import re | ||||
import resource | ||||
import sched | ||||
import six | ||||
import sys | ||||
import time | ||||
VERSION = '0.7.3' | VERSION = '0.8.0' | |||
theme = { 'default': '' } | theme = { 'default': '' } | |||
if sys.version_info < (2, 2): | if sys.version_info < (2, 2): | |||
sys.exit('error: Python 2.2 or later required') | sys.exit('error: Python 2.2 or later required') | |||
### Workaround for python <= 2.2.1 | ||||
try: | ||||
True, False | ||||
except NameError: | ||||
True = 1 | ||||
False = 0 | ||||
### Workaround for python < 2.3 | ||||
#if 'enumerate' not in __builtins__.__dict__.keys(): | ||||
if sys.version_info >= (2, 2) and sys.version_info < (2, 3): | ||||
def enumerate(sequence): | ||||
index = 0 | ||||
for item in sequence: | ||||
yield index, item | ||||
index = index + 1 | ||||
elif sys.version_info < (2, 2): | ||||
def enumerate(sequence): | ||||
index = 0 | ||||
seqlist = [] | ||||
for item in sequence: | ||||
seqlist.append((index, item)) | ||||
index = index + 1 | ||||
return seqlist | ||||
### Workaround for python < 2.3 | ||||
#if 'sum' not in __builtins__.__dict__.keys(): | ||||
if sys.version_info < (2, 3): | ||||
def sum(sequence): | ||||
ret = 0 | ||||
for i in sequence: | ||||
ret = ret + i | ||||
return ret | ||||
pluginpath = [ | pluginpath = [ | |||
os.path.expanduser('~/.dstat/'), # home + /.d stat/ | os.path.expanduser('~/.dstat/'), # home + /.d stat/ | |||
os.path.abspath(os.path.dirname(sys.argv[0])) + '/plugins/', # binary pat h + /plugins/ | os.path.abspath(os.path.dirname(sys.argv[0])) + '/plugins/', # binary pat h + /plugins/ | |||
'/usr/share/dstat/', | '/usr/share/dstat/', | |||
'/usr/local/share/dstat/', | '/usr/local/share/dstat/', | |||
] | ] | |||
class Options: | class Options: | |||
def __init__(self, args): | def __init__(self, args): | |||
self.args = args | self.args = args | |||
skipping to change at line 122 | skipping to change at line 98 | |||
'lores': ('sd[b-k]', 'sd[v-z]', 'sda[a-e]'), | 'lores': ('sd[b-k]', 'sd[v-z]', 'sda[a-e]'), | |||
'hires': ('sd[l-u]', 'sda[f-o]'), | 'hires': ('sd[l-u]', 'sda[f-o]'), | |||
} | } | |||
try: | try: | |||
opts, args = getopt.getopt(args, 'acdfghilmno:prstTvyC:D:I:M:N:S:V', | opts, args = getopt.getopt(args, 'acdfghilmno:prstTvyC:D:I:M:N:S:V', | |||
['all', 'all-plugins', 'bits', 'bw', 'black-on-white', 'color', | ['all', 'all-plugins', 'bits', 'bw', 'black-on-white', 'color', | |||
'debug', 'filesystem', 'float', 'full', 'help', 'integer', | 'debug', 'filesystem', 'float', 'full', 'help', 'integer', | |||
'list', 'mods', 'modules', 'nocolor', 'noheaders', 'noupdate', | 'list', 'mods', 'modules', 'nocolor', 'noheaders', 'noupdate', | |||
'output=', 'pidfile=', 'profile', 'version', 'vmstat'] + allplu gins) | 'output=', 'pidfile=', 'profile', 'version', 'vmstat'] + allplu gins) | |||
except getopt.error, exc: | except getopt.error as exc: | |||
print 'dstat: %s, try dstat -h for a list of all the options' % str( | print('dstat: %s, try dstat -h for a list of all the options' % exc) | |||
exc) | ||||
sys.exit(1) | sys.exit(1) | |||
for opt, arg in opts: | for opt, arg in opts: | |||
if opt in ['-c']: | if opt in ['-c']: | |||
self.plugins.append('cpu') | self.plugins.append('cpu') | |||
elif opt in ['-C']: | elif opt in ['-C']: | |||
self.cpulist = arg.split(',') | self.cpulist = arg.split(',') | |||
elif opt in ['-d']: | elif opt in ['-d']: | |||
self.plugins.append('disk') | self.plugins.append('disk') | |||
elif opt in ['-D']: | elif opt in ['-D']: | |||
skipping to change at line 148 | skipping to change at line 124 | |||
self.plugins.append('page') | self.plugins.append('page') | |||
elif opt in ['-i']: | elif opt in ['-i']: | |||
self.plugins.append('int') | self.plugins.append('int') | |||
elif opt in ['-I']: | elif opt in ['-I']: | |||
self.intlist = arg.split(',') | self.intlist = arg.split(',') | |||
elif opt in ['-l']: | elif opt in ['-l']: | |||
self.plugins.append('load') | self.plugins.append('load') | |||
elif opt in ['-m']: | elif opt in ['-m']: | |||
self.plugins.append('mem') | self.plugins.append('mem') | |||
elif opt in ['-M', '--mods', '--modules']: | elif opt in ['-M', '--mods', '--modules']: | |||
print >>sys.stderr, 'WARNING: Option %s is deprecated, please us e --%s instead' % (opt, ' --'.join(arg.split(','))) | print('WARNING: Option %s is deprecated, please use --%s instead ' % (opt, ' --'.join(arg.split(','))), file=sys.stderr) | |||
self.plugins += arg.split(',') | self.plugins += arg.split(',') | |||
elif opt in ['-n']: | elif opt in ['-n']: | |||
self.plugins.append('net') | self.plugins.append('net') | |||
elif opt in ['-N']: | elif opt in ['-N']: | |||
self.netlist = arg.split(',') | self.netlist = arg.split(',') | |||
elif opt in ['-p']: | elif opt in ['-p']: | |||
self.plugins.append('proc') | self.plugins.append('proc') | |||
elif opt in ['-r']: | elif opt in ['-r']: | |||
self.plugins.append('io') | self.plugins.append('io') | |||
elif opt in ['-s']: | elif opt in ['-s']: | |||
skipping to change at line 178 | skipping to change at line 154 | |||
elif opt in ['-a', '--all']: | elif opt in ['-a', '--all']: | |||
self.plugins += [ 'cpu', 'disk', 'net', 'page', 'sys' ] | self.plugins += [ 'cpu', 'disk', 'net', 'page', 'sys' ] | |||
elif opt in ['-v', '--vmstat']: | elif opt in ['-v', '--vmstat']: | |||
self.plugins += [ 'proc', 'mem', 'page', 'disk', 'sys', 'cpu' ] | self.plugins += [ 'proc', 'mem', 'page', 'disk', 'sys', 'cpu' ] | |||
elif opt in ['-f', '--full']: | elif opt in ['-f', '--full']: | |||
self.full = True | self.full = True | |||
elif opt in ['--all-plugins']: | elif opt in ['--all-plugins']: | |||
### Make list unique in a fancy fast way | ### Make list unique in a fancy fast way | |||
plugins = {}.fromkeys(allplugins).keys() | plugins = list({}.fromkeys(allplugins).keys()) | |||
plugins.sort() | plugins.sort() | |||
self.plugins += plugins | self.plugins += plugins | |||
elif opt in ['--bits']: | elif opt in ['--bits']: | |||
self.bits = True | self.bits = True | |||
elif opt in ['--bw', '--black-on-white', '--blackonwhite']: | elif opt in ['--bw', '--black-on-white', '--blackonwhite']: | |||
self.blackonwhite = True | self.blackonwhite = True | |||
elif opt in ['--color']: | elif opt in ['--color']: | |||
self.color = True | self.color = True | |||
self.update = True | self.update = True | |||
elif opt in ['--debug']: | elif opt in ['--debug']: | |||
skipping to change at line 219 | skipping to change at line 195 | |||
elif opt in ['-h', '--help']: | elif opt in ['-h', '--help']: | |||
self.usage() | self.usage() | |||
self.help() | self.help() | |||
sys.exit(0) | sys.exit(0) | |||
elif opt in ['-V', '--version']: | elif opt in ['-V', '--version']: | |||
self.version() | self.version() | |||
sys.exit(0) | sys.exit(0) | |||
elif opt.startswith('--'): | elif opt.startswith('--'): | |||
self.plugins.append(opt[2:]) | self.plugins.append(opt[2:]) | |||
else: | else: | |||
print 'dstat: option %s unknown to getopt, try dstat -h for a li st of all the options' % opt | print('dstat: option %s unknown to getopt, try dstat -h for a li st of all the options' % opt) | |||
sys.exit(1) | sys.exit(1) | |||
if self.float and self.integer: | if self.float and self.integer: | |||
print 'dstat: option --float and --integer are mutual exclusive, you can only force one' | print('dstat: option --float and --integer are mutual exclusive, you can only force one') | |||
sys.exit(1) | sys.exit(1) | |||
if not self.plugins: | if not self.plugins: | |||
print 'You did not select any stats, using -cdngy by default.' | print('You did not select any stats, using -cdngy by default.') | |||
self.plugins = [ 'cpu', 'disk', 'net', 'page', 'sys' ] | self.plugins = [ 'cpu', 'disk', 'net', 'page', 'sys' ] | |||
try: | try: | |||
if len(args) > 0: self.delay = int(args[0]) | if len(args) > 0: self.delay = int(args[0]) | |||
if len(args) > 1: self.count = int(args[1]) | if len(args) > 1: self.count = int(args[1]) | |||
except: | except: | |||
print 'dstat: incorrect argument, try dstat -h for the correct synta x' | print('dstat: incorrect argument, try dstat -h for the correct synta x') | |||
sys.exit(1) | sys.exit(1) | |||
if self.delay <= 0: | if self.delay <= 0: | |||
print 'dstat: delay must be an integer, greater than zero' | print('dstat: delay must be an integer, greater than zero') | |||
sys.exit(1) | sys.exit(1) | |||
if self.debug: | if self.debug: | |||
print 'Plugins: %s' % self.plugins | print('Plugins: %s' % self.plugins) | |||
def version(self): | def version(self): | |||
print 'Dstat %s' % VERSION | print('Dstat %s' % VERSION) | |||
print 'Written by Dag Wieers <dag@wieers.com>' | print('Written by Dag Wieers <dag@wieers.com>') | |||
print 'Homepage at http://dag.wieers.com/home-made/dstat/' | print('Homepage at http://dag.wieers.com/home-made/dstat/') | |||
print() | ||||
print 'Platform %s/%s' % (os.name, sys.platform) | print('Platform %s/%s' % (os.name, sys.platform)) | |||
print 'Kernel %s' % os.uname()[2] | print('Kernel %s' % os.uname()[2]) | |||
print 'Python %s' % sys.version | print('Python %s' % sys.version) | |||
print() | ||||
color = "" | color = "" | |||
if not gettermcolor(): | if not gettermcolor(): | |||
color = "no " | color = "no " | |||
print 'Terminal type: %s (%scolor support)' % (os.getenv('TERM'), color) | print('Terminal type: %s (%scolor support)' % (os.getenv('TERM'), color) ) | |||
rows, cols = gettermsize() | rows, cols = gettermsize() | |||
print 'Terminal size: %d lines, %d columns' % (rows, cols) | print('Terminal size: %d lines, %d columns' % (rows, cols)) | |||
print() | ||||
print 'Processors: %d' % getcpunr() | print('Processors: %d' % getcpunr()) | |||
print 'Pagesize: %d' % resource.getpagesize() | print('Pagesize: %d' % resource.getpagesize()) | |||
print 'Clock ticks per secs: %d' % os.sysconf('SC_CLK_TCK') | print('Clock ticks per secs: %d' % os.sysconf('SC_CLK_TCK')) | |||
print() | ||||
global op | global op | |||
op = self | op = self | |||
showplugins() | showplugins() | |||
def usage(self): | def usage(self): | |||
print 'Usage: dstat [-afv] [options..] [delay [count]]' | print('Usage: dstat [-afv] [options..] [delay [count]]') | |||
def help(self): | def help(self): | |||
print '''Versatile tool for generating system resource statistics | print('''Versatile tool for generating system resource statistics) | |||
Dstat options: | Dstat options: | |||
-c, --cpu enable cpu stats | -c, --cpu enable cpu stats | |||
-C 0,3,total include cpu0, cpu3 and total | -C 0,3,total include cpu0, cpu3 and total | |||
-d, --disk enable disk stats | -d, --disk enable disk stats | |||
-D total,hda include hda and total | -D total,hda include hda and total | |||
-g, --page enable page stats | -g, --page enable page stats | |||
-i, --int enable interrupt stats | -i, --int enable interrupt stats | |||
-I 5,eth2 include int5 and interrupt used by eth2 | -I 5,eth2 include int5 and interrupt used by eth2 | |||
-l, --load enable load stats | -l, --load enable load stats | |||
skipping to change at line 310 | skipping to change at line 286 | |||
--raw enable raw stats | --raw enable raw stats | |||
--socket enable socket stats | --socket enable socket stats | |||
--tcp enable tcp stats | --tcp enable tcp stats | |||
--udp enable udp stats | --udp enable udp stats | |||
--unix enable unix stats | --unix enable unix stats | |||
--vm enable vm stats | --vm enable vm stats | |||
--vm-adv enable advanced vm stats | --vm-adv enable advanced vm stats | |||
--zones enable zoneinfo stats | --zones enable zoneinfo stats | |||
--list list all available plugins | --list list all available plugins | |||
--plugin enable external plugin by name (see --list) | --<plugin-name> enable external plugin by name (see --list) | |||
-a, --all equals -cdngy (default) | -a, --all equals -cdngy (default) | |||
-f, --full automatically expand -C, -D, -I, -N and -S lists | -f, --full automatically expand -C, -D, -I, -N and -S lists | |||
-v, --vmstat equals -pmgdsc -D total | -v, --vmstat equals -pmgdsc -D total | |||
--bits force bits for values expressed in bytes | --bits force bits for values expressed in bytes | |||
--float force float values on screen | --float force float values on screen | |||
--integer force integer values on screen | --integer force integer values on screen | |||
--bw, --black-on-white change colors for white background terminal | --bw, --black-on-white change colors for white background terminal | |||
--color force colors | --color force colors | |||
--nocolor disable colors | --nocolor disable colors | |||
--noheaders disable repetitive headers | --noheaders disable repetitive headers | |||
--noupdate disable intermediate updates | --noupdate disable intermediate updates | |||
--output file write CSV output to file | --output file write CSV output to file | |||
--profile show profiling statistics when exiting dstat | --profile show profiling statistics when exiting dstat | |||
delay is the delay in seconds between each update (default: 1) | delay is the delay in seconds between each update (default: 1) | |||
count is the number of updates to display before exiting (default: unlimited) | count is the number of updates to display before exiting (default: unlimited) | |||
''' | ''') | |||
### START STATS DEFINITIONS ### | ### START STATS DEFINITIONS ### | |||
class dstat: | class dstat: | |||
vars = None | vars = None | |||
name = None | name = None | |||
nick = None | nick = None | |||
type = 'f' | type = 'f' | |||
types = () | types = () | |||
width = 5 | width = 5 | |||
scale = 1024 | scale = 1024 | |||
skipping to change at line 354 | skipping to change at line 330 | |||
# val = {} | # val = {} | |||
# set1 = {} | # set1 = {} | |||
# set2 = {} | # set2 = {} | |||
def prepare(self): | def prepare(self): | |||
if callable(self.discover): | if callable(self.discover): | |||
self.discover = self.discover() | self.discover = self.discover() | |||
if callable(self.vars): | if callable(self.vars): | |||
self.vars = self.vars() | self.vars = self.vars() | |||
if not self.vars: | if not self.vars: | |||
raise Exception, 'No counter objects to monitor' | raise Exception('No counter objects to monitor') | |||
if callable(self.name): | if callable(self.name): | |||
self.name = self.name() | self.name = self.name() | |||
if callable(self.nick): | if callable(self.nick): | |||
self.nick = self.nick() | self.nick = self.nick() | |||
if not self.nick: | if not self.nick: | |||
self.nick = self.vars | self.nick = self.vars | |||
self.val = {}; self.set1 = {}; self.set2 = {} | self.val = {}; self.set1 = {}; self.set2 = {} | |||
if self.struct: ### Plugin API version 2 | if self.struct: ### Plugin API version 2 | |||
for name in self.vars + [ 'total', ]: | for name in self.vars + [ 'total', ]: | |||
self.val[name] = self.struct | self.val[name] = self.struct | |||
self.set1[name] = self.struct | self.set1[name] = self.struct | |||
self.set2[name] = {} | self.set2[name] = {} | |||
elif self.cols <= 0: ### Plugin API version 1 | elif self.cols <= 0: ### Plugin API version 1 | |||
for name in self.vars: | for name in self.vars: | |||
self.val[name] = self.set1[name] = self.set2[name] = 0 | self.val[name] = self.set1[name] = self.set2[name] = 0 | |||
else: ### Plugin API version 1 | else: ### Plugin API version 1 | |||
for name in self.vars + [ 'total', ]: | for name in self.vars + [ 'total', ]: | |||
self.val[name] = range(self.cols) | self.val[name] = list(range(self.cols)) | |||
self.set1[name] = range(self.cols) | self.set1[name] = list(range(self.cols)) | |||
self.set2[name] = range(self.cols) | self.set2[name] = list(range(self.cols)) | |||
for i in range(self.cols): | for i in list(range(self.cols)): | |||
self.val[name][i] = self.set1[name][i] = self.set2[name][i] = 0 | self.val[name][i] = self.set1[name][i] = self.set2[name][i] = 0 | |||
# print self.val | # print(self.val) | |||
def open(self, *filenames): | def open(self, *filenames): | |||
"Open stat file descriptor" | "Open stat file descriptor" | |||
self.file = [] | self.file = [] | |||
self.fd = [] | self.fd = [] | |||
for filename in filenames: | for filename in filenames: | |||
try: | try: | |||
fd = dopen(filename) | fd = dopen(filename) | |||
if fd: | if fd: | |||
self.file.append(filename) | self.file.append(filename) | |||
self.fd.append(fd) | self.fd.append(fd) | |||
except: | except: | |||
pass | pass | |||
if not self.fd: | if not self.fd: | |||
raise Exception, 'Cannot open file %s' % filename | raise Exception('Cannot open file %s' % filename) | |||
def readlines(self): | def readlines(self): | |||
"Return lines from any file descriptor" | "Return lines from any file descriptor" | |||
for fd in self.fd: | for fd in self.fd: | |||
fd.seek(0) | fd.seek(0) | |||
for line in fd.readlines(): | for line in fd.readlines(): | |||
yield line | yield line | |||
### Implemented linecache (for top-plugins) but slows down normal plugin s | ### Implemented linecache (for top-plugins) but slows down normal plugin s | |||
# for fd in self.fd: | # for fd in self.fd: | |||
# i = 1 | # i = 1 | |||
skipping to change at line 445 | skipping to change at line 421 | |||
def statwidth(self): | def statwidth(self): | |||
"Return complete stat width" | "Return complete stat width" | |||
if self.cols: | if self.cols: | |||
return len(self.vars) * self.colwidth() + len(self.vars) - 1 | return len(self.vars) * self.colwidth() + len(self.vars) - 1 | |||
else: | else: | |||
return len(self.nick) * self.colwidth() + len(self.nick) - 1 | return len(self.nick) * self.colwidth() + len(self.nick) - 1 | |||
def colwidth(self): | def colwidth(self): | |||
"Return column width" | "Return column width" | |||
if isinstance(self.name, types.StringType): | if isinstance(self.name, six.string_types): | |||
return self.width | return self.width | |||
else: | else: | |||
return len(self.nick) * self.width + len(self.nick) - 1 | return len(self.nick) * self.width + len(self.nick) - 1 | |||
def title(self): | def title(self): | |||
ret = theme['title'] | ret = theme['title'] | |||
if isinstance(self.name, types.StringType): | if isinstance(self.name, six.string_types): | |||
width = self.statwidth() | width = self.statwidth() | |||
return ret + self.name[0:width].center(width).replace(' ', '-') + th eme['default'] | return ret + self.name[0:width].center(width).replace(' ', '-') + th eme['default'] | |||
for i, name in enumerate(self.name): | for i, name in enumerate(self.name): | |||
width = self.colwidth() | width = self.colwidth() | |||
ret = ret + name[0:width].center(width).replace(' ', '-') | ret = ret + name[0:width].center(width).replace(' ', '-') | |||
if i + 1 != len(self.vars): | if i + 1 != len(self.vars): | |||
if op.color: | if op.color: | |||
ret = ret + theme['frame'] + char['dash'] + theme['title'] | ret = ret + theme['frame'] + char['dash'] + theme['title'] | |||
else: | else: | |||
ret = ret + char['space'] | ret = ret + char['space'] | |||
return ret | return ret | |||
def subtitle(self): | def subtitle(self): | |||
ret = '' | ret = '' | |||
if isinstance(self.name, types.StringType): | if isinstance(self.name, six.string_types): | |||
for i, nick in enumerate(self.nick): | for i, nick in enumerate(self.nick): | |||
ret = ret + theme['subtitle'] + nick[0:self.width].center(self.w idth) + theme['default'] | ret = ret + theme['subtitle'] + nick[0:self.width].center(self.w idth) + theme['default'] | |||
if i + 1 != len(self.nick): ret = ret + char['space'] | if i + 1 != len(self.nick): ret = ret + char['space'] | |||
return ret | return ret | |||
else: | else: | |||
for i, name in enumerate(self.name): | for i, name in enumerate(self.name): | |||
for j, nick in enumerate(self.nick): | for j, nick in enumerate(self.nick): | |||
ret = ret + theme['subtitle'] + nick[0:self.width].center(se lf.width) + theme['default'] | ret = ret + theme['subtitle'] + nick[0:self.width].center(se lf.width) + theme['default'] | |||
if j + 1 != len(self.nick): ret = ret + char['space'] | if j + 1 != len(self.nick): ret = ret + char['space'] | |||
if i + 1 != len(self.name): ret = ret + theme['frame'] + char['c olon'] | if i + 1 != len(self.name): ret = ret + theme['frame'] + char['c olon'] | |||
return ret | return ret | |||
def csvtitle(self): | def csvtitle(self): | |||
if isinstance(self.name, types.StringType): | if isinstance(self.name, six.string_types): | |||
return '"' + self.name + '"' + char['sep'] * (len(self.nick) - 1) | return '"' + self.name + '"' + char['sep'] * (len(self.nick) - 1) | |||
else: | else: | |||
ret = '' | ret = '' | |||
for i, name in enumerate(self.name): | for i, name in enumerate(self.name): | |||
ret = ret + '"' + name + '"' + char['sep'] * (len(self.nick) - 1 ) | ret = ret + '"' + name + '"' + char['sep'] * (len(self.nick) - 1 ) | |||
if i + 1 != len(self.name): ret = ret + char['sep'] | if i + 1 != len(self.name): ret = ret + char['sep'] | |||
return ret | return ret | |||
def csvsubtitle(self): | def csvsubtitle(self): | |||
ret = '' | ret = '' | |||
if isinstance(self.name, types.StringType): | if isinstance(self.name, six.string_types): | |||
for i, nick in enumerate(self.nick): | for i, nick in enumerate(self.nick): | |||
ret = ret + '"' + nick + '"' | ret = ret + '"' + nick + '"' | |||
if i + 1 != len(self.nick): ret = ret + char['sep'] | if i + 1 != len(self.nick): ret = ret + char['sep'] | |||
elif len(self.name) == 1: | elif len(self.name) == 1: | |||
for i, name in enumerate(self.name): | for i, name in enumerate(self.name): | |||
for j, nick in enumerate(self.nick): | for j, nick in enumerate(self.nick): | |||
ret = ret + '"' + nick + '"' | ret = ret + '"' + nick + '"' | |||
if j + 1 != len(self.nick): ret = ret + char['sep'] | if j + 1 != len(self.nick): ret = ret + char['sep'] | |||
if i + 1 != len(self.name): ret = ret + char['sep'] | if i + 1 != len(self.name): ret = ret + char['sep'] | |||
else: | else: | |||
skipping to change at line 515 | skipping to change at line 491 | |||
ret = ret + '"' + name + ':' + nick + '"' | ret = ret + '"' + name + ':' + nick + '"' | |||
if j + 1 != len(self.nick): ret = ret + char['sep'] | if j + 1 != len(self.nick): ret = ret + char['sep'] | |||
if i + 1 != len(self.name): ret = ret + char['sep'] | if i + 1 != len(self.name): ret = ret + char['sep'] | |||
return ret | return ret | |||
def check(self): | def check(self): | |||
"Check if stat is applicable" | "Check if stat is applicable" | |||
# if hasattr(self, 'fd') and not self.fd: | # if hasattr(self, 'fd') and not self.fd: | |||
# raise Exception, 'File %s does not exist' % self.fd | # raise Exception, 'File %s does not exist' % self.fd | |||
if not self.vars: | if not self.vars: | |||
raise Exception, 'No objects found, no stats available' | raise Exception('No objects found, no stats available') | |||
if not self.discover: | if not self.discover: | |||
raise Exception, 'No objects discovered, no stats available' | raise Exception('No objects discovered, no stats available') | |||
if self.colwidth(): | if self.colwidth(): | |||
return True | return True | |||
raise Exception, 'Unknown problem, please report' | raise Exception('Unknown problem, please report') | |||
def discover(self, *objlist): | def discover(self, *objlist): | |||
return True | return True | |||
def show(self): | def show(self): | |||
"Display stat results" | "Display stat results" | |||
line = '' | line = '' | |||
if hasattr(self, 'output'): | if hasattr(self, 'output'): | |||
return cprint(self.output, self.type, self.width, self.scale) | return cprint(self.output, self.type, self.width, self.scale) | |||
for i, name in enumerate(self.vars): | for i, name in enumerate(self.vars): | |||
if i < len(self.types): | if i < len(self.types): | |||
type = self.types[i] | ctype = self.types[i] | |||
else: | else: | |||
type = self.type | ctype = self.type | |||
if i < len(self.scales): | if i < len(self.scales): | |||
scale = self.scales[i] | scale = self.scales[i] | |||
else: | else: | |||
scale = self.scale | scale = self.scale | |||
if isinstance(self.val[name], types.TupleType) or isinstance(self.va | if isinstance(self.val[name], collections.Sequence) and not isinstan | |||
l[name], types.ListType): | ce(self.val[name], six.string_types): | |||
line = line + cprintlist(self.val[name], type, self.width, scale | line = line + cprintlist(self.val[name], ctype, self.width, scal | |||
) | e) | |||
sep = theme['frame'] + char['colon'] | sep = theme['frame'] + char['colon'] | |||
if i + 1 != len(self.vars): | if i + 1 != len(self.vars): | |||
line = line + sep | line = line + sep | |||
else: | else: | |||
### Make sure we don't show more values than we have nicknames | ### Make sure we don't show more values than we have nicknames | |||
if i >= len(self.nick): break | if i >= len(self.nick): break | |||
line = line + cprint(self.val[name], type, self.width, scale) | line = line + cprint(self.val[name], ctype, self.width, scale) | |||
sep = char['space'] | sep = char['space'] | |||
if i + 1 != len(self.nick): | if i + 1 != len(self.nick): | |||
line = line + sep | line = line + sep | |||
return line | return line | |||
def showend(self, totlist, vislist): | def showend(self, totlist, vislist): | |||
if vislist and self is not vislist[-1]: | if vislist and self is not vislist[-1]: | |||
return theme['frame'] + char['pipe'] | return theme['frame'] + char['pipe'] | |||
elif totlist != vislist: | elif totlist != vislist: | |||
return theme['frame'] + char['gt'] | return theme['frame'] + char['gt'] | |||
return '' | return '' | |||
def showcsv(self): | def showcsv(self): | |||
def printcsv(var): | def printcsv(var): | |||
if var != round(var): | if var != round(var): | |||
return '%.3f' % var | return '%.3f' % var | |||
return '%d' % long(round(var)) | return '%d' % int(round(var)) | |||
line = '' | line = '' | |||
for i, name in enumerate(self.vars): | for i, name in enumerate(self.vars): | |||
if isinstance(self.val[name], types.ListType) or isinstance(self.val [name], types.TupleType): | if isinstance(self.val[name], types.ListType) or isinstance(self.val [name], types.TupleType): | |||
for j, val in enumerate(self.val[name]): | for j, val in enumerate(self.val[name]): | |||
line = line + printcsv(val) | line = line + printcsv(val) | |||
if j + 1 != len(self.val[name]): | if j + 1 != len(self.val[name]): | |||
line = line + char['sep'] | line = line + char['sep'] | |||
elif isinstance(self.val[name], types.StringType): | elif isinstance(self.val[name], types.StringType): | |||
line = line + self.val[name] | line = line + self.val[name] | |||
skipping to change at line 600 | skipping to change at line 576 | |||
self.name = 'async' | self.name = 'async' | |||
self.nick = ('#aio',) | self.nick = ('#aio',) | |||
self.vars = ('aio',) | self.vars = ('aio',) | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 5; | self.width = 5; | |||
self.open('/proc/sys/fs/aio-nr') | self.open('/proc/sys/fs/aio-nr') | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 1: continue | if len(l) < 1: continue | |||
self.val['aio'] = long(l[0]) | self.val['aio'] = int(l[0]) | |||
class dstat_cpu(dstat): | class dstat_cpu(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.nick = ( 'usr', 'sys', 'idl', 'wai', 'stl' ) | self.nick = ( 'usr', 'sys', 'idl', 'wai', 'stl' ) | |||
self.type = 'p' | self.type = 'p' | |||
self.width = 3 | self.width = 3 | |||
self.scale = 34 | self.scale = 34 | |||
self.open('/proc/stat') | self.open('/proc/stat') | |||
self.cols = 5 | self.cols = 5 | |||
skipping to change at line 652 | skipping to change at line 628 | |||
ret.append('total cpu usage') | ret.append('total cpu usage') | |||
else: | else: | |||
ret.append('cpu' + name + ' usage') | ret.append('cpu' + name + ' usage') | |||
return ret | return ret | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 9: continue | if len(l) < 9: continue | |||
for name in self.vars: | for name in self.vars: | |||
if l[0] == 'cpu' + name or ( l[0] == 'cpu' and name == 'total' ) : | if l[0] == 'cpu' + name or ( l[0] == 'cpu' and name == 'total' ) : | |||
self.set2[name] = ( long(l[1]) + long(l[2]) + long(l[6]) + l ong(l[7]), long(l[3]), long(l[4]), long(l[5]), long(l[8]) ) | self.set2[name] = ( int(l[1]) + int(l[2]) + int(l[6]) + int( l[7]), int(l[3]), int(l[4]), int(l[5]), int(l[8]) ) | |||
for name in self.vars: | for name in self.vars: | |||
for i in range(self.cols): | for i in list(range(self.cols)): | |||
if sum(self.set2[name]) > sum(self.set1[name]): | if sum(self.set2[name]) > sum(self.set1[name]): | |||
self.val[name][i] = 100.0 * (self.set2[name][i] - self.set1[ name][i]) / (sum(self.set2[name]) - sum(self.set1[name])) | self.val[name][i] = 100.0 * (self.set2[name][i] - self.set1[ name][i]) / (sum(self.set2[name]) - sum(self.set1[name])) | |||
else: | else: | |||
self.val[name][i] = 0 | self.val[name][i] = 0 | |||
# print >>sys.stderr, "Error: tick problem detected, this sho uld never happen !" | # print("Error: tick problem detected, this should never happ en !", file=sys.stderr) | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_cpu_use(dstat_cpu): | class dstat_cpu_use(dstat_cpu): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'per cpu usage' | self.name = 'per cpu usage' | |||
self.type = 'p' | self.type = 'p' | |||
self.width = 3 | self.width = 3 | |||
self.scale = 34 | self.scale = 34 | |||
self.open('/proc/stat') | self.open('/proc/stat') | |||
self.cols = 7 | self.cols = 7 | |||
if not op.cpulist: | if not op.cpulist: | |||
self.vars = [ str(x) for x in range(cpunr) ] | self.vars = [ str(x) for x in list(range(cpunr)) ] | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 9: continue | if len(l) < 9: continue | |||
for name in self.vars: | for name in self.vars: | |||
if l[0] == 'cpu' + name or ( l[0] == 'cpu' and name == 'total' ) : | if l[0] == 'cpu' + name or ( l[0] == 'cpu' and name == 'total' ) : | |||
self.set2[name] = ( long(l[1]) + long(l[2]), long(l[3]), lon g(l[4]), long(l[5]), long(l[6]), long(l[7]), long(l[8]) ) | self.set2[name] = ( int(l[1]) + int(l[2]), int(l[3]), int(l[ 4]), int(l[5]), int(l[6]), int(l[7]), int(l[8]) ) | |||
for name in self.vars: | for name in self.vars: | |||
if sum(self.set2[name]) > sum(self.set1[name]): | if sum(self.set2[name]) > sum(self.set1[name]): | |||
self.val[name] = 100.0 - 100.0 * (self.set2[name][2] - self.set1 [name][2]) / (sum(self.set2[name]) - sum(self.set1[name])) | self.val[name] = 100.0 - 100.0 * (self.set2[name][2] - self.set1 [name][2]) / (sum(self.set2[name]) - sum(self.set1[name])) | |||
else: | else: | |||
self.val[name] = 0 | self.val[name] = 0 | |||
# print >>sys.stderr, "Error: tick problem detected, this sho uld never happen !" | # print("Error: tick problem detected, this should never happ en !", file=sys.stderr) | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_cpu_adv(dstat_cpu): | class dstat_cpu_adv(dstat_cpu): | |||
def __init__(self): | def __init__(self): | |||
self.nick = ( 'usr', 'sys', 'idl', 'wai', 'hiq', 'siq', 'stl' ) | self.nick = ( 'usr', 'sys', 'idl', 'wai', 'hiq', 'siq', 'stl' ) | |||
self.type = 'p' | self.type = 'p' | |||
self.width = 3 | self.width = 3 | |||
self.scale = 34 | self.scale = 34 | |||
self.open('/proc/stat') | self.open('/proc/stat') | |||
self.cols = 7 | self.cols = 7 | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 9: continue | if len(l) < 9: continue | |||
for name in self.vars: | for name in self.vars: | |||
if l[0] == 'cpu' + name or ( l[0] == 'cpu' and name == 'total' ) : | if l[0] == 'cpu' + name or ( l[0] == 'cpu' and name == 'total' ) : | |||
self.set2[name] = ( long(l[1]) + long(l[2]), long(l[3]), lon g(l[4]), long(l[5]), long(l[6]), long(l[7]), long(l[8]) ) | self.set2[name] = ( int(l[1]) + int(l[2]), int(l[3]), int(l[ 4]), int(l[5]), int(l[6]), int(l[7]), int(l[8]) ) | |||
for name in self.vars: | for name in self.vars: | |||
for i in range(self.cols): | for i in list(range(self.cols)): | |||
if sum(self.set2[name]) > sum(self.set1[name]): | if sum(self.set2[name]) > sum(self.set1[name]): | |||
self.val[name][i] = 100.0 * (self.set2[name][i] - self.set1[ name][i]) / (sum(self.set2[name]) - sum(self.set1[name])) | self.val[name][i] = 100.0 * (self.set2[name][i] - self.set1[ name][i]) / (sum(self.set2[name]) - sum(self.set1[name])) | |||
else: | else: | |||
self.val[name][i] = 0 | self.val[name][i] = 0 | |||
# print >>sys.stderr, "Error: tick problem detected, this sho uld never happen !" | # print("Error: tick problem detected, this should never happ en !", file=sys.stderr) | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_cpu24(dstat): | class dstat_cpu24(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.nick = ( 'usr', 'sys', 'idl') | self.nick = ( 'usr', 'sys', 'idl') | |||
self.type = 'p' | self.type = 'p' | |||
self.width = 3 | self.width = 3 | |||
self.scale = 34 | self.scale = 34 | |||
skipping to change at line 769 | skipping to change at line 745 | |||
if name == 'total': | if name == 'total': | |||
ret.append('cpu usage') | ret.append('cpu usage') | |||
else: | else: | |||
ret.append('cpu' + name) | ret.append('cpu' + name) | |||
return ret | return ret | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
for name in self.vars: | for name in self.vars: | |||
if l[0] == 'cpu' + name or ( l[0] == 'cpu' and name == 'total' ) : | if l[0] == 'cpu' + name or ( l[0] == 'cpu' and name == 'total' ) : | |||
self.set2[name] = ( long(l[1]) + long(l[2]), long(l[3]), lon g(l[4]) ) | self.set2[name] = ( int(l[1]) + int(l[2]), int(l[3]), int(l[ 4]) ) | |||
for name in self.vars: | for name in self.vars: | |||
for i in range(self.cols): | for i in list(range(self.cols)): | |||
self.val[name][i] = 100.0 * (self.set2[name][i] - self.set1[name ][i]) / (sum(self.set2[name]) - sum(self.set1[name])) | self.val[name][i] = 100.0 * (self.set2[name][i] - self.set1[name ][i]) / (sum(self.set2[name]) - sum(self.set1[name])) | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_disk(dstat): | class dstat_disk(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.nick = ('read', 'writ') | self.nick = ('read', 'writ') | |||
self.type = 'b' | self.type = 'b' | |||
self.diskfilter = re.compile('^([hsv]d[a-z]+\d+|cciss/c\d+d\d+p\d+|dm-\d +|md\d+|mmcblk\d+p\d0|VxVM\d+)$') | self.diskfilter = re.compile('^([hsv]d[a-z]+\d+|cciss/c\d+d\d+p\d+|dm-\d +|md\d+|mmcblk\d+p\d0|VxVM\d+)$') | |||
skipping to change at line 795 | skipping to change at line 771 | |||
def discover(self, *objlist): | def discover(self, *objlist): | |||
ret = [] | ret = [] | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 13: continue | if len(l) < 13: continue | |||
if l[3:] == ['0',] * 11: continue | if l[3:] == ['0',] * 11: continue | |||
name = l[2] | name = l[2] | |||
ret.append(name) | ret.append(name) | |||
for item in objlist: ret.append(item) | for item in objlist: ret.append(item) | |||
if not ret: | if not ret: | |||
raise Exception, "No suitable block devices found to monitor" | raise Exception("No suitable block devices found to monitor") | |||
return ret | return ret | |||
def basename(self, disk): | def basename(self, disk): | |||
"Strip /dev/ and convert symbolic link" | "Strip /dev/ and convert symbolic link" | |||
if disk[:5] == '/dev/': | if disk[:5] == '/dev/': | |||
# file or symlink | # file or symlink | |||
if os.path.exists(disk): | if os.path.exists(disk): | |||
# e.g. /dev/disk/by-uuid/15e40cc5-85de-40ea-b8fb-cb3a2eaf872 | # e.g. /dev/disk/by-uuid/15e40cc5-85de-40ea-b8fb-cb3a2eaf872 | |||
if os.path.islink(disk): | if os.path.islink(disk): | |||
target = os.readlink(disk) | target = os.readlink(disk) | |||
# convert relative pathname to absolute | # convert relative pathname to absolute | |||
if target[0] != '/': | if target[0] != '/': | |||
target = os.path.join(os.path.dirname(disk), target) | target = os.path.join(os.path.dirname(disk), target) | |||
target = os.path.normpath(target) | target = os.path.normpath(target) | |||
print 'dstat: symlink %s -> %s' % (disk, target) | print('dstat: symlink %s -> %s' % (disk, target)) | |||
disk = target | disk = target | |||
# trim leading /dev/ | # trim leading /dev/ | |||
return disk[5:] | return disk[5:] | |||
else: | else: | |||
print 'dstat: %s does not exist' % disk | print('dstat: %s does not exist' % disk) | |||
else: | else: | |||
return disk | return disk | |||
def vars(self): | def vars(self): | |||
ret = [] | ret = [] | |||
if op.disklist: | if op.disklist: | |||
varlist = map(self.basename, op.disklist) | varlist = list(map(self.basename, op.disklist)) | |||
elif not op.full: | elif not op.full: | |||
varlist = ('total',) | varlist = ('total',) | |||
else: | else: | |||
varlist = [] | varlist = [] | |||
for name in self.discover: | for name in self.discover: | |||
if self.diskfilter.match(name): continue | if self.diskfilter.match(name): continue | |||
if name not in blockdevices(): continue | if name not in blockdevices(): continue | |||
varlist.append(name) | varlist.append(name) | |||
# if len(varlist) > 2: varlist = varlist[0:2] | # if len(varlist) > 2: varlist = varlist[0:2] | |||
varlist.sort() | varlist.sort() | |||
for name in varlist: | for name in varlist: | |||
if name in self.discover + ['total'] + op.diskset.keys(): | if name in self.discover + ['total'] or name in op.diskset: | |||
ret.append(name) | ret.append(name) | |||
return ret | return ret | |||
def name(self): | def name(self): | |||
return ['dsk/'+sysfs_dev(name) for name in self.vars] | return ['dsk/'+sysfs_dev(name) for name in self.vars] | |||
def extract(self): | def extract(self): | |||
for name in self.vars: self.set2[name] = (0, 0) | for name in self.vars: self.set2[name] = (0, 0) | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 13: continue | if len(l) < 13: continue | |||
if l[5] == '0' and l[9] == '0': continue | if l[5] == '0' and l[9] == '0': continue | |||
name = l[2] | name = l[2] | |||
if l[3:] == ['0',] * 11: continue | if l[3:] == ['0',] * 11: continue | |||
if not self.diskfilter.match(name): | if not self.diskfilter.match(name): | |||
self.set2['total'] = ( self.set2['total'][0] + long(l[5]), self. set2['total'][1] + long(l[9]) ) | self.set2['total'] = ( self.set2['total'][0] + int(l[5]), self.s et2['total'][1] + int(l[9]) ) | |||
if name in self.vars and name != 'total': | if name in self.vars and name != 'total': | |||
self.set2[name] = ( self.set2[name][0] + long(l[5]), self.set2[n ame][1] + long(l[9]) ) | self.set2[name] = ( self.set2[name][0] + int(l[5]), self.set2[na me][1] + int(l[9]) ) | |||
for diskset in self.vars: | for diskset in self.vars: | |||
if diskset in op.diskset.keys(): | if diskset in op.diskset: | |||
for disk in op.diskset[diskset]: | for disk in op.diskset[diskset]: | |||
if fnmatch.fnmatch(name, disk): | if fnmatch.fnmatch(name, disk): | |||
self.set2[diskset] = ( self.set2[diskset][0] + long( l[5]), self.set2[diskset][1] + long(l[9]) ) | self.set2[diskset] = ( self.set2[diskset][0] + int(l [5]), self.set2[diskset][1] + int(l[9]) ) | |||
for name in self.set2.keys(): | for name in self.set2: | |||
self.val[name] = map(lambda x, y: (y - x) * 512.0 / elapsed, self.se | self.val[name] = list(map(lambda x, y: (y - x) * 512.0 / elapsed, se | |||
t1[name], self.set2[name]) | lf.set1[name], self.set2[name])) | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_disk24(dstat): | class dstat_disk24(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.nick = ('read', 'writ') | self.nick = ('read', 'writ') | |||
self.type = 'b' | self.type = 'b' | |||
self.diskfilter = re.compile('^([hsv]d[a-z]+\d+|cciss/c\d+d\d+p\d+|dm-\d +|md\d+|mmcblk\d+p\d0|VxVM\d+)$') | self.diskfilter = re.compile('^([hsv]d[a-z]+\d+|cciss/c\d+d\d+p\d+|dm-\d +|md\d+|mmcblk\d+p\d0|VxVM\d+)$') | |||
self.open('/proc/partitions') | self.open('/proc/partitions') | |||
if self.fd and not self.discover: | if self.fd and not self.discover: | |||
raise Exception, 'Kernel has no per-partition I/O accounting [CONFIG _BLK_STATS], use at least 2.4.20' | raise Exception('Kernel has no per-partition I/O accounting [CONFIG_ BLK_STATS], use at least 2.4.20') | |||
self.cols = 2 | self.cols = 2 | |||
def discover(self, *objlist): | def discover(self, *objlist): | |||
ret = [] | ret = [] | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 15 or l[0] == 'major' or int(l[1]) % 16 != 0: continue | if len(l) < 15 or l[0] == 'major' or int(l[1]) % 16 != 0: continue | |||
name = l[3] | name = l[3] | |||
ret.append(name) | ret.append(name) | |||
for item in objlist: ret.append(item) | for item in objlist: ret.append(item) | |||
if not ret: | if not ret: | |||
raise Exception, "No suitable block devices found to monitor" | raise Exception("No suitable block devices found to monitor") | |||
return ret | return ret | |||
def basename(self, disk): | def basename(self, disk): | |||
"Strip /dev/ and convert symbolic link" | "Strip /dev/ and convert symbolic link" | |||
if disk[:5] == '/dev/': | if disk[:5] == '/dev/': | |||
# file or symlink | # file or symlink | |||
if os.path.exists(disk): | if os.path.exists(disk): | |||
# e.g. /dev/disk/by-uuid/15e40cc5-85de-40ea-b8fb-cb3a2eaf872 | # e.g. /dev/disk/by-uuid/15e40cc5-85de-40ea-b8fb-cb3a2eaf872 | |||
if os.path.islink(disk): | if os.path.islink(disk): | |||
target = os.readlink(disk) | target = os.readlink(disk) | |||
# convert relative pathname to absolute | # convert relative pathname to absolute | |||
if target[0] != '/': | if target[0] != '/': | |||
target = os.path.join(os.path.dirname(disk), target) | target = os.path.join(os.path.dirname(disk), target) | |||
target = os.path.normpath(target) | target = os.path.normpath(target) | |||
print 'dstat: symlink %s -> %s' % (disk, target) | print('dstat: symlink %s -> %s' % (disk, target)) | |||
disk = target | disk = target | |||
# trim leading /dev/ | # trim leading /dev/ | |||
return disk[5:] | return disk[5:] | |||
else: | else: | |||
print 'dstat: %s does not exist' % disk | print('dstat: %s does not exist' % disk) | |||
else: | else: | |||
return disk | return disk | |||
def vars(self): | def vars(self): | |||
ret = [] | ret = [] | |||
if op.disklist: | if op.disklist: | |||
varlist = map(self.basename, op.disklist) | varlist = list(map(self.basename, op.disklist)) | |||
elif not op.full: | elif not op.full: | |||
varlist = ('total',) | varlist = ('total',) | |||
else: | else: | |||
varlist = [] | varlist = [] | |||
for name in self.discover: | for name in self.discover: | |||
if self.diskfilter.match(name): continue | if self.diskfilter.match(name): continue | |||
varlist.append(name) | varlist.append(name) | |||
# if len(varlist) > 2: varlist = varlist[0:2] | # if len(varlist) > 2: varlist = varlist[0:2] | |||
varlist.sort() | varlist.sort() | |||
for name in varlist: | for name in varlist: | |||
if name in self.discover + ['total'] + op.diskset.keys(): | if name in self.discover + ['total'] or name in op.diskset: | |||
ret.append(name) | ret.append(name) | |||
return ret | return ret | |||
def name(self): | def name(self): | |||
return ['dsk/'+sysfs_dev(name) for name in self.vars] | return ['dsk/'+sysfs_dev(name) for name in self.vars] | |||
def extract(self): | def extract(self): | |||
for name in self.vars: self.set2[name] = (0, 0) | for name in self.vars: self.set2[name] = (0, 0) | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 15 or l[0] == 'major' or int(l[1]) % 16 != 0: continue | if len(l) < 15 or l[0] == 'major' or int(l[1]) % 16 != 0: continue | |||
name = l[3] | name = l[3] | |||
if not self.diskfilter.match(name): | if not self.diskfilter.match(name): | |||
self.set2['total'] = ( self.set2['total'][0] + long(l[6]), self. set2['total'][1] + long(l[10]) ) | self.set2['total'] = ( self.set2['total'][0] + int(l[6]), self.s et2['total'][1] + int(l[10]) ) | |||
if name in self.vars: | if name in self.vars: | |||
self.set2[name] = ( self.set2[name][0] + long(l[6]), self.set2[n ame][1] + long(l[10]) ) | self.set2[name] = ( self.set2[name][0] + int(l[6]), self.set2[na me][1] + int(l[10]) ) | |||
for diskset in self.vars: | for diskset in self.vars: | |||
if diskset in op.diskset.keys(): | if diskset in op.diskset: | |||
for disk in op.diskset[diskset]: | for disk in op.diskset[diskset]: | |||
if fnmatch.fnmatch(name, disk): | if fnmatch.fnmatch(name, disk): | |||
self.set2[diskset] = ( self.set2[diskset][0] + long( l[6]), self.set2[diskset][1] + long(l[10]) ) | self.set2[diskset] = ( self.set2[diskset][0] + int(l [6]), self.set2[diskset][1] + int(l[10]) ) | |||
for name in self.set2.keys(): | for name in self.set2: | |||
self.val[name] = map(lambda x, y: (y - x) * 512.0 / elapsed, self.se | self.val[name] = list(map(lambda x, y: (y - x) * 512.0 / elapsed, se | |||
t1[name], self.set2[name]) | lf.set1[name], self.set2[name])) | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
### FIXME: Needs rework, does anyone care ? | ### FIXME: Needs rework, does anyone care ? | |||
class dstat_disk24_old(dstat): | class dstat_disk24_old(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.nick = ('read', 'writ') | self.nick = ('read', 'writ') | |||
self.type = 'b' | self.type = 'b' | |||
self.diskfilter = re.compile('^([hsv]d[a-z]+\d+|cciss/c\d+d\d+p\d+|dm-\d +|md\d+|mmcblk\d+p\d0|VxVM\d+)$') | self.diskfilter = re.compile('^([hsv]d[a-z]+\d+|cciss/c\d+d\d+p\d+|dm-\d +|md\d+|mmcblk\d+p\d0|VxVM\d+)$') | |||
skipping to change at line 974 | skipping to change at line 950 | |||
for pair in line.split()[1:]: | for pair in line.split()[1:]: | |||
m = self.regexp.match(pair) | m = self.regexp.match(pair) | |||
if not m: continue | if not m: continue | |||
l = m.groups() | l = m.groups() | |||
if len(l) < 4: continue | if len(l) < 4: continue | |||
name = dev(int(l[0]), int(l[1])) | name = dev(int(l[0]), int(l[1])) | |||
ret.append(name) | ret.append(name) | |||
break | break | |||
for item in objlist: ret.append(item) | for item in objlist: ret.append(item) | |||
if not ret: | if not ret: | |||
raise Exception, "No suitable block devices found to monitor" | raise Exception("No suitable block devices found to monitor") | |||
return ret | return ret | |||
def vars(self): | def vars(self): | |||
ret = [] | ret = [] | |||
if op.disklist: | if op.disklist: | |||
varlist = op.disklist | varlist = op.disklist | |||
elif not op.full: | elif not op.full: | |||
varlist = ('total',) | varlist = ('total',) | |||
else: | else: | |||
varlist = [] | varlist = [] | |||
for name in self.discover: | for name in self.discover: | |||
if self.diskfilter.match(name): continue | if self.diskfilter.match(name): continue | |||
varlist.append(name) | varlist.append(name) | |||
# if len(varlist) > 2: varlist = varlist[0:2] | # if len(varlist) > 2: varlist = varlist[0:2] | |||
varlist.sort() | varlist.sort() | |||
for name in varlist: | for name in varlist: | |||
if name in self.discover + ['total'] + op.diskset.keys(): | if name in self.discover + ['total'] or name in op.diskset: | |||
ret.append(name) | ret.append(name) | |||
return ret | return ret | |||
def name(self): | def name(self): | |||
return ['dsk/'+name for name in self.vars] | return ['dsk/'+name for name in self.vars] | |||
def extract(self): | def extract(self): | |||
for name in self.vars: self.set2[name] = (0, 0) | for name in self.vars: self.set2[name] = (0, 0) | |||
for line in self.splitlines(':'): | for line in self.splitlines(':'): | |||
if len(l) < 3: continue | if len(l) < 3: continue | |||
name = l[0] | name = l[0] | |||
if name != 'disk_io': continue | if name != 'disk_io': continue | |||
for pair in line.split()[1:]: | for pair in line.split()[1:]: | |||
m = self.regexp.match(pair) | m = self.regexp.match(pair) | |||
if not m: continue | if not m: continue | |||
l = m.groups() | l = m.groups() | |||
if len(l) < 4: continue | if len(l) < 4: continue | |||
name = dev(int(l[0]), int(l[1])) | name = dev(int(l[0]), int(l[1])) | |||
if not self.diskfilter.match(name): | if not self.diskfilter.match(name): | |||
self.set2['total'] = ( self.set2['total'][0] + long(l[2]), s elf.set2['total'][1] + long(l[3]) ) | self.set2['total'] = ( self.set2['total'][0] + int(l[2]), se lf.set2['total'][1] + int(l[3]) ) | |||
if name in self.vars and name != 'total': | if name in self.vars and name != 'total': | |||
self.set2[name] = ( self.set2[name][0] + long(l[2]), self.se t2[name][1] + long(l[3]) ) | self.set2[name] = ( self.set2[name][0] + int(l[2]), self.set 2[name][1] + int(l[3]) ) | |||
for diskset in self.vars: | for diskset in self.vars: | |||
if diskset in op.diskset.keys(): | if diskset in op.diskset: | |||
for disk in op.diskset[diskset]: | for disk in op.diskset[diskset]: | |||
if fnmatch.fnmatch(name, disk): | if fnmatch.fnmatch(name, disk): | |||
self.set2[diskset] = ( self.set2[diskset][0] + l ong(l[2]), self.set2[diskset][1] + long(l[3]) ) | self.set2[diskset] = ( self.set2[diskset][0] + i nt(l[2]), self.set2[diskset][1] + int(l[3]) ) | |||
break | break | |||
for name in self.set2.keys(): | for name in self.set2: | |||
self.val[name] = map(lambda x, y: (y - x) * 512.0 / elapsed, self.se | self.val[name] = list(map(lambda x, y: (y - x) * 512.0 / elapsed, se | |||
t1[name], self.set2[name]) | lf.set1[name], self.set2[name])) | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_epoch(dstat): | class dstat_epoch(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'epoch' | self.name = 'epoch' | |||
self.vars = ('epoch',) | self.vars = ('epoch',) | |||
self.width = 10 | self.width = 10 | |||
if op.debug: | if op.debug: | |||
skipping to change at line 1053 | skipping to change at line 1029 | |||
self.name = 'filesystem' | self.name = 'filesystem' | |||
self.vars = ('files', 'inodes') | self.vars = ('files', 'inodes') | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 6 | self.width = 6 | |||
self.scale = 1000 | self.scale = 1000 | |||
def extract(self): | def extract(self): | |||
for line in dopen('/proc/sys/fs/file-nr'): | for line in dopen('/proc/sys/fs/file-nr'): | |||
l = line.split() | l = line.split() | |||
if len(l) < 1: continue | if len(l) < 1: continue | |||
self.val['files'] = long(l[0]) | self.val['files'] = int(l[0]) | |||
for line in dopen('/proc/sys/fs/inode-nr'): | for line in dopen('/proc/sys/fs/inode-nr'): | |||
l = line.split() | l = line.split() | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
self.val['inodes'] = long(l[0]) - long(l[1]) | self.val['inodes'] = int(l[0]) - int(l[1]) | |||
class dstat_int(dstat): | class dstat_int(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'interrupts' | self.name = 'interrupts' | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 5 | self.width = 5 | |||
self.scale = 1000 | self.scale = 1000 | |||
self.open('/proc/stat') | self.open('/proc/stat') | |||
self.intmap = self.intmap() | self.intmap = self.intmap() | |||
skipping to change at line 1085 | skipping to change at line 1061 | |||
ret[l1] = l1 | ret[l1] = l1 | |||
for name in l2: | for name in l2: | |||
ret[name.strip().lower()] = l1 | ret[name.strip().lower()] = l1 | |||
return ret | return ret | |||
def discover(self, *objlist): | def discover(self, *objlist): | |||
ret = [] | ret = [] | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if l[0] != 'intr': continue | if l[0] != 'intr': continue | |||
for name, i in enumerate(l[2:]): | for name, i in enumerate(l[2:]): | |||
if long(i) > 10: ret.append(str(name)) | if int(i) > 10: ret.append(str(name)) | |||
return ret | return ret | |||
# def check(self): | # def check(self): | |||
# if self.fd[0] and self.vars: | # if self.fd[0] and self.vars: | |||
# self.fd[0].seek(0) | # self.fd[0].seek(0) | |||
# for l in self.fd[0].splitlines(): | # for l in self.fd[0].splitlines(): | |||
# if l[0] != 'intr': continue | # if l[0] != 'intr': continue | |||
# return True | # return True | |||
# return False | # return False | |||
skipping to change at line 1109 | skipping to change at line 1085 | |||
varlist = op.intlist | varlist = op.intlist | |||
else: | else: | |||
varlist = self.discover | varlist = self.discover | |||
for name in varlist: | for name in varlist: | |||
if name in ('0', '1', '2', '8', 'NMI', 'LOC', 'MIS', 'CPU0'): | if name in ('0', '1', '2', '8', 'NMI', 'LOC', 'MIS', 'CPU0'): | |||
varlist.remove(name) | varlist.remove(name) | |||
if not op.full and len(varlist) > 3: varlist = varlist[-3:] | if not op.full and len(varlist) > 3: varlist = varlist[-3:] | |||
for name in varlist: | for name in varlist: | |||
if name in self.discover + ['total',]: | if name in self.discover + ['total',]: | |||
ret.append(name) | ret.append(name) | |||
elif name.lower() in self.intmap.keys(): | elif name.lower() in self.intmap: | |||
ret.append(self.intmap[name.lower()]) | ret.append(self.intmap[name.lower()]) | |||
return ret | return ret | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if not l or l[0] != 'intr': continue | if not l or l[0] != 'intr': continue | |||
for name in self.vars: | for name in self.vars: | |||
if name != 'total': | if name != 'total': | |||
self.set2[name] = long(l[int(name) + 2]) | self.set2[name] = int(l[int(name) + 2]) | |||
self.set2['total'] = long(l[1]) | self.set2['total'] = int(l[1]) | |||
for name in self.vars: | for name in self.vars: | |||
self.val[name] = (self.set2[name] - self.set1[name]) * 1.0 / elapsed | self.val[name] = (self.set2[name] - self.set1[name]) * 1.0 / elapsed | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_int24(dstat): | class dstat_int24(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'interrupts' | self.name = 'interrupts' | |||
skipping to change at line 1151 | skipping to change at line 1127 | |||
ret[l1] = l1 | ret[l1] = l1 | |||
for name in l2: | for name in l2: | |||
ret[name.strip().lower()] = l1 | ret[name.strip().lower()] = l1 | |||
return ret | return ret | |||
def discover(self, *objlist): | def discover(self, *objlist): | |||
ret = [] | ret = [] | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < cpunr+1: continue | if len(l) < cpunr+1: continue | |||
name = l[0].split(':')[0] | name = l[0].split(':')[0] | |||
if long(l[1]) > 10: | if int(l[1]) > 10: | |||
ret.append(name) | ret.append(name) | |||
return ret | return ret | |||
# def check(self): | # def check(self): | |||
# if self.fd and self.discover: | # if self.fd and self.discover: | |||
# self.fd[0].seek(0) | # self.fd[0].seek(0) | |||
# for l in self.fd[0].splitlines(): | # for l in self.fd[0].splitlines(): | |||
# if l[0] != 'intr' or len(l) > 2: continue | # if l[0] != 'intr' or len(l) > 2: continue | |||
# return True | # return True | |||
# return False | # return False | |||
skipping to change at line 1176 | skipping to change at line 1152 | |||
varlist = op.intlist | varlist = op.intlist | |||
else: | else: | |||
varlist = self.discover | varlist = self.discover | |||
for name in varlist: | for name in varlist: | |||
if name in ('0', '1', '2', '8', 'CPU0', 'ERR', 'LOC', 'MIS', 'NM I'): | if name in ('0', '1', '2', '8', 'CPU0', 'ERR', 'LOC', 'MIS', 'NM I'): | |||
varlist.remove(name) | varlist.remove(name) | |||
if not op.full and len(varlist) > 3: varlist = varlist[-3:] | if not op.full and len(varlist) > 3: varlist = varlist[-3:] | |||
for name in varlist: | for name in varlist: | |||
if name in self.discover: | if name in self.discover: | |||
ret.append(name) | ret.append(name) | |||
elif name.lower() in self.intmap.keys(): | elif name.lower() in self.intmap: | |||
ret.append(self.intmap[name.lower()]) | ret.append(self.intmap[name.lower()]) | |||
return ret | return ret | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < cpunr+1: continue | if len(l) < cpunr+1: continue | |||
name = l[0].split(':')[0] | name = l[0].split(':')[0] | |||
if name in self.vars: | if name in self.vars: | |||
self.set2[name] = 0 | self.set2[name] = 0 | |||
for i in l[1:1+cpunr]: | for i in l[1:1+cpunr]: | |||
self.set2[name] = self.set2[name] + long(i) | self.set2[name] = self.set2[name] + int(i) | |||
# elif len(l) > 2 + cpunr: | # elif len(l) > 2 + cpunr: | |||
# for hw in self.vars: | # for hw in self.vars: | |||
# for mod in l[2+cpunr:]: | # for mod in l[2+cpunr:]: | |||
# self.set2[mod] = long(l[1]) | # self.set2[mod] = int(l[1]) | |||
for name in self.set2.keys(): | for name in self.set2: | |||
self.val[name] = (self.set2[name] - self.set1[name]) * 1.0 / elapsed | self.val[name] = (self.set2[name] - self.set1[name]) * 1.0 / elapsed | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_io(dstat): | class dstat_io(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.nick = ('read', 'writ') | self.nick = ('read', 'writ') | |||
self.type = 'f' | self.type = 'f' | |||
self.width = 5 | self.width = 5 | |||
skipping to change at line 1218 | skipping to change at line 1194 | |||
def discover(self, *objlist): | def discover(self, *objlist): | |||
ret = [] | ret = [] | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 13: continue | if len(l) < 13: continue | |||
if l[3:] == ['0',] * 11: continue | if l[3:] == ['0',] * 11: continue | |||
name = l[2] | name = l[2] | |||
ret.append(name) | ret.append(name) | |||
for item in objlist: ret.append(item) | for item in objlist: ret.append(item) | |||
if not ret: | if not ret: | |||
raise Exception, "No suitable block devices found to monitor" | raise Exception("No suitable block devices found to monitor") | |||
return ret | return ret | |||
def vars(self): | def vars(self): | |||
ret = [] | ret = [] | |||
if op.disklist: | if op.disklist: | |||
varlist = op.disklist | varlist = op.disklist | |||
elif not op.full: | elif not op.full: | |||
varlist = ('total',) | varlist = ('total',) | |||
else: | else: | |||
varlist = [] | varlist = [] | |||
for name in self.discover: | for name in self.discover: | |||
if self.diskfilter.match(name): continue | if self.diskfilter.match(name): continue | |||
if name not in blockdevices(): continue | if name not in blockdevices(): continue | |||
varlist.append(name) | varlist.append(name) | |||
# if len(varlist) > 2: varlist = varlist[0:2] | # if len(varlist) > 2: varlist = varlist[0:2] | |||
varlist.sort() | varlist.sort() | |||
for name in varlist: | for name in varlist: | |||
if name in self.discover + ['total'] + op.diskset.keys(): | if name in self.discover + ['total'] or name in op.diskset: | |||
ret.append(name) | ret.append(name) | |||
return ret | return ret | |||
def name(self): | def name(self): | |||
return ['io/'+name for name in self.vars] | return ['io/'+name for name in self.vars] | |||
def extract(self): | def extract(self): | |||
for name in self.vars: self.set2[name] = (0, 0) | for name in self.vars: self.set2[name] = (0, 0) | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 13: continue | if len(l) < 13: continue | |||
if l[3] == '0' and l[7] == '0': continue | if l[3] == '0' and l[7] == '0': continue | |||
name = l[2] | name = l[2] | |||
if l[3:] == ['0',] * 11: continue | if l[3:] == ['0',] * 11: continue | |||
if not self.diskfilter.match(name): | if not self.diskfilter.match(name): | |||
self.set2['total'] = ( self.set2['total'][0] + long(l[3]), self. set2['total'][1] + long(l[7]) ) | self.set2['total'] = ( self.set2['total'][0] + int(l[3]), self.s et2['total'][1] + int(l[7]) ) | |||
if name in self.vars and name != 'total': | if name in self.vars and name != 'total': | |||
self.set2[name] = ( self.set2[name][0] + long(l[3]), self.set2[n ame][1] + long(l[7]) ) | self.set2[name] = ( self.set2[name][0] + int(l[3]), self.set2[na me][1] + int(l[7]) ) | |||
for diskset in self.vars: | for diskset in self.vars: | |||
if diskset in op.diskset.keys(): | if diskset in op.diskset: | |||
for disk in op.diskset[diskset]: | for disk in op.diskset[diskset]: | |||
if fnmatch.fnmatch(name, disk): | if fnmatch.fnmatch(name, disk): | |||
self.set2[diskset] = ( self.set2[diskset][0] + long( l[3]), self.set2[diskset][1] + long(l[7]) ) | self.set2[diskset] = ( self.set2[diskset][0] + int(l [3]), self.set2[diskset][1] + int(l[7]) ) | |||
for name in self.set2.keys(): | for name in self.set2: | |||
self.val[name] = map(lambda x, y: (y - x) * 1.0 / elapsed, self.set1 | self.val[name] = list(map(lambda x, y: (y - x) * 1.0 / elapsed, self | |||
[name], self.set2[name]) | .set1[name], self.set2[name])) | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_ipc(dstat): | class dstat_ipc(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'sysv ipc' | self.name = 'sysv ipc' | |||
self.vars = ('msg', 'sem', 'shm') | self.vars = ('msg', 'sem', 'shm') | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 3 | self.width = 3 | |||
skipping to change at line 1328 | skipping to change at line 1304 | |||
self.vars = ('MemUsed', 'MemFree', 'Buffers', 'Cached') | self.vars = ('MemUsed', 'MemFree', 'Buffers', 'Cached') | |||
self.open('/proc/meminfo') | self.open('/proc/meminfo') | |||
def extract(self): | def extract(self): | |||
adv_extract_vars = ('MemTotal', 'Shmem', 'SReclaimable') | adv_extract_vars = ('MemTotal', 'Shmem', 'SReclaimable') | |||
adv_val={} | adv_val={} | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
name = l[0].split(':')[0] | name = l[0].split(':')[0] | |||
if name in self.vars: | if name in self.vars: | |||
self.val[name] = long(l[1]) * 1024.0 | self.val[name] = int(l[1]) * 1024.0 | |||
if name in adv_extract_vars: | if name in adv_extract_vars: | |||
adv_val[name] = long(l[1]) * 1024.0 | adv_val[name] = int(l[1]) * 1024.0 | |||
self.val['MemUsed'] = adv_val['MemTotal'] - self.val['MemFree'] - self.v al['Buffers'] - self.val['Cached'] - adv_val['SReclaimable'] + adv_val['Shmem'] | self.val['MemUsed'] = adv_val['MemTotal'] - self.val['MemFree'] - self.v al['Buffers'] - self.val['Cached'] - adv_val['SReclaimable'] + adv_val['Shmem'] | |||
class dstat_mem_adv(dstat_mem): | class dstat_mem_adv(dstat_mem): | |||
""" | """ | |||
Advanced memory usage | Advanced memory usage | |||
Displays memory usage similarly to the internal plugin but with added total, shared and reclaimable counters. | Displays memory usage similarly to the internal plugin but with added total, shared and reclaimable counters. | |||
Additionally, shared memory is added and reclaimable memory is subtracted fr om the used memory counter. | Additionally, shared memory is added and reclaimable memory is subtracted fr om the used memory counter. | |||
""" | """ | |||
skipping to change at line 1381 | skipping to change at line 1357 | |||
elif not op.full: | elif not op.full: | |||
varlist = ('total',) | varlist = ('total',) | |||
else: | else: | |||
varlist = self.discover | varlist = self.discover | |||
# if len(varlist) > 2: varlist = varlist[0:2] | # if len(varlist) > 2: varlist = varlist[0:2] | |||
varlist.sort() | varlist.sort() | |||
for name in varlist: | for name in varlist: | |||
if name in self.discover + ['total', 'lo']: | if name in self.discover + ['total', 'lo']: | |||
ret.append(name) | ret.append(name) | |||
if not ret: | if not ret: | |||
raise Exception, "No suitable network interfaces found to monitor" | raise Exception("No suitable network interfaces found to monitor") | |||
return ret | return ret | |||
def name(self): | def name(self): | |||
return ['net/'+name for name in self.vars] | return ['net/'+name for name in self.vars] | |||
def extract(self): | def extract(self): | |||
self.set2['total'] = [0, 0] | self.set2['total'] = [0, 0] | |||
for l in self.splitlines(replace=':'): | for l in self.splitlines(replace=':'): | |||
if len(l) < 17: continue | if len(l) < 17: continue | |||
if l[2] == '0' and l[10] == '0': continue | if l[2] == '0' and l[10] == '0': continue | |||
name = l[0] | name = l[0] | |||
if name in self.vars : | if name in self.vars : | |||
self.set2[name] = ( long(l[1]), long(l[9]) ) | self.set2[name] = ( int(l[1]), int(l[9]) ) | |||
if not self.totalfilter.match(name): | if not self.totalfilter.match(name): | |||
self.set2['total'] = ( self.set2['total'][0] + long(l[1]), self. set2['total'][1] + long(l[9])) | self.set2['total'] = ( self.set2['total'][0] + int(l[1]), self.s et2['total'][1] + int(l[9])) | |||
if update: | if update: | |||
for name in self.set2.keys(): | for name in self.set2: | |||
self.val[name] = map(lambda x, y: (y - x) * 1.0 / elapsed, self. | self.val[name] = list(map(lambda x, y: (y - x) * 1.0 / elapsed, | |||
set1[name], self.set2[name]) | self.set1[name], self.set2[name])) | |||
if self.val[name][0] < 0: self.val[name][0] += maxint + 1 | if self.val[name][0] < 0: self.val[name][0] += maxint + 1 | |||
if self.val[name][1] < 0: self.val[name][1] += maxint + 1 | if self.val[name][1] < 0: self.val[name][1] += maxint + 1 | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_page(dstat): | class dstat_page(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'paging' | self.name = 'paging' | |||
self.nick = ('in', 'out') | self.nick = ('in', 'out') | |||
self.vars = ('pswpin', 'pswpout') | self.vars = ('pswpin', 'pswpout') | |||
self.type = 'd' | self.type = 'd' | |||
self.open('/proc/vmstat') | self.open('/proc/vmstat') | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
name = l[0] | name = l[0] | |||
if name in self.vars: | if name in self.vars: | |||
self.set2[name] = long(l[1]) | self.set2[name] = int(l[1]) | |||
for name in self.vars: | for name in self.vars: | |||
self.val[name] = (self.set2[name] - self.set1[name]) * pagesize * 1. 0 / elapsed | self.val[name] = (self.set2[name] - self.set1[name]) * pagesize * 1. 0 / elapsed | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_page24(dstat): | class dstat_page24(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'paging' | self.name = 'paging' | |||
self.nick = ('in', 'out') | self.nick = ('in', 'out') | |||
self.vars = ('pswpin', 'pswpout') | self.vars = ('pswpin', 'pswpout') | |||
self.type = 'd' | self.type = 'd' | |||
self.open('/proc/stat') | self.open('/proc/stat') | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 3: continue | if len(l) < 3: continue | |||
name = l[0] | name = l[0] | |||
if name != 'swap': continue | if name != 'swap': continue | |||
self.set2['pswpin'] = long(l[1]) | self.set2['pswpin'] = int(l[1]) | |||
self.set2['pswpout'] = long(l[2]) | self.set2['pswpout'] = int(l[2]) | |||
break | break | |||
for name in self.vars: | for name in self.vars: | |||
self.val[name] = (self.set2[name] - self.set1[name]) * pagesize * 1. 0 / elapsed | self.val[name] = (self.set2[name] - self.set1[name]) * pagesize * 1. 0 / elapsed | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_proc(dstat): | class dstat_proc(dstat): | |||
def __init__(self): | def __init__(self): | |||
skipping to change at line 1467 | skipping to change at line 1443 | |||
self.width = 3 | self.width = 3 | |||
self.scale = 10 | self.scale = 10 | |||
self.open('/proc/stat') | self.open('/proc/stat') | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
name = l[0] | name = l[0] | |||
if name == 'processes': | if name == 'processes': | |||
self.val['processes'] = 0 | self.val['processes'] = 0 | |||
self.set2[name] = long(l[1]) | self.set2[name] = int(l[1]) | |||
elif name == 'procs_running': | elif name == 'procs_running': | |||
self.set2[name] = self.set2[name] + long(l[1]) - 1 | self.set2[name] = self.set2[name] + int(l[1]) - 1 | |||
elif name == 'procs_blocked': | elif name == 'procs_blocked': | |||
self.set2[name] = self.set2[name] + long(l[1]) | self.set2[name] = self.set2[name] + int(l[1]) | |||
self.val['processes'] = (self.set2['processes'] - self.set1['processes'] ) * 1.0 / elapsed | self.val['processes'] = (self.set2['processes'] - self.set1['processes'] ) * 1.0 / elapsed | |||
for name in ('procs_running', 'procs_blocked'): | for name in ('procs_running', 'procs_blocked'): | |||
self.val[name] = self.set2[name] * 1.0 | self.val[name] = self.set2[name] * 1.0 | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
for name in ('procs_running', 'procs_blocked'): | for name in ('procs_running', 'procs_blocked'): | |||
self.set2[name] = 0 | self.set2[name] = 0 | |||
class dstat_raw(dstat): | class dstat_raw(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'raw' | self.name = 'raw' | |||
self.nick = ('raw',) | self.nick = ('raw',) | |||
self.vars = ('sockets',) | self.vars = ('sockets',) | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 3 | self.width = 4 | |||
self.scale = 100 | self.scale = 1000 | |||
self.open('/proc/net/raw') | self.open('/proc/net/raw') | |||
def extract(self): | def extract(self): | |||
lines = -1 | lines = -1 | |||
for line in self.readlines(): | for line in self.readlines(): | |||
lines += 1 | lines += 1 | |||
self.val['sockets'] = lines | self.val['sockets'] = lines | |||
### Cannot use len() on generator | ### Cannot use len() on generator | |||
# self.val['sockets'] = len(self.readlines()) - 1 | # self.val['sockets'] = len(self.readlines()) - 1 | |||
class dstat_socket(dstat): | class dstat_socket(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'sockets' | self.name = 'sockets' | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 3 | self.width = 4 | |||
self.scale = 100 | self.scale = 1000 | |||
self.open('/proc/net/sockstat') | self.open('/proc/net/sockstat') | |||
self.nick = ('tot', 'tcp', 'udp', 'raw', 'frg') | self.nick = ('tot', 'tcp', 'udp', 'raw', 'frg') | |||
self.vars = ('sockets:', 'TCP:', 'UDP:', 'RAW:', 'FRAG:') | self.vars = ('sockets:', 'TCP:', 'UDP:', 'RAW:', 'FRAG:') | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 3: continue | if len(l) < 3: continue | |||
self.val[l[0]] = long(l[2]) | self.val[l[0]] = int(l[2]) | |||
self.val['other'] = self.val['sockets:'] - self.val['TCP:'] - self.val[' UDP:'] - self.val['RAW:'] - self.val['FRAG:'] | self.val['other'] = self.val['sockets:'] - self.val['TCP:'] - self.val[' UDP:'] - self.val['RAW:'] - self.val['FRAG:'] | |||
class dstat_swap(dstat): | class dstat_swap(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'swap' | self.name = 'swap' | |||
self.nick = ('used', 'free') | self.nick = ('used', 'free') | |||
self.type = 'd' | self.type = 'd' | |||
self.open('/proc/swaps') | self.open('/proc/swaps') | |||
skipping to change at line 1554 | skipping to change at line 1530 | |||
elif not op.full: | elif not op.full: | |||
varlist = ('total',) | varlist = ('total',) | |||
else: | else: | |||
varlist = self.discover | varlist = self.discover | |||
# if len(varlist) > 2: varlist = varlist[0:2] | # if len(varlist) > 2: varlist = varlist[0:2] | |||
varlist.sort() | varlist.sort() | |||
for name in varlist: | for name in varlist: | |||
if name in self.discover + ['total']: | if name in self.discover + ['total']: | |||
ret.append(name) | ret.append(name) | |||
if not ret: | if not ret: | |||
raise Exception, "No suitable swap devices found to monitor" | raise Exception("No suitable swap devices found to monitor") | |||
return ret | return ret | |||
def name(self): | def name(self): | |||
return ['swp/'+improve(name) for name in self.vars] | return ['swp/'+improve(name) for name in self.vars] | |||
def extract(self): | def extract(self): | |||
self.val['total'] = [0, 0] | self.val['total'] = [0, 0] | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 5 or l[0] == 'Filename': continue | if len(l) < 5 or l[0] == 'Filename': continue | |||
name = l[0] | name = l[0] | |||
self.val[name] = ( long(l[3]) * 1024.0, (long(l[2]) - long(l[3])) * 1024.0 ) | self.val[name] = ( int(l[3]) * 1024.0, (int(l[2]) - int(l[3])) * 102 4.0 ) | |||
self.val['total'] = ( self.val['total'][0] + self.val[name][0], self .val['total'][1] + self.val[name][1]) | self.val['total'] = ( self.val['total'][0] + self.val[name][0], self .val['total'][1] + self.val[name][1]) | |||
class dstat_swap_old(dstat): | class dstat_swap_old(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'swap' | self.name = 'swap' | |||
self.nick = ('used', 'free') | self.nick = ('used', 'free') | |||
self.vars = ('SwapUsed', 'SwapFree') | self.vars = ('SwapUsed', 'SwapFree') | |||
self.type = 'd' | self.type = 'd' | |||
self.open('/proc/meminfo') | self.open('/proc/meminfo') | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
name = l[0].split(':')[0] | name = l[0].split(':')[0] | |||
if name in self.vars + ('SwapTotal',): | if name in self.vars + ('SwapTotal',): | |||
self.val[name] = long(l[1]) * 1024.0 | self.val[name] = int(l[1]) * 1024.0 | |||
self.val['SwapUsed'] = self.val['SwapTotal'] - self.val['SwapFree'] | self.val['SwapUsed'] = self.val['SwapTotal'] - self.val['SwapFree'] | |||
class dstat_sys(dstat): | class dstat_sys(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'system' | self.name = 'system' | |||
self.nick = ('int', 'csw') | self.nick = ('int', 'csw') | |||
self.vars = ('intr', 'ctxt') | self.vars = ('intr', 'ctxt') | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 5 | self.width = 5 | |||
self.scale = 1000 | self.scale = 1000 | |||
self.open('/proc/stat') | self.open('/proc/stat') | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
name = l[0] | name = l[0] | |||
if name in self.vars: | if name in self.vars: | |||
self.set2[name] = long(l[1]) | self.set2[name] = int(l[1]) | |||
for name in self.vars: | for name in self.vars: | |||
self.val[name] = (self.set2[name] - self.set1[name]) * 1.0 / elapsed | self.val[name] = (self.set2[name] - self.set1[name]) * 1.0 / elapsed | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_tcp(dstat): | class dstat_tcp(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'tcp sockets' | self.name = 'tcp sockets' | |||
self.nick = ('lis', 'act', 'syn', 'tim', 'clo') | self.nick = ('lis', 'act', 'syn', 'tim', 'clo') | |||
self.vars = ('listen', 'established', 'syn', 'wait', 'close') | self.vars = ('listen', 'established', 'syn', 'wait', 'close') | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 4 | self.width = 4 | |||
self.scale = 100 | self.scale = 1000 | |||
self.open('/proc/net/tcp', '/proc/net/tcp6') | self.open('/proc/net/tcp', '/proc/net/tcp6') | |||
def extract(self): | def extract(self): | |||
for name in self.vars: self.val[name] = 0 | for name in self.vars: self.val[name] = 0 | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 12: continue | if len(l) < 12: continue | |||
### 01: established, 02: syn_sent, 03: syn_recv, 04: fin_wait1, | ### 01: established, 02: syn_sent, 03: syn_recv, 04: fin_wait1, | |||
### 05: fin_wait2, 06: time_wait, 07: close, 08: close_wait, | ### 05: fin_wait2, 06: time_wait, 07: close, 08: close_wait, | |||
### 09: last_ack, 0A: listen, 0B: closing | ### 09: last_ack, 0A: listen, 0B: closing | |||
if l[3] in ('0A',): self.val['listen'] += 1 | if l[3] in ('0A',): self.val['listen'] += 1 | |||
skipping to change at line 1656 | skipping to change at line 1632 | |||
self.val['time'] = time.strftime(self.timefmt, time.localtime(startt ime)) + ".%03d" % (round(starttime * 1000 % 1000 )) | self.val['time'] = time.strftime(self.timefmt, time.localtime(startt ime)) + ".%03d" % (round(starttime * 1000 % 1000 )) | |||
else: | else: | |||
self.val['time'] = time.strftime(self.timefmt, time.localtime(startt ime)) | self.val['time'] = time.strftime(self.timefmt, time.localtime(startt ime)) | |||
class dstat_udp(dstat): | class dstat_udp(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'udp' | self.name = 'udp' | |||
self.nick = ('lis', 'act') | self.nick = ('lis', 'act') | |||
self.vars = ('listen', 'established') | self.vars = ('listen', 'established') | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 3 | self.width = 4 | |||
self.scale = 100 | self.scale = 1000 | |||
self.open('/proc/net/udp', '/proc/net/udp6') | self.open('/proc/net/udp', '/proc/net/udp6') | |||
def extract(self): | def extract(self): | |||
for name in self.vars: self.val[name] = 0 | for name in self.vars: self.val[name] = 0 | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if l[3] == '07': self.val['listen'] += 1 | if l[3] == '07': self.val['listen'] += 1 | |||
elif l[3] == '01': self.val['established'] += 1 | elif l[3] == '01': self.val['established'] += 1 | |||
class dstat_unix(dstat): | class dstat_unix(dstat): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'unix sockets' | self.name = 'unix sockets' | |||
self.nick = ('dgm', 'str', 'lis', 'act') | self.nick = ('dgm', 'str', 'lis', 'act') | |||
self.vars = ('datagram', 'stream', 'listen', 'established') | self.vars = ('datagram', 'stream', 'listen', 'established') | |||
self.type = 'd' | self.type = 'd' | |||
self.width = 3 | self.width = 4 | |||
self.scale = 100 | self.scale = 1000 | |||
self.open('/proc/net/unix') | self.open('/proc/net/unix') | |||
def extract(self): | def extract(self): | |||
for name in self.vars: self.val[name] = 0 | for name in self.vars: self.val[name] = 0 | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if l[4] == '0002': self.val['datagram'] += 1 | if l[4] == '0002': self.val['datagram'] += 1 | |||
elif l[4] == '0001': | elif l[4] == '0001': | |||
self.val['stream'] += 1 | self.val['stream'] += 1 | |||
if l[5] == '01': self.val['listen'] += 1 | if l[5] == '01': self.val['listen'] += 1 | |||
elif l[5] == '03': self.val['established'] += 1 | elif l[5] == '03': self.val['established'] += 1 | |||
skipping to change at line 1704 | skipping to change at line 1680 | |||
self.scale = 1000 | self.scale = 1000 | |||
self.open('/proc/vmstat') | self.open('/proc/vmstat') | |||
def extract(self): | def extract(self): | |||
for name in self.vars: | for name in self.vars: | |||
self.set2[name] = 0 | self.set2[name] = 0 | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
for name in self.vars: | for name in self.vars: | |||
if fnmatch.fnmatch(l[0], name): | if fnmatch.fnmatch(l[0], name): | |||
self.set2[name] += long(l[1]) | self.set2[name] += int(l[1]) | |||
for name in self.vars: | for name in self.vars: | |||
self.val[name] = (self.set2[name] - self.set1[name]) * 1.0 / elapsed | self.val[name] = (self.set2[name] - self.set1[name]) * 1.0 / elapsed | |||
if step == op.delay: | if step == op.delay: | |||
self.set1.update(self.set2) | self.set1.update(self.set2) | |||
class dstat_vm_adv(dstat_vm): | class dstat_vm_adv(dstat_vm): | |||
def __init__(self): | def __init__(self): | |||
self.name = 'advanced virtual memory' | self.name = 'advanced virtual memory' | |||
skipping to change at line 1743 | skipping to change at line 1719 | |||
### Page allocations should include all page zones, not just ZONE_NORMAL, | ### Page allocations should include all page zones, not just ZONE_NORMAL, | |||
### but also ZONE_DMA, ZONE_HIGHMEM, ZONE_DMA32 (depending on architecture) | ### but also ZONE_DMA, ZONE_HIGHMEM, ZONE_DMA32 (depending on architecture) | |||
def extract(self): | def extract(self): | |||
for l in self.splitlines(): | for l in self.splitlines(): | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
if l[0].startswith('Node'): | if l[0].startswith('Node'): | |||
zone = l[3] | zone = l[3] | |||
found_high = 0 | found_high = 0 | |||
if l[0].startswith('pages'): | if l[0].startswith('pages'): | |||
self.val[zone+'_free'] = long(l[2]) | self.val[zone+'_free'] = int(l[2]) | |||
if l[0].startswith('high') and not found_high: | if l[0].startswith('high') and not found_high: | |||
self.val[zone+'_high'] = long(l[1]) | self.val[zone+'_high'] = int(l[1]) | |||
found_high = 1 | found_high = 1 | |||
### END STATS DEFINITIONS ### | ### END STATS DEFINITIONS ### | |||
color = { | color = { | |||
'black': '\033[0;30m', | 'black': '\033[0;30m', | |||
'darkred': '\033[0;31m', | 'darkred': '\033[0;31m', | |||
'darkgreen': '\033[0;32m', | 'darkgreen': '\033[0;32m', | |||
'darkyellow': '\033[0;33m', | 'darkyellow': '\033[0;33m', | |||
'darkblue': '\033[0;34m', | 'darkblue': '\033[0;34m', | |||
skipping to change at line 1788 | skipping to change at line 1764 | |||
ansi = { | ansi = { | |||
'reset': '\033[0;0m', | 'reset': '\033[0;0m', | |||
'bold': '\033[1m', | 'bold': '\033[1m', | |||
'reverse': '\033[2m', | 'reverse': '\033[2m', | |||
'underline': '\033[4m', | 'underline': '\033[4m', | |||
'clear': '\033[2J', | 'clear': '\033[2J', | |||
# 'clearline': '\033[K', | # 'clearline': '\033[K', | |||
'clearline': '\033[2K', | 'clearline': '\033[2K', | |||
# 'save': '\033[s', | 'save': '\033[s', | |||
# 'restore': '\033[u', | 'restore': '\033[u', | |||
'save': '\0337', | 'save_all': '\0337', | |||
'restore': '\0338', | 'restore_all': '\0338', | |||
'linewrap': '\033[7h', | 'linewrap': '\033[7h', | |||
'nolinewrap': '\033[7l', | 'nolinewrap': '\033[7l', | |||
'up': '\033[1A', | 'up': '\033[1A', | |||
'down': '\033[1B', | 'down': '\033[1B', | |||
'right': '\033[1C', | 'right': '\033[1C', | |||
'left': '\033[1D', | 'left': '\033[1D', | |||
'default': '\033[0;0m', | 'default': '\033[0;0m', | |||
} | } | |||
skipping to change at line 1863 | skipping to change at line 1839 | |||
'colors_lo': (color['red'], color['yellow'], color['green'], color[' blue'], | 'colors_lo': (color['red'], color['yellow'], color['green'], color[' blue'], | |||
color['cyan'], color['white'], color['darkred'], color ['darkgreen']), | color['cyan'], color['white'], color['darkred'], color ['darkgreen']), | |||
'colors_hi': (color['darkred'], color['darkyellow'], color['darkgree n'], color['darkblue'], | 'colors_hi': (color['darkred'], color['darkyellow'], color['darkgree n'], color['darkblue'], | |||
color['darkcyan'], color['gray'], color['red'], color[ 'green']), | color['darkcyan'], color['gray'], color['red'], color[ 'green']), | |||
} | } | |||
return theme | return theme | |||
def ticks(): | def ticks(): | |||
"Return the number of 'ticks' since bootup" | "Return the number of 'ticks' since bootup" | |||
try: | try: | |||
for line in open('/proc/uptime', 'r', 0).readlines(): | for line in open('/proc/uptime', 'r').readlines(): | |||
l = line.split() | l = line.split() | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
return float(l[0]) | return float(l[0]) | |||
except: | except: | |||
for line in dopen('/proc/stat').readlines(): | for line in dopen('/proc/stat').readlines(): | |||
l = line.split() | l = line.split() | |||
if len(l) < 2: continue | if len(l) < 2: continue | |||
if l[0] == 'btime': | if l[0] == 'btime': | |||
return time.time() - long(l[1]) | return time.time() - int(l[1]) | |||
def improve(devname): | def improve(devname): | |||
"Improve a device name" | "Improve a device name" | |||
if devname.startswith('/dev/mapper/'): | if devname.startswith('/dev/mapper/'): | |||
devname = devname.split('/')[3] | devname = devname.split('/')[3] | |||
elif devname.startswith('/dev/'): | elif devname.startswith('/dev/'): | |||
devname = devname.split('/')[2] | devname = devname.split('/')[2] | |||
return devname | return devname | |||
def dopen(filename): | def dopen(filename): | |||
"Open a file for reuse, if already opened, return file descriptor" | "Open a file for reuse, if already opened, return file descriptor" | |||
global fds | global fds | |||
if not os.path.exists(filename): | if not os.path.exists(filename): | |||
raise Exception, 'File %s does not exist' % filename | raise Exception('File %s does not exist' % filename) | |||
# return None | if 'fds' not in globals(): | |||
if 'fds' not in globals().keys(): | ||||
fds = {} | fds = {} | |||
if file not in fds.keys(): | if filename in fds: | |||
fds[filename] = open(filename, 'r', 0) | ||||
else: | ||||
fds[filename].seek(0) | fds[filename].seek(0) | |||
else: | ||||
fds[filename] = open(filename, 'r') | ||||
return fds[filename] | return fds[filename] | |||
def dclose(filename): | def dclose(filename): | |||
"Close an open file and remove file descriptor from list" | "Close an open file and remove file descriptor from list" | |||
global fds | global fds | |||
if not 'fds' in globals().keys(): fds = {} | if not 'fds' in globals(): fds = {} | |||
if filename in fds: | if filename in fds: | |||
fds[filename].close() | fds[filename].close() | |||
del(fds[filename]) | del(fds[filename]) | |||
def dpopen(cmd): | def dpopen(cmd): | |||
"Open a pipe for reuse, if already opened, return pipes" | "Open a pipe for reuse, if already opened, return pipes" | |||
global pipes, select | global pipes, select | |||
import select | import select | |||
if 'pipes' not in globals().keys(): pipes = {} | if 'pipes' not in globals(): pipes = {} | |||
if cmd not in pipes.keys(): | if cmd not in pipes: | |||
try: | try: | |||
import asubprocess | import asubprocess | |||
p = subprocess.Popen(cmd, shell=True, bufsize=0, close_fds=True, | p = subprocess.Popen(cmd, shell=True, bufsize=0, close_fds=True, | |||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess .PIPE) | stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess .PIPE) | |||
pipes[cmd] = (p.stdin, p.stdout, p.stderr) | pipes[cmd] = (p.stdin, p.stdout, p.stderr) | |||
except ImportError: | except ImportError: | |||
pipes[cmd] = os.popen3(cmd, 't', 0) | pipes[cmd] = os.popen3(cmd, 't', 0) | |||
return pipes[cmd] | return pipes[cmd] | |||
def readpipe(fileobj, tmout = 0.001): | def readpipe(fileobj, tmout = 0.001): | |||
skipping to change at line 1942 | skipping to change at line 1917 | |||
pass | pass | |||
while select.select([fileobj.fileno()], [], [], tmout)[0]: | while select.select([fileobj.fileno()], [], [], tmout)[0]: | |||
character = fileobj.read(1) | character = fileobj.read(1) | |||
if character != '\n': | if character != '\n': | |||
ret = ret + character | ret = ret + character | |||
elif ret.startswith(str): | elif ret.startswith(str): | |||
return ret | return ret | |||
else: | else: | |||
ret = '' | ret = '' | |||
if op.debug: | if op.debug: | |||
raise Exception, 'Nothing found during greppipe data collection' | raise Exception('Nothing found during greppipe data collection') | |||
return None | return None | |||
def matchpipe(fileobj, string, tmout = 0.001): | def matchpipe(fileobj, string, tmout = 0.001): | |||
"Match available data from pipe in a non-blocking fashion" | "Match available data from pipe in a non-blocking fashion" | |||
ret = '' | ret = '' | |||
regexp = re.compile(string) | regexp = re.compile(string) | |||
while not select.select([fileobj.fileno()], [], [], tmout)[0]: | while not select.select([fileobj.fileno()], [], [], tmout)[0]: | |||
pass | pass | |||
while select.select([fileobj.fileno()], [], [], tmout)[0]: | while select.select([fileobj.fileno()], [], [], tmout)[0]: | |||
character = fileobj.read(1) | character = fileobj.read(1) | |||
if character != '\n': | if character != '\n': | |||
ret = ret + character | ret = ret + character | |||
elif regexp.match(ret): | elif regexp.match(ret): | |||
return ret | return ret | |||
else: | else: | |||
ret = '' | ret = '' | |||
if op.debug: | if op.debug: | |||
raise Exception, 'Nothing found during matchpipe data collection' | raise Exception('Nothing found during matchpipe data collection') | |||
return None | return None | |||
def cmd_test(cmd): | def cmd_test(cmd): | |||
pipes = os.popen3(cmd, 't', 0) | pipes = os.popen3(cmd, 't', 0) | |||
for line in pipes[2].readlines(): | for line in pipes[2].readlines(): | |||
raise Exception, line.strip() | raise Exception(line.strip()) | |||
def cmd_readlines(cmd): | def cmd_readlines(cmd): | |||
pipes = os.popen3(cmd, 't', 0) | pipes = os.popen3(cmd, 't', 0) | |||
for line in pipes[1].readlines(): | for line in pipes[1].readlines(): | |||
yield line | yield line | |||
def cmd_splitlines(cmd, sep=None): | def cmd_splitlines(cmd, sep=None): | |||
pipes = os.popen3(cmd, 't', 0) | pipes = os.popen3(cmd, 't', 0) | |||
for line in pipes[1].readlines(): | for line in pipes[1].readlines(): | |||
yield line.split(sep) | yield line.split(sep) | |||
skipping to change at line 2037 | skipping to change at line 2012 | |||
except ValueError: | except ValueError: | |||
continue | continue | |||
def snmpget(server, community, oid): | def snmpget(server, community, oid): | |||
errorIndication, errorStatus, errorIndex, varBinds = cmdgen.CommandGenerator ().getCmd( | errorIndication, errorStatus, errorIndex, varBinds = cmdgen.CommandGenerator ().getCmd( | |||
cmdgen.CommunityData('test-agent', community, 0), | cmdgen.CommunityData('test-agent', community, 0), | |||
cmdgen.UdpTransportTarget((server, 161)), | cmdgen.UdpTransportTarget((server, 161)), | |||
oid | oid | |||
) | ) | |||
# print '%s -> ind: %s, stat: %s, idx: %s' % (oid, errorIndication, errorStat us, errorIndex) | # print('%s -> ind: %s, stat: %s, idx: %s' % (oid, errorIndication, errorStat us, errorIndex)) | |||
for x in varBinds: | for x in varBinds: | |||
return str(x[1]) | return str(x[1]) | |||
def snmpwalk(server, community, oid): | def snmpwalk(server, community, oid): | |||
ret = [] | ret = [] | |||
errorIndication, errorStatus, errorIndex, varBindTable = cmdgen.CommandGener ator().nextCmd( | errorIndication, errorStatus, errorIndex, varBindTable = cmdgen.CommandGener ator().nextCmd( | |||
cmdgen.CommunityData('test-agent', community, 0), | cmdgen.CommunityData('test-agent', community, 0), | |||
cmdgen.UdpTransportTarget((server, 161)), | cmdgen.UdpTransportTarget((server, 161)), | |||
oid | oid | |||
) | ) | |||
# print '%s -> ind: %s, stat: %s, idx: %s' % (oid, errorIndication, errorStat us, errorIndex) | # print('%s -> ind: %s, stat: %s, idx: %s' % (oid, errorIndication, errorStat us, errorIndex)) | |||
for x in varBindTable: | for x in varBindTable: | |||
for y in x: | for y in x: | |||
ret.append(str(y[1])) | ret.append(str(y[1])) | |||
return ret | return ret | |||
def dchg(var, width, base): | def dchg(var, width, base): | |||
"Convert decimal to string given base and length" | "Convert decimal to string given base and length" | |||
c = 0 | c = 0 | |||
while True: | while True: | |||
ret = str(long(round(var))) | ret = str(int(round(var))) | |||
if len(ret) <= width: | if len(ret) <= width: | |||
break | break | |||
var = var / base | var = var / base | |||
c = c + 1 | c = c + 1 | |||
else: | else: | |||
c = -1 | c = -1 | |||
return ret, c | return ret, c | |||
def fchg(var, width, base): | def fchg(var, width, base): | |||
"Convert float to string given scale and length" | "Convert float to string given scale and length" | |||
c = 0 | c = 0 | |||
while True: | while True: | |||
if var == 0: | if var == 0: | |||
ret = str('0') | ret = str('0') | |||
break | break | |||
# ret = repr(round(var)) | # ret = repr(round(var)) | |||
# ret = repr(long(round(var, maxlen))) | # ret = repr(int(round(var, maxlen))) | |||
ret = str(long(round(var, width))) | ret = str(int(round(var, width))) | |||
if len(ret) <= width: | if len(ret) <= width: | |||
i = width - len(ret) - 1 | i = width - len(ret) - 1 | |||
while i > 0: | while i > 0: | |||
ret = ('%%.%df' % i) % var | ret = ('%%.%df' % i) % var | |||
if len(ret) <= width and ret != str(long(round(var, width))): | if len(ret) <= width and ret != str(int(round(var, width))): | |||
break | break | |||
i = i - 1 | i = i - 1 | |||
else: | else: | |||
ret = str(long(round(var))) | ret = str(int(round(var))) | |||
break | break | |||
var = var / base | var = var / base | |||
c = c + 1 | c = c + 1 | |||
else: | else: | |||
c = -1 | c = -1 | |||
return ret, c | return ret, c | |||
def tchg(var, width): | def tchg(var, width): | |||
"Convert time string to given length" | "Convert time string to given length" | |||
ret = '%2dh%02d' % (var / 60, var % 60) | ret = '%2dh%02d' % (var / 60, var % 60) | |||
if len(ret) > width: | if len(ret) > width: | |||
ret = '%2dh' % (var / 60) | ret = '%2dh' % (var / 60) | |||
if len(ret) > width: | if len(ret) > width: | |||
ret = '%2dd' % (var / 60 / 24) | ret = '%2dd' % (var / 60 / 24) | |||
if len(ret) > width: | if len(ret) > width: | |||
ret = '%2dw' % (var / 60 / 24 / 7) | ret = '%2dw' % (var / 60 / 24 / 7) | |||
return ret | return ret | |||
def cprintlist(varlist, type, width, scale): | def cprintlist(varlist, ctype, width, scale): | |||
"Return all columns color printed" | "Return all columns color printed" | |||
ret = sep = '' | ret = sep = '' | |||
for var in varlist: | for var in varlist: | |||
ret = ret + sep + cprint(var, type, width, scale) | ret = ret + sep + cprint(var, ctype, width, scale) | |||
sep = char['space'] | sep = char['space'] | |||
return ret | return ret | |||
def cprint(var, type = 'f', width = 4, scale = 1000): | def cprint(var, ctype = 'f', width = 4, scale = 1000): | |||
"Color print one column" | "Color print one column" | |||
base = 1000 | base = 1000 | |||
if scale == 1024: | if scale == 1024: | |||
base = 1024 | base = 1024 | |||
### Use units when base is exact 1000 or 1024 | ### Use units when base is exact 1000 or 1024 | |||
unit = False | unit = False | |||
if scale in (1000, 1024) and width >= len(str(base)): | if scale in (1000, 1024) and width >= len(str(base)): | |||
unit = True | unit = True | |||
width = width - 1 | width = width - 1 | |||
### If this is a negative value, return a dash | ### If this is a negative value, return a dash | |||
if var < 0: | if ctype != 's' and var < 0: | |||
if unit: | if unit: | |||
return theme['error'] + '-'.rjust(width) + char['space'] + theme['de fault'] | return theme['error'] + '-'.rjust(width) + char['space'] + theme['de fault'] | |||
else: | else: | |||
return theme['error'] + '-'.rjust(width) + theme['default'] | return theme['error'] + '-'.rjust(width) + theme['default'] | |||
if base != 1024: | if base != 1024: | |||
units = (char['space'], 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') | units = (char['space'], 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') | |||
elif op.bits and type in ('b', ): | elif op.bits and ctype in ('b', ): | |||
units = ('b', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') | units = ('b', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') | |||
base = scale = 1000 | base = scale = 1000 | |||
var = var * 8.0 | var = var * 8.0 | |||
else: | else: | |||
units = ('B', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') | units = ('B', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') | |||
if step == op.delay: | if step == op.delay: | |||
colors = theme['colors_lo'] | colors = theme['colors_lo'] | |||
ctext = theme['text_lo'] | ctext = theme['text_lo'] | |||
cunit = theme['unit_lo'] | cunit = theme['unit_lo'] | |||
cdone = theme['done_lo'] | cdone = theme['done_lo'] | |||
else: | else: | |||
colors = theme['colors_hi'] | colors = theme['colors_hi'] | |||
ctext = theme['text_hi'] | ctext = theme['text_hi'] | |||
cunit = theme['unit_hi'] | cunit = theme['unit_hi'] | |||
cdone = theme['done_hi'] | cdone = theme['done_hi'] | |||
### Convert value to string given base and field-length | ### Convert value to string given base and field-length | |||
if op.integer and type in ('b', 'd', 'p', 'f'): | if op.integer and ctype in ('b', 'd', 'p', 'f'): | |||
ret, c = dchg(var, width, base) | ret, c = dchg(var, width, base) | |||
elif op.float and type in ('b', 'd', 'p', 'f'): | elif op.float and ctype in ('b', 'd', 'p', 'f'): | |||
ret, c = fchg(var, width, base) | ret, c = fchg(var, width, base) | |||
elif type in ('b', 'd', 'p'): | elif ctype in ('b', 'd', 'p'): | |||
ret, c = dchg(var, width, base) | ret, c = dchg(var, width, base) | |||
elif type in ('f'): | elif ctype in ('f',): | |||
ret, c = fchg(var, width, base) | ret, c = fchg(var, width, base) | |||
elif type in ('s',): | elif ctype in ('s',): | |||
ret, c = str(var), ctext | ret, c = str(var), ctext | |||
elif type in ('t'): | elif ctype in ('t',): | |||
ret, c = tchg(var, width), ctext | ret, c = tchg(var, width), ctext | |||
else: | else: | |||
raise Exception, 'Type %s not known to dstat.' % type | raise Exception('Type %s not known to dstat.' % ctype) | |||
### Set the counter color | ### Set the counter color | |||
if ret == '0': | if ret == '0': | |||
color = cunit | color = cunit | |||
elif scale <= 0: | elif scale <= 0: | |||
color = ctext | color = ctext | |||
elif type in ('p') and round(var) >= 100.0: | elif ctype in ('p') and round(var) >= 100.0: | |||
color = cdone | color = cdone | |||
# elif type in ('p'): | # elif type in ('p'): | |||
# color = colors[int(round(var)/scale)%len(colors)] | # color = colors[int(round(var)/scale)%len(colors)] | |||
elif scale not in (1000, 1024): | elif scale not in (1000, 1024): | |||
color = colors[int(var/scale)%len(colors)] | color = colors[int(var/scale)%len(colors)] | |||
elif type in ('b', 'd', 'f'): | elif ctype in ('b', 'd', 'f'): | |||
color = colors[c%len(colors)] | color = colors[c%len(colors)] | |||
else: | else: | |||
color = ctext | color = ctext | |||
### Justify value to left if string | ### Justify value to left if string | |||
if type in ('s',): | if ctype in ('s',): | |||
ret = color + ret.ljust(width) | ret = color + ret.ljust(width) | |||
else: | else: | |||
ret = color + ret.rjust(width) | ret = color + ret.rjust(width) | |||
### Add unit to output | ### Add unit to output | |||
if unit: | if unit: | |||
if c != -1 and round(var) != 0: | if c != -1 and round(var) != 0: | |||
ret += cunit + units[c] | ret += cunit + units[c] | |||
else: | else: | |||
ret += char['space'] | ret += char['space'] | |||
skipping to change at line 2235 | skipping to change at line 2210 | |||
if o is not totlist[-1]: | if o is not totlist[-1]: | |||
line = line + char['sep'] | line = line + char['sep'] | |||
line += '\n' | line += '\n' | |||
### Process subtitle | ### Process subtitle | |||
for o in totlist: | for o in totlist: | |||
line = line + o.csvsubtitle() | line = line + o.csvsubtitle() | |||
if o is not totlist[-1]: | if o is not totlist[-1]: | |||
line = line + char['sep'] | line = line + char['sep'] | |||
return line + '\n' | return line + '\n' | |||
def info(level, str): | def info(level, msg): | |||
"Output info message" | "Output info message" | |||
# if level <= op.verbose: | # if level <= op.verbose: | |||
print >>sys.stderr, str | print(msg, file=sys.stderr) | |||
def die(ret, str): | def die(ret, msg): | |||
"Print error and exit with errorcode" | "Print error and exit with errorcode" | |||
print >>sys.stderr, str | print(msg, file=sys.stderr) | |||
exit(ret) | exit(ret) | |||
def initterm(): | def initterm(): | |||
"Initialise terminal" | "Initialise terminal" | |||
global termsize | global termsize | |||
### Unbuffered sys.stdout | ### Unbuffered sys.stdout | |||
# sys.stdout = os.fdopen(1, 'w', 0) | # sys.stdout = os.fdopen(1, 'w', 0) | |||
termsize = None, 0 | termsize = None, 0 | |||
skipping to change at line 2297 | skipping to change at line 2272 | |||
def gettermcolor(): | def gettermcolor(): | |||
"Return whether the system can use colors or not" | "Return whether the system can use colors or not" | |||
if sys.stdout.isatty(): | if sys.stdout.isatty(): | |||
try: | try: | |||
import curses | import curses | |||
curses.setupterm() | curses.setupterm() | |||
if curses.tigetnum('colors') < 0: | if curses.tigetnum('colors') < 0: | |||
return False | return False | |||
except ImportError: | except ImportError: | |||
print >>sys.stderr, 'Color support is disabled as python-curses is n ot installed.' | print('Color support is disabled as python-curses is not installed.' , file=sys.stderr) | |||
return False | return False | |||
except: | except: | |||
print >>sys.stderr, 'Color support is disabled as curses does not fi nd terminal "%s".' % os.getenv('TERM') | print('Color support is disabled as curses does not find terminal "% s".' % os.getenv('TERM'), file=sys.stderr) | |||
return False | return False | |||
return True | return True | |||
return False | return False | |||
### We only want to filter out paths, not ksoftirqd/1 | ### We only want to filter out paths, not ksoftirqd/1 | |||
def basename(name): | def basename(name): | |||
"Perform basename on paths only" | "Perform basename on paths only" | |||
if name[0] in ('/', '.'): | if name[0] in ('/', '.'): | |||
return os.path.basename(name) | return os.path.basename(name) | |||
return name | return name | |||
skipping to change at line 2364 | skipping to change at line 2339 | |||
# Fallback 2 | # Fallback 2 | |||
try: | try: | |||
search = re.compile('^cpu\d+') | search = re.compile('^cpu\d+') | |||
cpunr = 0 | cpunr = 0 | |||
for line in dopen('/proc/stat').readlines(): | for line in dopen('/proc/stat').readlines(): | |||
if search.match(line): | if search.match(line): | |||
cpunr += 1 | cpunr += 1 | |||
if cpunr > 0: | if cpunr > 0: | |||
return cpunr | return cpunr | |||
except: | except: | |||
raise Exception, "Problem finding number of CPUs in system." | raise Exception("Problem finding number of CPUs in system.") | |||
def blockdevices(): | def blockdevices(): | |||
### We have to replace '!' by '/' to support cciss!c0d0 type devices :-/ | ### We have to replace '!' by '/' to support cciss!c0d0 type devices :-/ | |||
return [os.path.basename(filename).replace('!', '/') for filename in glob.gl ob('/sys/block/*')] | return [os.path.basename(filename).replace('!', '/') for filename in glob.gl ob('/sys/block/*')] | |||
### FIXME: Add scsi support too and improve | ### FIXME: Add scsi support too and improve | |||
def sysfs_dev(device): | def sysfs_dev(device): | |||
"Convert sysfs device names into device names" | "Convert sysfs device names into device names" | |||
m = re.match('ide/host(\d)/bus(\d)/target(\d)/lun(\d)/disc', device) | m = re.match('ide/host(\d)/bus(\d)/target(\d)/lun(\d)/disc', device) | |||
if m: | if m: | |||
skipping to change at line 2478 | skipping to change at line 2453 | |||
plugins.append(remod.match(filename).groups()[0].replace('_', '-')) | plugins.append(remod.match(filename).groups()[0].replace('_', '-')) | |||
remod = re.compile('.+/dstat_(.+).py$') | remod = re.compile('.+/dstat_(.+).py$') | |||
for path in pluginpath: | for path in pluginpath: | |||
for filename in glob.glob(path + '/dstat_*.py'): | for filename in glob.glob(path + '/dstat_*.py'): | |||
plugins.append(remod.match(filename).groups()[0].replace('_', '-')) | plugins.append(remod.match(filename).groups()[0].replace('_', '-')) | |||
plugins.sort() | plugins.sort() | |||
return plugins | return plugins | |||
def showplugins(): | def showplugins(): | |||
rows, cols = gettermsize() | rows, cols = gettermsize() | |||
print 'internal:\n\t', | print('internal:\n\t', end='') | |||
remod = re.compile('^dstat_(.+)$') | remod = re.compile('^dstat_(.+)$') | |||
plugins = [] | plugins = [] | |||
for filename in globals(): | for filename in globals(): | |||
if filename.startswith('dstat_'): | if filename.startswith('dstat_'): | |||
plugins.append(remod.match(filename).groups()[0].replace('_', '-')) | plugins.append(remod.match(filename).groups()[0].replace('_', '-')) | |||
plugins.sort() | plugins.sort() | |||
cols2 = cols - 8 | cols2 = cols - 8 | |||
for mod in plugins: | for mod in plugins: | |||
cols2 = cols2 - len(mod) - 2 | cols2 = cols2 - len(mod) - 2 | |||
if cols2 <= 0: | if cols2 <= 0: | |||
print '\n\t', | print('\n\t', end='') | |||
cols2 = cols - len(mod) - 10 | cols2 = cols - len(mod) - 10 | |||
if mod != plugins[-1]: | if mod != plugins[-1]: | |||
print mod+',', | print(mod, end=',') | |||
print mod | print(mod) | |||
remod = re.compile('.+/dstat_(.+).py$') | remod = re.compile('.+/dstat_(.+).py$') | |||
for path in pluginpath: | for path in pluginpath: | |||
plugins = [] | plugins = [] | |||
for filename in glob.glob(path + '/dstat_*.py'): | for filename in glob.glob(path + '/dstat_*.py'): | |||
plugins.append(remod.match(filename).groups()[0].replace('_', '-')) | plugins.append(remod.match(filename).groups()[0].replace('_', '-')) | |||
if not plugins: continue | if not plugins: continue | |||
plugins.sort() | plugins.sort() | |||
cols2 = cols - 8 | cols2 = cols - 8 | |||
print '%s:\n\t' % os.path.abspath(path), | print('%s:' % os.path.abspath(path), end='\n\t') | |||
for mod in plugins: | for mod in plugins: | |||
cols2 = cols2 - len(mod) - 2 | cols2 = cols2 - len(mod) - 2 | |||
if cols2 <= 0: | if cols2 <= 0: | |||
print '\n\t', | print(end='\n\t') | |||
cols2 = cols - len(mod) - 10 | cols2 = cols - len(mod) - 10 | |||
if mod != plugins[-1]: | if mod != plugins[-1]: | |||
print mod+',', | print(mod, end=',') | |||
print mod | print(mod) | |||
def exit(ret): | def exit(ret): | |||
sys.stdout.write(ansi['reset']) | sys.stdout.write(ansi['reset']) | |||
sys.stdout.flush() | sys.stdout.flush() | |||
if op.pidfile and os.path.exists(op.pidfile): | if op.pidfile and os.path.exists(op.pidfile): | |||
os.remove(op.pidfile) | os.remove(op.pidfile) | |||
if op.profile and os.path.exists(op.profile): | if op.profile and os.path.exists(op.profile): | |||
rows, cols = gettermsize() | rows, cols = gettermsize() | |||
import pstats | import pstats | |||
p = pstats.Stats(op.profile) | p = pstats.Stats(op.profile) | |||
# p.sort_stats('name') | # p.sort_stats('name') | |||
# p.print_stats() | # p.print_stats() | |||
p.sort_stats('cumulative').print_stats(rows - 13) | p.sort_stats('cumulative').print_stats(rows - 13) | |||
# p.sort_stats('time').print_stats(rows - 13) | # p.sort_stats('time').print_stats(rows - 13) | |||
# p.sort_stats('file').print_stats('__init__') | # p.sort_stats('file').print_stats('__init__') | |||
# p.sort_stats('time', 'cum').print_stats(.5, 'init') | # p.sort_stats('time', 'cum').print_stats(.5, 'init') | |||
# p.print_callees() | # p.print_callees() | |||
elif op.profile: | elif op.profile: | |||
print >>sys.stderr, "No profiling data was found, maybe profiler was int errupted ?" | print('No profiling data was found, maybe profiler was interrupted ?', f ile=sys.stderr) | |||
sys.exit(ret) | sys.exit(ret) | |||
def main(): | def main(): | |||
"Initialization of the program, terminal, internal structures" | "Initialization of the program, terminal, internal structures" | |||
global cpunr, hz, maxint, ownpid, pagesize | global cpunr, hz, maxint, ownpid, pagesize | |||
global ansi, theme, outputfile | global ansi, theme, outputfile | |||
global totlist, inittime | global totlist, inittime | |||
global update, missed | global update, missed | |||
cpunr = getcpunr() | cpunr = getcpunr() | |||
hz = os.sysconf('SC_CLK_TCK') | hz = os.sysconf('SC_CLK_TCK') | |||
maxint = (sys.maxint + 1) * 2 | try: | |||
maxint = (sys.maxint + 1) * 2 | ||||
except: | ||||
# Support Python 3 | ||||
maxint = float("inf") | ||||
ownpid = str(os.getpid()) | ownpid = str(os.getpid()) | |||
pagesize = resource.getpagesize() | pagesize = resource.getpagesize() | |||
interval = 1 | interval = 1 | |||
user = getpass.getuser() | user = getpass.getuser() | |||
hostname = os.uname()[1] | hostname = os.uname()[1] | |||
### Disable line-wrapping (does not work ?) | ||||
sys.stdout.write('\033[7l') | ||||
### Write term-title | ### Write term-title | |||
if sys.stdout.isatty(): | if sys.stdout.isatty(): | |||
shell = os.getenv('XTERM_SHELL') | shell = os.getenv('XTERM_SHELL') | |||
term = os.getenv('TERM') | term = os.getenv('TERM') | |||
if shell == '/bin/bash' and term and re.compile('(screen*|xterm*)').matc h(term): | if shell == '/bin/bash' and term and re.compile('(screen*|xterm*)').matc h(term): | |||
sys.stdout.write('\033]0;(%s@%s) %s %s\007' % (user, hostname.split( '.')[0], os.path.basename(sys.argv[0]), ' '.join(op.args))) | sys.stdout.write('\033]0;(%s@%s) %s %s\007' % (user, hostname.split( '.')[0], os.path.basename(sys.argv[0]), ' '.join(op.args))) | |||
### Check background color (rxvt) | ### Check background color (rxvt) | |||
### COLORFGBG="15;default;0" | ### COLORFGBG="15;default;0" | |||
# if os.environ['COLORFGBG'] and len(os.environ['COLORFGBG'].split(';')) >= 3: | # if os.environ['COLORFGBG'] and len(os.environ['COLORFGBG'].split(';')) >= 3: | |||
skipping to change at line 2581 | skipping to change at line 2557 | |||
# else: | # else: | |||
# print 'Background is unknown, assuming dark.' | # print 'Background is unknown, assuming dark.' | |||
### Check terminal capabilities | ### Check terminal capabilities | |||
if op.color == None: | if op.color == None: | |||
op.color = gettermcolor() | op.color = gettermcolor() | |||
### Prepare CSV output file (unbuffered) | ### Prepare CSV output file (unbuffered) | |||
if op.output: | if op.output: | |||
if not os.path.exists(op.output): | if not os.path.exists(op.output): | |||
outputfile = open(op.output, 'w', 0) | outputfile = open(op.output, 'w') | |||
outputfile.write('"Dstat %s CSV output"\n' % VERSION) | outputfile.write('"Dstat %s CSV output"\n' % VERSION) | |||
header = ('"Author:","Dag Wieers <dag@wieers.com>"','','','','"URL:" ','"http://dag.wieers.com/home-made/dstat/"\n') | header = ('"Author:","Dag Wieers <dag@wieers.com>"','','','','"URL:" ','"http://dag.wieers.com/home-made/dstat/"\n') | |||
outputfile.write(char['sep'].join(header)) | outputfile.write(char['sep'].join(header)) | |||
else: | else: | |||
outputfile = open(op.output, 'a', 0) | outputfile = open(op.output, 'a') | |||
outputfile.write('\n\n') | outputfile.write('\n\n') | |||
header = ('"Host:"','"%s"' % hostname,'','','','"User:"','"%s"\n' % user ) | header = ('"Host:"','"%s"' % hostname,'','','','"User:"','"%s"\n' % user ) | |||
outputfile.write(char['sep'].join(header)) | outputfile.write(char['sep'].join(header)) | |||
header = ('"Cmdline:"','"dstat %s"' % ' '.join(op.args),'','','','"Date: "','"%s"\n' % time.strftime('%d %b %Y %H:%M:%S %Z', time.localtime())) | header = ('"Cmdline:"','"dstat %s"' % ' '.join(op.args),'','','','"Date: "','"%s"\n' % time.strftime('%d %b %Y %H:%M:%S %Z', time.localtime())) | |||
outputfile.write(char['sep'].join(header)) | outputfile.write(char['sep'].join(header)) | |||
### Create pidfile | ### Create pidfile | |||
if op.pidfile: | if op.pidfile: | |||
try: | try: | |||
pidfile = open(op.pidfile, 'w', 0) | pidfile = open(op.pidfile, 'w') | |||
pidfile.write(str(os.getpid())) | pidfile.write(str(os.getpid())) | |||
pidfile.close() | pidfile.close() | |||
except Exception, e: | except Exception as e: | |||
print >>sys.stderr, 'Failed to create pidfile %s' % op.pidfile, e | print('Failed to create pidfile %s: %s' % (op.pidfile, e), file=sys. | |||
stderr) | ||||
op.pidfile = False | op.pidfile = False | |||
### Empty ansi and theme database if no colors are requested | ### Empty ansi and theme database if no colors are requested | |||
if not op.color: | if not op.color: | |||
for key in color.keys(): | for key in color: | |||
color[key] = '' | color[key] = '' | |||
for key in theme.keys(): | for key in theme: | |||
theme[key] = '' | theme[key] = '' | |||
for key in ansi: | ||||
ansi[key] = '' | ||||
theme['colors_hi'] = (ansi['default'],) | theme['colors_hi'] = (ansi['default'],) | |||
theme['colors_lo'] = (ansi['default'],) | theme['colors_lo'] = (ansi['default'],) | |||
# print color['blackbg'] | # print color['blackbg'] | |||
### Disable line-wrapping (does not work ?) | ||||
sys.stdout.write(ansi['nolinewrap']) | ||||
if not op.update: | if not op.update: | |||
interval = op.delay | interval = op.delay | |||
### Build list of requested plugins | ### Build list of requested plugins | |||
linewidth = 0 | linewidth = 0 | |||
totlist = [] | totlist = [] | |||
for plugin in op.plugins: | for plugin in op.plugins: | |||
### Set up fallback lists | ### Set up fallback lists | |||
if plugin == 'cpu': mods = ( 'cpu', 'cpu24' ) | if plugin == 'cpu': mods = ( 'cpu', 'cpu24' ) | |||
elif plugin == 'disk': mods = ( 'disk', 'disk24', 'disk24-old' ) | elif plugin == 'disk': mods = ( 'disk', 'disk24', 'disk24-old' ) | |||
elif plugin == 'int': mods = ( 'int', 'int24' ) | elif plugin == 'int': mods = ( 'int', 'int24' ) | |||
elif plugin == 'page': mods = ( 'page', 'page24' ) | elif plugin == 'page': mods = ( 'page', 'page24' ) | |||
elif plugin == 'swap': mods = ( 'swap', 'swap-old' ) | elif plugin == 'swap': mods = ( 'swap', 'swap-old' ) | |||
else: mods = ( plugin, ) | else: mods = ( plugin, ) | |||
for mod in mods: | for mod in mods: | |||
pluginfile = 'dstat_' + mod.replace('-', '_') | pluginfile = 'dstat_' + mod.replace('-', '_') | |||
try: | try: | |||
if pluginfile not in globals().keys(): | if pluginfile not in globals(): | |||
import imp | import imp | |||
fp, pathname, description = imp.find_module(pluginfile, plug inpath) | fp, pathname, description = imp.find_module(pluginfile, plug inpath) | |||
fp.close() | fp.close() | |||
### TODO: Would using .pyc help with anything ? | ### TODO: Would using .pyc help with anything ? | |||
### Try loading python plugin | ### Try loading python plugin | |||
if description[0] in ('.py', ): | if description[0] in ('.py', ): | |||
execfile(pathname) | exec(open(pathname).read()) | |||
exec 'o = dstat_plugin(); del(dstat_plugin)' | #execfile(pathname) | |||
o.filename = pluginfile | exec('global plug; plug = dstat_plugin(); del(dstat_plug | |||
o.check() | in)') | |||
o.prepare() | plug.filename = pluginfile | |||
plug.check() | ||||
plug.prepare() | ||||
### Try loading C plugin (not functional yet) | ### Try loading C plugin (not functional yet) | |||
elif description[0] == '.so': | elif description[0] == '.so': | |||
exec 'import %s' % pluginfile | exec('import %s; global plug; plug = %s.new()' % (plugin | |||
exec 'o = %s.new()' % pluginfile | file, pluginfile)) | |||
o.check() | plug.check() | |||
o.prepare() | plug.prepare() | |||
# print dir(o) | # print(dir(plug)) | |||
# print o.__module__ | # print(plug.__module__) | |||
# print o.name | # print(plug.name) | |||
else: | else: | |||
print >>sys.stderr, 'Module %s is of unknown type.' % pl uginfile | print('Module %s is of unknown type.' % pluginfile, file =sys.stderr) | |||
else: | else: | |||
exec 'o = %s()' % pluginfile | exec('global plug; plug = %s()' % pluginfile) | |||
o.check() | plug.check() | |||
o.prepare() | plug.prepare() | |||
# print o.__module__ | # print(plug.__module__) | |||
except Exception, e: | except Exception as e: | |||
if mod == mods[-1]: | if mod == mods[-1]: | |||
print >>sys.stderr, 'Module %s failed to load. (%s)' % (plug infile, e) | print('Module %s failed to load. (%s)' % (pluginfile, e), fi le=sys.stderr) | |||
elif op.debug: | elif op.debug: | |||
print >>sys.stderr, 'Module %s failed to load, trying anothe r. (%s)' % (pluginfile, e) | print('Module %s failed to load, trying another. (%s)' % (pl uginfile, e), file=sys.stderr) | |||
if op.debug >= 3: | if op.debug >= 3: | |||
raise | raise | |||
# tb = sys.exc_info()[2] | # tb = sys.exc_info()[2] | |||
continue | continue | |||
except: | except: | |||
print >>sys.stderr, 'Module %s caused unknown exception' % plugi nfile | print('Module %s caused unknown exception' % pluginfile, file=sy s.stderr) | |||
linewidth = linewidth + o.statwidth() + 1 | linewidth = linewidth + plug.statwidth() + 1 | |||
totlist.append(o) | totlist.append(plug) | |||
if op.debug: | if op.debug: | |||
print 'Module', pluginfile, | print('Module %s' % pluginfile, end='') | |||
if hasattr(o, 'file'): | if hasattr(plug, 'file'): | |||
print 'requires', o.file, | print(' requires %s' % plug.file, end='') | |||
print() | ||||
break | break | |||
if not totlist: | if not totlist: | |||
die(8, 'None of the stats you selected are available.') | die(8, 'None of the stats you selected are available.') | |||
if op.output: | if op.output: | |||
outputfile.write(csvheader(totlist)) | outputfile.write(csvheader(totlist)) | |||
scheduler = sched.scheduler(time.time, time.sleep) | scheduler = sched.scheduler(time.time, time.sleep) | |||
inittime = time.time() | inittime = time.time() | |||
skipping to change at line 2763 | skipping to change at line 2744 | |||
for o in totlist: | for o in totlist: | |||
newwidth = curwidth + o.statwidth() + 1 | newwidth = curwidth + o.statwidth() + 1 | |||
if newwidth <= cols or ( vislist == totlist[:-1] and newwidt h < cols ): | if newwidth <= cols or ( vislist == totlist[:-1] and newwidt h < cols ): | |||
vislist.append(o) | vislist.append(o) | |||
curwidth = newwidth | curwidth = newwidth | |||
### Check when to display the header | ### Check when to display the header | |||
if op.header and rows >= 6: | if op.header and rows >= 6: | |||
if oldvislist != vislist: | if oldvislist != vislist: | |||
showheader = True | showheader = True | |||
elif step == 1 and loop % (rows - 1) == 0: | elif not op.update and loop % (rows - 2) == 0: | |||
showheader = True | ||||
elif op.update and step == 1 and loop % (rows - 1) == 0: | ||||
showheader = True | showheader = True | |||
oldvislist = vislist | oldvislist = vislist | |||
else: | else: | |||
vislist = totlist | vislist = totlist | |||
### Prepare the colors for intermediate updates, last step in a loop is definitive | ### Prepare the colors for intermediate updates, last step in a loop is definitive | |||
if step == op.delay: | if step == op.delay: | |||
theme['default'] = ansi['reset'] | theme['default'] = ansi['reset'] | |||
else: | else: | |||
skipping to change at line 2787 | skipping to change at line 2770 | |||
newline = '' | newline = '' | |||
if op.update: | if op.update: | |||
if step == 1 and update != 0: | if step == 1 and update != 0: | |||
newline = '\n' + ansi['reset'] + ansi['clearline'] + ansi['save' ] | newline = '\n' + ansi['reset'] + ansi['clearline'] + ansi['save' ] | |||
elif loop != 0: | elif loop != 0: | |||
newline = ansi['restore'] | newline = ansi['restore'] | |||
### Display header | ### Display header | |||
if showheader: | if showheader: | |||
if loop == 0 and totlist != vislist: | if loop == 0 and totlist != vislist: | |||
print >>sys.stderr, 'Terminal width too small, trimming output.' | print('Terminal width too small, trimming output.', file=sys.std err) | |||
showheader = False | showheader = False | |||
sys.stdout.write(newline) | sys.stdout.write(newline) | |||
newline = header(totlist, vislist) | newline = header(totlist, vislist) | |||
### Calculate all objects (visible, invisible) | ### Calculate all objects (visible, invisible) | |||
line = newline | line = newline | |||
oline = '' | oline = '' | |||
for o in totlist: | for o in totlist: | |||
o.extract() | o.extract() | |||
if o in vislist: | if o in vislist: | |||
skipping to change at line 2842 | skipping to change at line 2825 | |||
initterm() | initterm() | |||
op = Options(os.getenv('DSTAT_OPTS','').split() + sys.argv[1:]) | op = Options(os.getenv('DSTAT_OPTS','').split() + sys.argv[1:]) | |||
theme = set_theme() | theme = set_theme() | |||
if op.profile: | if op.profile: | |||
import profile | import profile | |||
if os.path.exists(op.profile): | if os.path.exists(op.profile): | |||
os.remove(op.profile) | os.remove(op.profile) | |||
profile.run('main()', op.profile) | profile.run('main()', op.profile) | |||
else: | else: | |||
main() | main() | |||
except KeyboardInterrupt, e: | except KeyboardInterrupt as e: | |||
if op.update: | if op.update: | |||
sys.stdout.write('\n') | sys.stdout.write('\n') | |||
exit(0) | exit(0) | |||
else: | else: | |||
op = Options('') | op = Options('') | |||
step = 1 | step = 1 | |||
# vim:ts=4:sw=4:et | # vim:ts=4:sw=4:et | |||
End of changes. 189 change blocks. | ||||
290 lines changed or deleted | 275 lines changed or added |