[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r22952: {arm} added: config option for graph height fix: graph panel wasn' (in arm/trunk: . interface interface/graphing)



Author: atagar
Date: 2010-08-18 16:43:36 +0000 (Wed, 18 Aug 2010)
New Revision: 22952

Modified:
   arm/trunk/TODO
   arm/trunk/armrc.sample
   arm/trunk/interface/controller.py
   arm/trunk/interface/graphing/bandwidthStats.py
   arm/trunk/interface/graphing/graphPanel.py
   arm/trunk/interface/graphing/psStats.py
Log:
added: config option for graph height
fix: graph panel wasn't restricting bounds for sane config options
fix: off-by-one error with graphing bounds



Modified: arm/trunk/TODO
===================================================================
--- arm/trunk/TODO	2010-08-18 16:32:14 UTC (rev 22951)
+++ arm/trunk/TODO	2010-08-18 16:43:36 UTC (rev 22952)
@@ -144,6 +144,7 @@
       circuits at the exit
     * look at vidalia for ideas
     * need to solicit for ideas on what would be most helpful to clients
+  * interface option to change graph height
   * check if batch getInfo/getOption calls provide much performance benefit
   * layout (css) bugs with site
       Revise to use 'em' for measurements and somehow stretch image's y-margin?

Modified: arm/trunk/armrc.sample
===================================================================
--- arm/trunk/armrc.sample	2010-08-18 16:32:14 UTC (rev 22951)
+++ arm/trunk/armrc.sample	2010-08-18 16:43:36 UTC (rev 22952)
@@ -22,16 +22,19 @@
 features.log.prepopulateReadLimit 5000
 
 # general graph parameters
+# height:   height of graphed stats
+# maxWidth: maximum number of graphed entries
 # interval: 0 -> each second,  1 -> 5 seconds,  2 -> 30 seconds,
 #           3 -> minutely,     4 -> half hour,  5 -> hourly,      6 -> daily
 # bound:    0 -> global maxima,        1 -> local maxima, 2 -> tight
 # type:     0 -> None, 1 -> Bandwidth, 2 -> Connections,  3 -> System Resources
 # frequentRefrsh: updates stats each second if true, otherwise matches interval
 
+features.graph.height 5
+features.graph.maxWidth 150
 features.graph.interval 0
 features.graph.bound 1
 features.graph.type 1
-features.graph.maxSize 150
 features.graph.frequentRefresh true
 
 # ps graph parameters

Modified: arm/trunk/interface/controller.py
===================================================================
--- arm/trunk/interface/controller.py	2010-08-18 16:32:14 UTC (rev 22951)
+++ arm/trunk/interface/controller.py	2010-08-18 16:43:36 UTC (rev 22952)
@@ -307,7 +307,7 @@
   # loads config for various interface components
   config = conf.getConfig("arm")
   config.update(CONFIG)
-  config.update(graphing.graphPanel.CONFIG)
+  graphing.graphPanel.loadConfig(config)
   
   # adds events needed for arm functionality to the torTools REQ_EVENTS mapping
   # (they're then included with any setControllerEvents call, and log a more

Modified: arm/trunk/interface/graphing/bandwidthStats.py
===================================================================
--- arm/trunk/interface/graphing/bandwidthStats.py	2010-08-18 16:32:14 UTC (rev 22951)
+++ arm/trunk/interface/graphing/bandwidthStats.py	2010-08-18 16:43:36 UTC (rev 22952)
@@ -181,15 +181,18 @@
   def draw(self, panel, width, height):
     # if display is narrow, overwrites x-axis labels with avg / total stats
     if width <= COLLAPSE_WIDTH:
+      # line of the graph's x-axis labeling
+      labelingLine = self.getContentHeight() + panel.graphHeight - 5
+      
       # clears line
-      panel.addstr(8, 0, " " * width)
+      panel.addstr(labelingLine, 0, " " * width)
       graphCol = min((width - 10) / 2, self.maxCol)
       
       primaryFooter = "%s, %s" % (self._getAvgLabel(True), self._getTotalLabel(True))
       secondaryFooter = "%s, %s" % (self._getAvgLabel(False), self._getTotalLabel(False))
       
-      panel.addstr(8, 1, primaryFooter, uiTools.getColor(self.getColor(True)))
-      panel.addstr(8, graphCol + 6, secondaryFooter, uiTools.getColor(self.getColor(False)))
+      panel.addstr(labelingLine, 1, primaryFooter, uiTools.getColor(self.getColor(True)))
+      panel.addstr(labelingLine, graphCol + 6, secondaryFooter, uiTools.getColor(self.getColor(False)))
     
     # provides accounting stats if enabled
     if self.isAccounting:
@@ -203,21 +206,21 @@
           # failed to be queried
           status, hibernateColor = "unknown", "red"
         
-        panel.addfstr(10, 0, "<b>Accounting (<%s>%s</%s>)</b>" % (hibernateColor, status, hibernateColor))
+        panel.addfstr(labelingLine + 2, 0, "<b>Accounting (<%s>%s</%s>)</b>" % (hibernateColor, status, hibernateColor))
         
         resetTime = self.accountingInfo["resetTime"]
         if not resetTime: resetTime = "unknown"
-        panel.addstr(10, 35, "Time to reset: %s" % resetTime)
+        panel.addstr(labelingLine + 2, 35, "Time to reset: %s" % resetTime)
         
         used, total = self.accountingInfo["read"], self.accountingInfo["readLimit"]
         if used and total:
-          panel.addstr(11, 2, "%s / %s" % (used, total), uiTools.getColor(self.getColor(True)))
+          panel.addstr(labelingLine + 3, 2, "%s / %s" % (used, total), uiTools.getColor(self.getColor(True)))
         
         used, total = self.accountingInfo["written"], self.accountingInfo["writtenLimit"]
         if used and total:
-          panel.addstr(11, 37, "%s / %s" % (used, total), uiTools.getColor(self.getColor(False)))
+          panel.addstr(labelingLine + 3, 37, "%s / %s" % (used, total), uiTools.getColor(self.getColor(False)))
       else:
-        panel.addfstr(10, 0, "<b>Accounting:</b> Connection Closed...")
+        panel.addfstr(labelingLine + 2, 0, "<b>Accounting:</b> Connection Closed...")
   
   def getTitle(self, width):
     stats = list(self._titleStats)
@@ -258,8 +261,9 @@
   def getColor(self, isPrimary):
     return DL_COLOR if isPrimary else UL_COLOR
   
-  def getPreferredHeight(self):
-    return 13 if self.isAccounting else 10
+  def getContentHeight(self):
+    baseHeight = graphPanel.GraphStats.getContentHeight(self)
+    return baseHeight + 3 if self.isAccounting else baseHeight
   
   def new_desc_event(self, event):
     # updates self._titleStats with updated values

Modified: arm/trunk/interface/graphing/graphPanel.py
===================================================================
--- arm/trunk/interface/graphing/graphPanel.py	2010-08-18 16:32:14 UTC (rev 22951)
+++ arm/trunk/interface/graphing/graphPanel.py	2010-08-18 16:43:36 UTC (rev 22952)
@@ -27,7 +27,7 @@
                     ("minutely", 60),   ("15 minute", 900), ("30 minute", 1800),
                     ("hourly", 3600),   ("daily", 86400)]
 
-DEFAULT_HEIGHT = 10 # space needed for graph and content
+DEFAULT_CONTENT_HEIGHT = 4 # space needed for labeling above and below the graph
 DEFAULT_COLOR_PRIMARY, DEFAULT_COLOR_SECONDARY = "green", "cyan"
 
 # enums for graph bounds:
@@ -40,13 +40,14 @@
 WIDE_LABELING_GRAPH_COL = 50  # minimum graph columns to use wide spacing for x-axis labels
 
 # used for setting defaults when initializing GraphStats and GraphPanel instances
-CONFIG = {"features.graph.interval": 0, "features.graph.bound": 1, "features.graph.maxSize": 150, "features.graph.frequentRefresh": True}
+CONFIG = {"features.graph.height": 5, "features.graph.interval": 0, "features.graph.bound": 1, "features.graph.maxWidth": 150, "features.graph.frequentRefresh": True}
 
 def loadConfig(config):
   config.update(CONFIG)
-  CONFIG["features.graph.interval"] = max(len(UPDATE_INTERVALS) - 1, min(0, CONFIG["features.graph.interval"]))
-  CONFIG["features.graph.bound"] = max(2, min(0, CONFIG["features.graph.bound"]))
-  CONFIG["features.graph.maxSize"] = max(CONFIG["features.graph.maxSize"], 1)
+  CONFIG["features.graph.height"] = max(3, CONFIG["features.graph.height"])
+  CONFIG["features.graph.maxWidth"] = max(1, CONFIG["features.graph.maxWidth"])
+  CONFIG["features.graph.interval"] = min(len(UPDATE_INTERVALS) - 1, max(0, CONFIG["features.graph.interval"]))
+  CONFIG["features.graph.bound"] = min(2, max(0, CONFIG["features.graph.bound"]))
 
 class GraphStats(TorCtl.PostEventListener):
   """
@@ -76,7 +77,7 @@
     self.primaryTotal, self.secondaryTotal = 0, 0 # sum of all stats seen
     
     # timescale dependent stats
-    self.maxCol = CONFIG["features.graph.maxSize"]
+    self.maxCol = CONFIG["features.graph.maxWidth"]
     self.maxPrimary, self.maxSecondary = {}, {}
     self.primaryCounts, self.secondaryCounts = {}, {}
     
@@ -133,14 +134,20 @@
     
     return DEFAULT_COLOR_PRIMARY if isPrimary else DEFAULT_COLOR_SECONDARY
   
-  def getPreferredHeight(self):
+  def getContentHeight(self):
     """
-    Provides the height content should take up. By default this provides the
-    space needed for the default graph and content.
+    Provides the height content should take up (not including the graph).
     """
     
-    return DEFAULT_HEIGHT
+    return DEFAULT_CONTENT_HEIGHT
   
+  def isVisible(self):
+    """
+    True if the stat has content to present, false if it should be hidden.
+    """
+    
+    return True
+  
   def draw(self, panel, width, height):
     """
     Allows for any custom drawing monitor wishes to append.
@@ -231,6 +238,7 @@
     panel.Panel.__init__(self, stdscr, "graph", 0)
     self.updateInterval = CONFIG["features.graph.interval"]
     self.bounds = CONFIG["features.graph.bound"]
+    self.graphHeight = CONFIG["features.graph.height"]
     self.currentDisplay = None    # label of the stats currently being displayed
     self.stats = {}               # available stats (mappings of label -> instance)
     self.showLabel = True         # shows top label if true, hides otherwise
@@ -242,8 +250,8 @@
     if hidden).
     """
     
-    if self.currentDisplay:
-      return self.stats[self.currentDisplay].getPreferredHeight()
+    if self.currentDisplay and self.stats[self.currentDisplay].isVisible():
+      return self.stats[self.currentDisplay].getContentHeight() + self.graphHeight
     else: return 0
   
   def draw(self, subwindow, width, height):
@@ -288,20 +296,20 @@
       
       # displays bound
       self.addstr(2, 0, "%4i" % primaryMaxBound, primaryColor)
-      self.addstr(7, 0, "%4i" % primaryMinBound, primaryColor)
+      self.addstr(self.graphHeight + 1, 0, "%4i" % primaryMinBound, primaryColor)
       
       self.addstr(2, graphCol + 5, "%4i" % secondaryMaxBound, secondaryColor)
-      self.addstr(7, graphCol + 5, "%4i" % secondaryMinBound, secondaryColor)
+      self.addstr(self.graphHeight + 1, graphCol + 5, "%4i" % secondaryMinBound, secondaryColor)
       
       # creates bar graph (both primary and secondary)
       for col in range(graphCol):
         colCount = param.primaryCounts[self.updateInterval][col + 1] - primaryMinBound
-        colHeight = min(5, 5 * colCount / (max(1, primaryMaxBound) - primaryMinBound))
-        for row in range(colHeight): self.addstr(7 - row, col + 5, " ", curses.A_STANDOUT | primaryColor)
+        colHeight = min(self.graphHeight, self.graphHeight * colCount / (max(1, primaryMaxBound) - primaryMinBound))
+        for row in range(colHeight): self.addstr(self.graphHeight + 1 - row, col + 5, " ", curses.A_STANDOUT | primaryColor)
         
         colCount = param.secondaryCounts[self.updateInterval][col + 1] - secondaryMinBound
-        colHeight = min(5, 5 * colCount / (max(1, secondaryMaxBound) - secondaryMinBound))
-        for row in range(colHeight): self.addstr(7 - row, col + graphCol + 10, " ", curses.A_STANDOUT | secondaryColor)
+        colHeight = min(self.graphHeight, self.graphHeight * colCount / (max(1, secondaryMaxBound) - secondaryMinBound))
+        for row in range(colHeight): self.addstr(self.graphHeight + 1 - row, col + graphCol + 10, " ", curses.A_STANDOUT | secondaryColor)
       
       # bottom labeling of x-axis
       intervalSec = 1 # seconds per labeling
@@ -323,8 +331,8 @@
           # if constrained on space then strips labeling since already provided
           timeLabel = timeLabel[:-1]
         
-        self.addstr(8, 4 + loc, timeLabel, primaryColor)
-        self.addstr(8, graphCol + 10 + loc, timeLabel, secondaryColor)
+        self.addstr(self.graphHeight + 2, 4 + loc, timeLabel, primaryColor)
+        self.addstr(self.graphHeight + 2, graphCol + 10 + loc, timeLabel, secondaryColor)
         
       param.draw(self, width, height) # allows current stats to modify the display
   

Modified: arm/trunk/interface/graphing/psStats.py
===================================================================
--- arm/trunk/interface/graphing/psStats.py	2010-08-18 16:32:14 UTC (rev 22951)
+++ arm/trunk/interface/graphing/psStats.py	2010-08-18 16:43:36 UTC (rev 22952)
@@ -66,12 +66,14 @@
       statLabel = statName[0].upper() + statName[1:]
       return "%s (%s, avg: %s):" % (statLabel, lastAmount, avg)
   
-  def getPreferredHeight(self):
-    # hides graph if there's nothing to display (provides default otherwise)
-    # provides default height unless there's nothing to 
+  def isVisible(self):
+    """
+    Hides graph if unable to fetch stats.
+    """
+    
     if self.queryPid and self.queryParam and self.failedCount < FAILURE_THRESHOLD:
-      return graphPanel.DEFAULT_HEIGHT
-    else: return 0
+      return graphPanel.GraphStats.isVisible(self)
+    else: return False
   
   def eventTick(self):
     """