[tor-commits] [nyx/master] Cache our router status entry

atagar at torproject.org atagar at torproject.org
Sun Aug 13 22:13:25 UTC 2017


commit 769ab42c72fb30fe2a7713604bc7663262d41379
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Aug 13 15:12:17 2017 -0700

    Cache our router status entry
    
    Both our header and graph frequenly refer to our router status entry. In
    practice this only changes once per hour so caching it for five minutes. At
    debug runlevel this causes the vast majority of the noise in our logs.
---
 nyx/panel/graph.py   |  2 +-
 nyx/panel/header.py  |  3 ++-
 nyx/tracker.py       | 24 ++++++++++++++++++++++++
 test/panel/header.py |  6 ++++--
 4 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py
index fc1e7cb..e7114cb 100644
--- a/nyx/panel/graph.py
+++ b/nyx/panel/graph.py
@@ -338,7 +338,7 @@ class BandwidthStats(GraphCategory):
       stats.append('limit: %s/s' % bw_rate_label)
       stats.append('burst: %s/s' % bw_burst_label)
 
-    my_router_status_entry = controller.get_network_status(default = None)
+    my_router_status_entry = nyx.tracker.get_consensus_tracker().my_router_status_entry()
     measured_bw = getattr(my_router_status_entry, 'bandwidth', None)
 
     if measured_bw:
diff --git a/nyx/panel/header.py b/nyx/panel/header.py
index 9d90d75..cf11b67 100644
--- a/nyx/panel/header.py
+++ b/nyx/panel/header.py
@@ -232,6 +232,7 @@ class Sampling(object):
 
     or_listeners = controller.get_listeners(stem.control.Listener.OR, [])
     control_listeners = controller.get_listeners(stem.control.Listener.CONTROL, [])
+    my_router_status_entry = nyx.tracker.get_consensus_tracker().my_router_status_entry()
 
     if controller.get_conf('HashedControlPassword', None):
       auth_type = 'password'
@@ -262,7 +263,7 @@ class Sampling(object):
       'nickname': controller.get_conf('Nickname', ''),
       'newnym_wait': controller.get_newnym_wait(),
       'exit_policy': controller.get_exit_policy(None),
-      'flags': getattr(controller.get_network_status(default = None), 'flags', []),
+      'flags': getattr(my_router_status_entry, 'flags', []),
 
       'version': str(controller.get_version('Unknown')).split()[0],
       'version_status': controller.get_info('status/version/current', 'Unknown'),
diff --git a/nyx/tracker.py b/nyx/tracker.py
index 0e97560..21d5b36 100644
--- a/nyx/tracker.py
+++ b/nyx/tracker.py
@@ -33,6 +33,7 @@ Background tasks for gathering information about the tor process.
 
   ConsensusTracker - performant lookups for consensus related information
     |- update - updates the consensus information we're based on
+    |- my_router_status_entry - provides the router status entry for ourselves
     |- get_relay_nickname - provides the nickname for a given relay
     |- get_relay_fingerprints - provides relays running at a location
     +- get_relay_address - provides the address a relay is running at
@@ -810,6 +811,9 @@ class ConsensusTracker(object):
     self._nickname_cache = {}  # fingerprint => nickname lookup cache
     self._address_cache = {}
 
+    self._my_router_status_entry = None
+    self._my_router_status_entry_time = 0
+
     # Stem's get_network_statuses() is slow, and overkill for what we need
     # here. Just parsing the raw GETINFO response to cut startup time down.
 
@@ -842,16 +846,36 @@ class ConsensusTracker(object):
     new_fingerprint_cache = {}
     new_address_cache = {}
     new_nickname_cache = {}
+    our_fingerprint = tor_controller().get_info('fingerprint', None)
 
     for desc in router_status_entries:
       new_fingerprint_cache.setdefault(desc.address, []).append((desc.or_port, desc.fingerprint))
       new_address_cache[desc.fingerprint] = (desc.address, desc.or_port)
       new_nickname_cache[desc.fingerprint] = desc.nickname
 
+      if desc.fingerprint == our_fingerprint:
+        self._my_router_status_entry = desc
+        self._my_router_status_entry_time = time.time()
+
     self._fingerprint_cache = new_fingerprint_cache
     self._address_cache = new_address_cache
     self._nickname_cache = new_nickname_cache
 
+  def my_router_status_entry(self):
+    """
+    Provides the router status entry of ourselves. Descriptors are published
+    hourly, and results are cached for five minutes.
+
+    :returns: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3`
+      for ourselves, **None** if it cannot be retrieved
+    """
+
+    if self._my_router_status_entry is None or (time.time() - self._my_router_status_entry_time) > 300:
+      self._my_router_status_entry = tor_controller().get_network_status(default = None)
+      self._my_router_status_entry_time = time.time()
+
+    return self._my_router_status_entry
+
   def get_relay_nickname(self, fingerprint):
     """
     Provides the nickname associated with the given relay.
diff --git a/test/panel/header.py b/test/panel/header.py
index 6a9ba3f..805c8c7 100644
--- a/test/panel/header.py
+++ b/test/panel/header.py
@@ -83,18 +83,18 @@ class TestHeaderPanel(unittest.TestCase):
 
   @patch('nyx.panel.header.tor_controller')
   @patch('nyx.tracker.get_resource_tracker')
+  @patch('nyx.tracker.get_consensus_tracker')
   @patch('time.time', Mock(return_value = 1234.5))
   @patch('os.times', Mock(return_value = (0.08, 0.03, 0.0, 0.0, 18759021.31)))
   @patch('os.uname', Mock(return_value = ('Linux', 'odin', '3.5.0-54-generic', '#81~precise1-Ubuntu SMP Tue Jul 15 04:05:58 UTC 2014', 'i686')))
   @patch('stem.util.system.start_time', Mock(return_value = 5678))
   @patch('stem.util.proc.file_descriptors_used', Mock(return_value = 89))
-  def test_sample(self, resource_tracker_mock, tor_controller_mock):
+  def test_sample(self, consensus_tracker_mock, resource_tracker_mock, tor_controller_mock):
     tor_controller_mock().is_alive.return_value = True
     tor_controller_mock().connection_time.return_value = 567.8
     tor_controller_mock().get_latest_heartbeat.return_value = 89.0
     tor_controller_mock().get_newnym_wait.return_value = 0
     tor_controller_mock().get_exit_policy.return_value = stem.exit_policy.ExitPolicy('reject *:*')
-    tor_controller_mock().get_network_status.return_value = None
     tor_controller_mock().get_version.return_value = stem.version.Version('0.1.2.3-tag')
     tor_controller_mock().get_pid.return_value = '123'
 
@@ -126,6 +126,8 @@ class TestHeaderPanel(unittest.TestCase):
     resource_tracker_mock().get_value.return_value = resources
     stem.util.system.SYSTEM_CALL_TIME = 0.0
 
+    consensus_tracker_mock().my_router_status_entry.return_value = None
+
     vals = nyx.panel.header.Sampling.create()
 
     self.assertEqual(1234.5, vals.retrieved)



More information about the tor-commits mailing list