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

[tor-commits] [arm/master] Rewriting bandwidth stat's accounting handling



commit f2481e63e9cd79c017fa4a245e5e0f2ebfa61535
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date:   Sun Sep 14 15:10:12 2014 -0700

    Rewriting bandwidth stat's accounting handling
    
    Taking advantage of stem's new get_accounting_stats() method, and overhauling
    how we render accounting information. We had three instance variables for this
    which was kinda silly.
---
 arm/config/attributes.cfg       |    3 +
 arm/graphing/bandwidth_stats.py |  119 +++++++--------------------------------
 armrc.sample                    |    3 -
 3 files changed, 22 insertions(+), 103 deletions(-)

diff --git a/arm/config/attributes.cfg b/arm/config/attributes.cfg
index 340cbdc..6f1fea5 100644
--- a/arm/config/attributes.cfg
+++ b/arm/config/attributes.cfg
@@ -23,3 +23,6 @@ attr.version_status_colors old => red
 attr.version_status_colors unrecommended => red
 attr.version_status_colors unknown => cyan
 
+attr.hibernate_color awake => green
+attr.hibernate_color soft => yellow
+attr.hibernate_color hard => red
diff --git a/arm/graphing/bandwidth_stats.py b/arm/graphing/bandwidth_stats.py
index 8dcf203..4fc01c6 100644
--- a/arm/graphing/bandwidth_stats.py
+++ b/arm/graphing/bandwidth_stats.py
@@ -3,7 +3,6 @@ Tracks bandwidth usage of the tor process, expanding to include accounting
 stats if they're set.
 """
 
-import calendar
 import time
 import curses
 
@@ -22,10 +21,10 @@ def conf_handler(key, value):
 
 
 CONFIG = conf.config_dict('arm', {
+  'attr.hibernate_color': {},
   'features.graph.bw.transferInBytes': False,
   'features.graph.bw.accounting.show': True,
   'features.graph.bw.accounting.rate': 10,
-  'features.graph.bw.accounting.isTimeLong': False,
   'tor.chroot': '',
 }, conf_handler)
 
@@ -36,10 +35,6 @@ DL_COLOR, UL_COLOR = 'green', 'cyan'
 
 COLLAPSE_WIDTH = 135
 
-# valid keys for the accounting_info mapping
-
-ACCOUNTING_ARGS = ('status', 'reset_time', 'read', 'written', 'read_limit', 'writtenLimit')
-
 
 class BandwidthStats(graph_panel.GraphStats):
   """
@@ -55,16 +50,13 @@ class BandwidthStats(graph_panel.GraphStats):
     self.prepopulate_secondary_total = 0
     self.prepopulate_ticks = 0
 
-    # accounting data (set by _update_accounting_info method)
-
-    self.accounting_last_updated = 0
-    self.accounting_info = dict([(arg, '') for arg in ACCOUNTING_ARGS])
+    self.accounting_stats = None
 
     # listens for tor reload (sighup) events which can reset the bandwidth
     # rate/burst and if tor's using accounting
 
     controller = tor_controller()
-    self._title_stats, self.is_accounting = [], False
+    self._title_stats = []
 
     if not is_pause_buffer:
       self.reset_listener(controller, State.INIT, None)  # initializes values
@@ -95,12 +87,10 @@ class BandwidthStats(graph_panel.GraphStats):
     if not new_copy:
       new_copy = BandwidthStats(True)
 
-    new_copy.accounting_last_updated = self.accounting_last_updated
-    new_copy.accounting_info = self.accounting_info
+    new_copy.accounting_stats = self.accounting_stats
 
     # attributes that would have been initialized from calling the reset_listener
 
-    new_copy.is_accounting = self.is_accounting
     new_copy._title_stats = self._title_stats
 
     return graph_panel.GraphStats.clone(self, new_copy)
@@ -114,8 +104,8 @@ class BandwidthStats(graph_panel.GraphStats):
     if event_type in (State.INIT, State.RESET) and CONFIG['features.graph.bw.accounting.show']:
       is_accounting_enabled = controller.get_info('accounting/enabled', None) == '1'
 
-      if is_accounting_enabled != self.is_accounting:
-        self.is_accounting = is_accounting_enabled
+      if is_accounting_enabled != bool(self.accounting_stats):
+        self.accounting_stats = tor_controller().get_accounting_stats(None)
 
         # redraws the whole screen since our height changed
 
@@ -183,9 +173,9 @@ class BandwidthStats(graph_panel.GraphStats):
     return time.time() - min(stats.last_read_time, stats.last_write_time)
 
   def bandwidth_event(self, event):
-    if self.is_accounting and self.is_next_tick_redraw():
-      if time.time() - self.accounting_last_updated >= CONFIG['features.graph.bw.accounting.rate']:
-        self._update_accounting_info()
+    if self.accounting_stats and self.is_next_tick_redraw():
+      if time.time() - self.accounting_stats.retrieved >= CONFIG['features.graph.bw.accounting.rate']:
+        self.accounting_stats = tor_controller().get_accounting_stats(None)
 
     # scales units from B to KB for graphing
 
@@ -212,40 +202,19 @@ class BandwidthStats(graph_panel.GraphStats):
 
     # provides accounting stats if enabled
 
-    if self.is_accounting:
+    if self.accounting_stats:
       if tor_controller().is_alive():
-        status = self.accounting_info['status']
-
-        hibernate_color = 'green'
-
-        if status == 'soft':
-          hibernate_color = 'yellow'
-        elif status == 'hard':
-          hibernate_color = 'red'
-        elif status == '':
-          # failed to be queried
-          status, hibernate_color = 'unknown', 'red'
-
-        panel.addstr(labeling_line + 2, 0, 'Accounting (', curses.A_BOLD)
-        panel.addstr(labeling_line + 2, 12, status, curses.A_BOLD, hibernate_color)
-        panel.addstr(labeling_line + 2, 12 + len(status), ')', curses.A_BOLD)
+        hibernate_color = CONFIG['attr.hibernate_color'].get(self.accounting_stats.status, 'red')
 
-        reset_time = self.accounting_info['reset_time']
+        x, y = 0, labeling_line + 2
+        x = panel.addstr(y, x, 'Accounting (', curses.A_BOLD)
+        x = panel.addstr(y, x, self.accounting_stats.status, curses.A_BOLD, hibernate_color)
+        x = panel.addstr(y, x, ')', curses.A_BOLD)
 
-        if not reset_time:
-          reset_time = 'unknown'
+        panel.addstr(y, 35, 'Time to reset: %s' % str_tools.short_time_label(self.accounting_stats.time_until_reset))
 
-        panel.addstr(labeling_line + 2, 35, 'Time to reset: %s' % reset_time)
-
-        used, total = self.accounting_info['read'], self.accounting_info['read_limit']
-
-        if used and total:
-          panel.addstr(labeling_line + 3, 2, '%s / %s' % (used, total), self.get_color(True))
-
-        used, total = self.accounting_info['written'], self.accounting_info['writtenLimit']
-
-        if used and total:
-          panel.addstr(labeling_line + 3, 37, '%s / %s' % (used, total), self.get_color(False))
+        panel.addstr(y + 1, 2, '%s / %s' % (self.accounting_stats.read_bytes, self.accounting_stats.read_limit), self.get_color(True))
+        panel.addstr(y + 1, 37, '%s / %s' % (self.accounting_stats.written_bytes, self.accounting_stats.write_limit), self.get_color(True))
       else:
         panel.addstr(labeling_line + 2, 0, 'Accounting:', curses.A_BOLD)
         panel.addstr(labeling_line + 2, 12, 'Connection Closed...')
@@ -297,7 +266,7 @@ class BandwidthStats(graph_panel.GraphStats):
 
   def get_content_height(self):
     base_height = graph_panel.GraphStats.get_content_height(self)
-    return base_height + 3 if self.is_accounting else base_height
+    return base_height + 3 if self.accounting_stats else base_height
 
   def new_desc_event(self, event):
     # updates self._title_stats with updated values
@@ -357,56 +326,6 @@ class BandwidthStats(graph_panel.GraphStats):
     total += self.initial_primary_total if is_primary else self.initial_secondary_total
     return 'total: %s' % str_tools.size_label(total * 1024, 1)
 
-  def _update_accounting_info(self):
-    """
-    Updates mapping used for accounting info. This includes the following keys:
-    status, reset_time, read, written, read_limit, writtenLimit
-
-    Any failed lookups result in a mapping to an empty string.
-    """
-
-    controller = tor_controller()
-    queried = dict([(arg, '') for arg in ACCOUNTING_ARGS])
-    queried['status'] = controller.get_info('accounting/hibernating', None)
-
-    # provides a nicely formatted reset time
-
-    end_interval = controller.get_info('accounting/interval-end', None)
-
-    if end_interval:
-      # converts from gmt to local with respect to DST
-
-      sec = calendar.timegm(time.strptime(end_interval, '%Y-%m-%d %H:%M:%S')) - time.time()
-
-      if CONFIG['features.graph.bw.accounting.isTimeLong']:
-        queried['reset_time'] = ', '.join(str_tools.time_labels(sec, True))
-      else:
-        days = sec / 86400
-        sec %= 86400
-        hours = sec / 3600
-        sec %= 3600
-        minutes = sec / 60
-        sec %= 60
-        queried['reset_time'] = '%i:%02i:%02i:%02i' % (days, hours, minutes, sec)
-
-    # number of bytes used and in total for the accounting period
-
-    used = controller.get_info('accounting/bytes', None)
-    left = controller.get_info('accounting/bytes-left', None)
-
-    if used and left:
-      used_comp, left_comp = used.split(' '), left.split(' ')
-      read, written = int(used_comp[0]), int(used_comp[1])
-      read_left, written_left = int(left_comp[0]), int(left_comp[1])
-
-      queried['read'] = str_tools.size_label(read)
-      queried['written'] = str_tools.size_label(written)
-      queried['read_limit'] = str_tools.size_label(read + read_left)
-      queried['writtenLimit'] = str_tools.size_label(written + written_left)
-
-    self.accounting_info = queried
-    self.accounting_last_updated = time.time()
-
 
 def _min_config(controller, *attributes):
   """
diff --git a/armrc.sample b/armrc.sample
index 6639879..eb28daa 100644
--- a/armrc.sample
+++ b/armrc.sample
@@ -180,14 +180,11 @@ features.graph.showIntermediateBounds true
 #   provides accounting stats if AccountingMax was set
 # accounting.rate
 #   seconds between querying accounting stats
-# accounting.isTimeLong
-#   provides verbose measurements of time if true
 
 features.graph.bw.prepopulate true
 features.graph.bw.transferInBytes false
 features.graph.bw.accounting.show true
 features.graph.bw.accounting.rate 10
-features.graph.bw.accounting.isTimeLong false
 
 # Parameters for connection display
 # ---------------------------------

_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits