Commit 0c794dce authored by Stefan Raspl's avatar Stefan Raspl Committed by Paolo Bonzini

tools/kvm_stat: add command line switch '-c' to log in csv format

Add an alternative format that can be more easily used for further
processing later on.
Note that we add a timestamp in the first column for both, the regular
and the new csv format.
Signed-off-by: default avatarStefan Raspl <raspl@linux.ibm.com>
Message-Id: <20200306114250.57585-5-raspl@linux.ibm.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 3cbb394d
...@@ -33,6 +33,8 @@ import struct ...@@ -33,6 +33,8 @@ import struct
import re import re
import subprocess import subprocess
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from functools import reduce
from datetime import datetime
VMX_EXIT_REASONS = { VMX_EXIT_REASONS = {
'EXCEPTION_NMI': 0, 'EXCEPTION_NMI': 0,
...@@ -1489,28 +1491,49 @@ def batch(stats): ...@@ -1489,28 +1491,49 @@ def batch(stats):
pass pass
def log(stats, opts): class StdFormat(object):
"""Prints statistics as reiterating key block, multiple value blocks.""" def __init__(self, keys):
keys = sorted(stats.get().keys()) self._banner = ''
def banner():
for key in keys: for key in keys:
print(key.split(' ')[0], end=' ') self._banner += key.split(' ')[0] + ' '
print()
def statline(): def get_banner(self):
s = stats.get() return self._banner
@staticmethod
def get_statline(keys, s):
res = ''
for key in keys: for key in keys:
print(' %9d' % s[key].delta, end=' ') res += ' %9d' % s[key].delta
print() return res
class CSVFormat(object):
def __init__(self, keys):
self._banner = 'timestamp'
self._banner += reduce(lambda res, key: "{},{!s}".format(res,
key.split(' ')[0]), keys, '')
def get_banner(self):
return self._banner
@staticmethod
def get_statline(keys, s):
return reduce(lambda res, key: "{},{!s}".format(res, s[key].delta),
keys, '')
def log(stats, opts, frmt, keys):
"""Prints statistics as reiterating key block, multiple value blocks."""
line = 0 line = 0
banner_repeat = 20 banner_repeat = 20
while True: while True:
try: try:
time.sleep(opts.set_delay) time.sleep(opts.set_delay)
if line % banner_repeat == 0: if line % banner_repeat == 0:
banner() print(frmt.get_banner())
statline() print(datetime.now().strftime("%Y-%m-%d %H:%M:%S") +
frmt.get_statline(keys, stats.get()))
line += 1 line += 1
except KeyboardInterrupt: except KeyboardInterrupt:
break break
...@@ -1584,6 +1607,11 @@ Press any other key to refresh statistics immediately. ...@@ -1584,6 +1607,11 @@ Press any other key to refresh statistics immediately.
default=False, default=False,
help='run in batch mode for one second', help='run in batch mode for one second',
) )
argparser.add_argument('-c', '--csv',
action='store_true',
default=False,
help='log in csv format - requires option -l/--log',
)
argparser.add_argument('-d', '--debugfs', argparser.add_argument('-d', '--debugfs',
action='store_true', action='store_true',
default=False, default=False,
...@@ -1628,6 +1656,8 @@ Press any other key to refresh statistics immediately. ...@@ -1628,6 +1656,8 @@ Press any other key to refresh statistics immediately.
help='retrieve statistics from tracepoints', help='retrieve statistics from tracepoints',
) )
options = argparser.parse_args() options = argparser.parse_args()
if options.csv and not options.log:
sys.exit('Error: Option -c/--csv requires -l/--log')
try: try:
# verify that we were passed a valid regex up front # verify that we were passed a valid regex up front
re.compile(options.fields) re.compile(options.fields)
...@@ -1708,7 +1738,12 @@ def main(): ...@@ -1708,7 +1738,12 @@ def main():
sys.exit(0) sys.exit(0)
if options.log: if options.log:
log(stats, options) keys = sorted(stats.get().keys())
if options.csv:
frmt = CSVFormat(keys)
else:
frmt = StdFormat(keys)
log(stats, options, frmt, keys)
elif not options.once: elif not options.once:
with Tui(stats, options) as tui: with Tui(stats, options) as tui:
tui.show_stats() tui.show_stats()
......
...@@ -64,6 +64,10 @@ OPTIONS ...@@ -64,6 +64,10 @@ OPTIONS
--batch:: --batch::
run in batch mode for one second run in batch mode for one second
-c::
--csv=<file>::
log in csv format - requires option -l/--log
-d:: -d::
--debugfs:: --debugfs::
retrieve statistics from debugfs retrieve statistics from debugfs
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment