public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Stefan Raspl <raspl@linux.ibm.com>
To: kvm@vger.kernel.org
Cc: rkrcmar@redhat.com, pbonzini@redhat.com
Subject: [PATCH 6/7] tools/kvm_stat: add command line switch '-T'
Date: Fri,  6 Mar 2020 12:42:49 +0100	[thread overview]
Message-ID: <20200306114250.57585-7-raspl@linux.ibm.com> (raw)
In-Reply-To: <20200306114250.57585-1-raspl@linux.ibm.com>

From: Stefan Raspl <raspl@de.ibm.com>

Allow to specify logfile size using a timeframe as specified by option
'-T'. Since .csv files have varying record lengths, the estimate might be
off, especially in case only a subset of (pathological) fields is chosen
via '-f'. But we try to over- rather than understimate the required space
to make up for it.

Signed-off-by: Stefan Raspl <raspl@linux.ibm.com>
---
 tools/kvm/kvm_stat/kvm_stat     | 73 ++++++++++++++++++++++++++++++++-
 tools/kvm/kvm_stat/kvm_stat.txt |  6 +++
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat
index 2275ab1b070b..d402ef97bf10 100755
--- a/tools/kvm/kvm_stat/kvm_stat
+++ b/tools/kvm/kvm_stat/kvm_stat
@@ -1509,6 +1509,10 @@ class StdFormat(object):
             res += ' %9d' % s[key].delta
         return res
 
+    def get_statline_len(self, keys, stats):
+        # Note: 19 chars for timestamp plus one for linefeed
+        return 20 + len(self.get_statline(keys, stats.get()))
+
 
 class CSVFormat(object):
     def __init__(self, keys):
@@ -1524,6 +1528,12 @@ class CSVFormat(object):
         return reduce(lambda res, key: "{},{!s}".format(res, s[key].delta),
                       keys, '')
 
+    def get_statline_len(self, keys, stats):
+        # csv statlines are of variable length - need to
+        # apply horrible heuristics to get a projection
+        # Note: 19 chars for timestamp plus one for linefeed
+        return 20 + len(keys) * 5
+
 
 def log(stats, opts, frmt, keys):
     """Prints statistics as reiterating key block, multiple value blocks."""
@@ -1543,6 +1553,14 @@ def log(stats, opts, frmt, keys):
 
 def rotating_log(stats, opts, frmt, keys):
     """Prints statistics to file in csv format."""
+    def convert_to_si(val):
+        if val / 1000000000000. > 1:
+            return "%.2fTB" % (val / 1000000000000.)
+        elif val / 1000000000. > 1:
+            return "%.2fGB" % (val / 1000000000.)
+        else:
+            return "%.2fMB" % (val / 1000000.)
+
     def init(opts, frmt):
         # Regular RotatingFileHandler doesn't add a header to each file,
         # so we create our own version
@@ -1580,6 +1598,18 @@ def rotating_log(stats, opts, frmt, keys):
         except:
             sys.exit("Error setting up csv log with file '%s'"
                      % opts.rotating_log)
+
+        def determine_logsize(opts, keys, stats):
+            if opts.time_frame != '':
+                opts.size = LOGCOUNT_DEFAULT * (len(frmt.get_banner()) + 1) + \
+                            opts.time_frame / opts.set_delay * \
+                            frmt.get_statline_len(keys, stats)
+                # Account for the current file being reset when we roll over
+                opts.size = opts.size / (LOGCOUNT_DEFAULT-1) * LOGCOUNT_DEFAULT
+                print("Estimated required total logfile size: %s" %
+                      convert_to_si(opts.size))
+
+        determine_logsize(opts, keys, stats)
         formatter = MyFormatter('%(asctime)s%(message)s', '%Y-%m-%d %H:%M:%S')
         hdl.setFormatter(formatter)
 
@@ -1645,6 +1675,32 @@ Press any other key to refresh statistics immediately.
 """ % (PATH_DEBUGFS_KVM, PATH_DEBUGFS_TRACING)
 
     def convert_from_si(opts):
+        if opts.time_frame != '':
+            try:
+                    num = int(opts.time_frame.rstrip(string.ascii_letters))
+                    unit = opts.time_frame.lstrip(string.digits)
+            except ValueError:
+                sys.exit("Error: Invalid argument to -T/--time-frame: '%s'"
+                         % opts.size)
+            if num <= 0:
+                sys.exit("Error: Argument to -S/--size must be >0")
+            factor = 3600
+            if unit != '':
+                if unit in ['h', 'H']:
+                    factor = 3600
+                elif unit in ['d', 'D']:
+                    factor = 24*3600
+                elif unit in ['w', 'W']:
+                    factor = 7*24*3600
+                elif unit in ['m', 'M']:
+                    factor = 30*24*3600
+                elif unit in ['y', 'Y']:
+                    factor = 365*24*3600
+                else:
+                    sys.exit("Error: Unsupported unit suffix '%s' for "
+                             "-T/--time-frame" % unit)
+            opts.time_frame = int(num * factor)
+
         try:
             factor = 1000000
             num = int(opts.size.rstrip(string.ascii_letters))
@@ -1749,6 +1805,13 @@ default: %s''' % SIZE_DEFAULT,
                            default=False,
                            help='retrieve statistics from tracepoints',
                            )
+    argparser.add_argument('-T', '--time-frame',
+                           type=str,
+                           default='',
+                           help='''determine total logfile size by minimum \
+time it should hold
+supported suffixes: hdwmy (hours (default), days, weeks, months, years)''',
+                           )
     options = argparser.parse_args()
     if options.csv and not options.log and not options.rotating_log:
         sys.exit('Error: Option -c/--csv requires one of -l/--log or '
@@ -1756,9 +1819,17 @@ default: %s''' % SIZE_DEFAULT,
     if options.rotating_log:
         if options.log:
             sys.exit('Error: Cannot mix -l/--log and -r/--rotating-log')
-        if not options.size:
+        if options.size:
+            if options.time_frame:
+                sys.exit('Error: Cannot specify -S/--size and -T/--time-frame '
+                         'together')
+        else:
             options.size = SIZE_DEFAULT
         convert_from_si(options)
+    else:
+        if options.size or options.time_frame:
+            sys.exit('Error: Options -S/--size and -T/--time-frame only valid '
+                     'with -r/--rotating-log')
     try:
         # verify that we were passed a valid regex up front
         re.compile(options.fields)
diff --git a/tools/kvm/kvm_stat/kvm_stat.txt b/tools/kvm/kvm_stat/kvm_stat.txt
index 35df0b1261a2..2531c3bf56eb 100644
--- a/tools/kvm/kvm_stat/kvm_stat.txt
+++ b/tools/kvm/kvm_stat/kvm_stat.txt
@@ -115,6 +115,12 @@ OPTIONS
 --tracepoints::
         retrieve statistics from tracepoints
 
+-T::
+--time-frame::
+        determine total logfile size by minimum time it should hold.
+            Supported suffixes: hd (hours (default), days, weeks, months,
+            years). Might be inaccurate for .csv format.
+
 SEE ALSO
 --------
 'perf'(1), 'trace-cmd'(1)
-- 
2.17.1


  parent reply	other threads:[~2020-03-06 11:43 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-06 11:42 [PATCH 0/7] tools/kvm_stat: add logfile support Stefan Raspl
2020-03-06 11:42 ` [PATCH 1/7] tools/kvm_stat: rework command line sequence and message texts Stefan Raspl
2020-03-06 11:42 ` [PATCH 2/7] tools/kvm_stat: switch to argparse Stefan Raspl
2020-03-06 11:42 ` [PATCH 3/7] tools/kvm_stat: add command line switch '-s' to set update interval Stefan Raspl
2020-03-06 11:42 ` [PATCH 4/7] tools/kvm_stat: add command line switch '-c' to log in csv format Stefan Raspl
2020-03-06 11:42 ` [PATCH 5/7] tools/kvm_stat: add rotating log support Stefan Raspl
2020-03-06 11:42 ` Stefan Raspl [this message]
2020-03-06 11:42 ` [PATCH 7/7] tools/kvm_stat: add sample systemd unit file Stefan Raspl
2020-03-29 11:22   ` Stefan Raspl
2020-03-19 11:21 ` [PATCH 0/7] tools/kvm_stat: add logfile support Stefan Raspl
2020-03-19 11:54 ` Paolo Bonzini
2020-03-23  9:58   ` Stefan Raspl
2020-03-23 10:12     ` Paolo Bonzini
2020-03-24  8:26       ` Stefan Raspl
2020-03-24 10:32         ` Paolo Bonzini
2020-03-29 11:22           ` Stefan Raspl
2020-03-30 10:43             ` Paolo Bonzini
2020-03-30 12:24               ` Stefan Raspl
2020-03-30 12:35                 ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200306114250.57585-7-raspl@linux.ibm.com \
    --to=raspl@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=rkrcmar@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox