public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "André Erdmann" <dywi@mailerd.de>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/R_overlay:master commit in: roverlay/stats/
Date: Mon, 29 Jul 2013 08:55:52 +0000 (UTC)	[thread overview]
Message-ID: <1375088075.55537b3dd0f8f1624f882af50f5dc9ea0de65678.dywi@gentoo> (raw)

commit:     55537b3dd0f8f1624f882af50f5dc9ea0de65678
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Mon Jul 29 08:54:35 2013 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Mon Jul 29 08:54:35 2013 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=55537b3d

visualize stats (formatted str output)

---
 roverlay/stats/abstract.py  |  68 +++++++++++++++++++++-
 roverlay/stats/collector.py | 137 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 204 insertions(+), 1 deletion(-)

diff --git a/roverlay/stats/abstract.py b/roverlay/stats/abstract.py
index 36c81ca..6d0575a 100644
--- a/roverlay/stats/abstract.py
+++ b/roverlay/stats/abstract.py
@@ -18,6 +18,26 @@ class MethodNotImplemented ( NotImplementedError ):
 
 # --- end of MethodNotImplemented ---
 
+class StatsVisualizer ( object ):
+
+   def __init__ ( self, stats ):
+      super ( StatsVisualizer, self ).__init__()
+      self.stats = stats
+      self.lines = None
+
+      self.prepare()
+   # --- end of __init__ (...) ---
+
+   def prepare ( self ):
+      raise MethodNotImplemented ( self, 'prepare' )
+   # --- end of prepare (...) ---
+
+   def __str__ ( self ):
+      return '\n'.join ( self.lines )
+   # --- end of __str__ (...) ---
+
+# --- end of StatsVisualizer ---
+
 
 class RoverlayStatsBase ( object ):
 
@@ -60,6 +80,15 @@ class RoverlayStatsBase ( object ):
             yield getattr ( self, member )
    # --- end of _iter_members (...) ---
 
+   def has_nonzero ( self ):
+      if hasattr ( self, '_MEMBERS' ):
+         for member in self._iter_members():
+            if int ( member ) != 0:
+               return member
+      else:
+         raise MethodNotImplemented ( self, 'has_nonzero' )
+   # --- end of has_nonzero (...) ---
+
    def reset_members ( self ):
       for member in self._iter_members():
          member.reset()
@@ -166,9 +195,29 @@ class TimeStats ( RoverlayStats ):
    # --- end of end (...) ---
 
    def get_total ( self ):
-      return sum ( v.get_delta() for v in self._timestats.values() )
+      return float (
+         sum ( filter (
+            lambda k: k > 0.0,
+            ( v.get_delta() for v in self._timestats.values() )
+         ) )
+      )
    # --- end of get_total (...) ---
 
+   def get_total_str ( self,
+      unknown_threshold=0.00001, ms_threshold=1.0, min_threshold=300.0,
+      unknown_return=None
+   ):
+      t = self.get_total()
+      if t < unknown_threshold:
+         return unknown_return
+      elif t < ms_threshold:
+         return "{:.2f} ms".format ( t * 1000 )
+      elif t > min_threshold:
+         return "{:.2f} minutes".format ( t / 60.0 )
+      else:
+         return "{:.2f} seconds".format ( t )
+   # --- end of get_total_str (...) ---
+
    def gen_str ( self ):
       desc = self.get_description_str()
       if desc:
@@ -211,6 +260,10 @@ class Counter ( RoverlayStatsBase ):
       return self.total_count - int ( other )
    # --- end of __sub__ (...) ---
 
+   def has_details ( self ):
+      return False
+   # --- end of has_details (...) ---
+
    def reset ( self ):
       self.total_count = 0
       self.underflow   = False
@@ -256,6 +309,14 @@ class DetailedCounter ( Counter ):
       self._detailed_count = collections.defaultdict ( int )
    # --- end of __init__ (...) ---
 
+   def has_details ( self ):
+      return any ( int(v) != 0 for v in self._detailed_count.values() )
+   # --- end of has_details (...) ---
+
+   def iter_details ( self ):
+      return ( kv for kv in self._detailed_count.items() if int(kv[1]) != 0 )
+   # --- end of iter_details (...) ---
+
    def __getitem__ ( self, key ):
       if key in self._detailed_count:
          return self._detailed_count [key]
@@ -350,6 +411,11 @@ class SuccessRatio ( object ):
          return float ( self.ebuild_count ) / float ( self.pkg_count )
    # --- end of get_ratio (...) ---
 
+   @property
+   def ratio ( self ):
+      return self.get_ratio()
+   # --- end of ratio (...) ---
+
    def __float__ ( self ):
       return self.get_ratio()
    # --- end of __float__ (...) ---

diff --git a/roverlay/stats/collector.py b/roverlay/stats/collector.py
index 1b122f4..3e3dee7 100644
--- a/roverlay/stats/collector.py
+++ b/roverlay/stats/collector.py
@@ -4,6 +4,8 @@
 # Distributed under the terms of the GNU General Public License;
 # either version 2 of the License, or (at your option) any later version.
 
+import collections
+
 from . import abstract
 from . import base
 
@@ -48,6 +50,12 @@ class StatsCollector ( abstract.RoverlayStatsBase ):
       )
    # --- end of get_overall_success_ratio (...) ---
 
+   def get_net_gain ( self ):
+      return (
+         self.overlay.ebuild_count - self.overlay.ebuilds_scanned
+      )
+   # --- end of get_net_gain (...) ---
+
    def __init__ ( self ):
       self.time             = abstract.TimeStats ( "misc time stats" )
       self.distmap          = base.DistmapStats()
@@ -68,8 +76,137 @@ class StatsCollector ( abstract.RoverlayStatsBase ):
          yield ""
    # --- end of gen_str (...) ---
 
+   def get_creation_str ( self ):
+      return str ( CreationStatsVisualizer ( self ) )
+   # --- end of to_creation_str (...) ---
 
 # --- end of StatsCollector ---
 
+
+class CreationStatsVisualizer ( abstract.StatsVisualizer ):
+
+   def prepare ( self ):
+      EMPTY_LINE = ""
+
+      pkg_count    = self.stats.repo.pkg_count
+      pkg_queued   = self.stats.overlay_creation.pkg_queued
+      pkg_fail     = self.stats.overlay_creation.pkg_fail
+      pkg_success  = self.stats.overlay_creation.pkg_success
+      ebuild_delta = self.stats.get_net_gain()
+      revbumps     = self.stats.overlay.revbump_count
+
+      max_number_len = min (
+         len ( str ( int ( k ) ) ) for k in (
+            pkg_queued, pkg_fail, pkg_success
+         )
+      )
+      max_number_len = min ( 5, max_number_len )
+
+      success_ratio         = self.stats.get_success_ratio()
+      overall_success_ratio = self.stats.get_overall_success_ratio()
+
+
+      timestats = (
+         ( 'scan_overlay', self.stats.overlay.scan_time.get_total_str() ),
+         ( 'add_packages', self.stats.repo.queue_time.get_total_str() ),
+         (
+            'ebuild_creation',
+            self.stats.overlay_creation.creation_time.get_total_str()
+         ),
+         ( 'write_overlay',  self.stats.overlay.write_time.get_total_str() ),
+      )
+
+      try:
+         max_time_len = max ( len(k) for k, v in timestats if v is not None )
+      except ValueError:
+         # empty sequence -> no timestats
+         max_time_len = -1
+      else:
+         # necessary?
+         max_time_len = min ( 39, max_time_len )
+
+
+      # create lines
+      lines   = collections.deque()
+      unshift = lines.appendleft
+      append  = lines.append
+
+      numstats = lambda k, s: "{num:<{l}d} {s}".format (
+         num=int ( k ), s=s, l=max_number_len
+      )
+
+
+      append (
+         'success ratio {s_i:.2%} (overall {s_o:.2%})'.format (
+            s_i = success_ratio.get_ratio(),
+            s_o = overall_success_ratio.get_ratio()
+         )
+      )
+      append ( EMPTY_LINE )
+
+      append (
+         "{e:+d} ebuilds ({r:d} revbumps)".format (
+            e=ebuild_delta, r=int ( revbumps )
+         )
+      )
+      append ( EMPTY_LINE )
+
+      if int ( pkg_count ) != int ( pkg_queued ):
+         append ( numstats (
+            pkg_queued,
+            '/ {n:d} packages added to the ebuild creation queue'.format (
+               n=int ( pkg_count )
+            )
+         ) )
+      else:
+         append ( numstats (
+            pkg_queued, 'packages added to the ebuild creation queue'
+         ) )
+
+      append ( numstats (
+         pkg_success, 'packages passed ebuild creation'
+      ) )
+
+      append ( numstats (
+         pkg_fail, 'packages failed ebuild creation'
+      ) )
+
+      if pkg_fail.has_details() and int ( pkg_fail ) != 0:
+         append ( EMPTY_LINE )
+         append ( "Details for ebuild creation failure:" )
+         details = sorted (
+            ( ( k, int(v) ) for k, v in pkg_fail.iter_details() ),
+            key=lambda kv: kv[1]
+         )
+         dlen = len ( str ( max ( details, key=lambda kv: kv[1] ) [1] ) )
+
+         for key, value in details:
+            append ( "* {v:>{l}d}: {k}".format ( k=key, v=value, l=dlen ) )
+      # -- end if <have pkg_fail details>
+
+      if max_time_len > 0:
+         # or >= 0
+         append ( EMPTY_LINE )
+         for k, v in timestats:
+            if v is not None:
+               append (
+                  "time for {0:<{l}} : {1}".format ( k, v, l=max_time_len )
+               )
+      # -- end if timestats
+
+
+      append ( EMPTY_LINE )
+
+      # add header/footer line(s)
+      max_line_len = 2 + min ( 78, max ( len(s) for s in lines ) )
+      unshift (
+         "{0:-^{1}}\n".format ( " Overlay creation stats ", max_line_len )
+      )
+      append ( max_line_len * '-' )
+
+      self.lines = lines
+   # --- end of gen_str (...) ---
+# --- end of CreationStatsVisualizer ---
+
 static = StatsCollector()
 StatsCollector._instance = static


             reply	other threads:[~2013-07-29  8:55 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-29  8:55 André Erdmann [this message]
  -- strict thread matches above, loose matches on Subject: below --
2014-02-21 17:36 [gentoo-commits] proj/R_overlay:master commit in: roverlay/stats/ André Erdmann
2013-09-05 10:24 André Erdmann
2013-09-05  9:25 André Erdmann
2013-09-05  9:25 André Erdmann
2013-08-16 12:42 André Erdmann
2013-08-16 10:43 André Erdmann
2013-08-15  9:18 André Erdmann
2013-08-02 10:34 André Erdmann
2013-07-29 14:56 André Erdmann
2013-07-26 13:02 André Erdmann
2013-07-25 15:20 André Erdmann
2013-07-25 14:28 André Erdmann
2013-07-24 16:52 André Erdmann

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=1375088075.55537b3dd0f8f1624f882af50f5dc9ea0de65678.dywi@gentoo \
    --to=dywi@mailerd.de \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /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