commit 07c7847c3eeb8aea09a0b2e2c80cc950e7828871 Author: Damian Johnson atagar@torproject.org Date: Mon Oct 28 13:25:59 2013 -0700
Dropping resource tracker's last_query_failed()
Ok, I'm not entirely sure why we had this method. We used to to render 0% resource usage when fresh results failed to be fetched. Why not show the last results we've seen? If we really want to track something reguarding staleness then that's what run_counter() is for. --- arm/graphing/resourceStats.py | 4 +++- arm/headerPanel.py | 15 +++++-------- arm/util/tracker.py | 49 ++++++++++++++++++----------------------- 3 files changed, 29 insertions(+), 39 deletions(-)
diff --git a/arm/graphing/resourceStats.py b/arm/graphing/resourceStats.py index 5be4ba8..352c8ec 100644 --- a/arm/graphing/resourceStats.py +++ b/arm/graphing/resourceStats.py @@ -17,6 +17,7 @@ class ResourceStats(graphPanel.GraphStats): def __init__(self): graphPanel.GraphStats.__init__(self) self.queryPid = torTools.getConn().controller.get_pid(None) + self.lastCounter = None
def clone(self, newCopy=None): if not newCopy: newCopy = ResourceStats() @@ -46,8 +47,9 @@ class ResourceStats(graphPanel.GraphStats): if self.queryPid: resourceTracker = arm.util.tracker.get_resource_tracker()
- if resourceTracker and not resourceTracker.last_query_failed(): + if resourceTracker and resourceTracker.run_counter() != self.lastCounter: resources = resourceTracker.get_resource_usage() + self.lastCounter = resourceTracker.run_counter() primary = resources.cpu_sample * 100 # decimal percentage to whole numbers secondary = resources.memory_bytes / 1048576 # translate size to MB so axis labels are short self.runCount = resourceTracker.run_counter() diff --git a/arm/headerPanel.py b/arm/headerPanel.py index d3a8d9d..3420ade 100644 --- a/arm/headerPanel.py +++ b/arm/headerPanel.py @@ -564,16 +564,11 @@ class HeaderPanel(panel.Panel, threading.Thread): if self.vals["tor/pid"]: resourceTracker = arm.util.tracker.get_resource_tracker()
- if resourceTracker.last_query_failed(): - self.vals["stat/%torCpu"] = "0" - self.vals["stat/rss"] = "0" - self.vals["stat/%mem"] = "0" - else: - resources = resourceTracker.get_resource_usage() - self._lastResourceFetch = resourceTracker.run_counter() - self.vals["stat/%torCpu"] = "%0.1f" % (100 * resources.cpu_sample) - self.vals["stat/rss"] = str(resources.memory_bytes) - self.vals["stat/%mem"] = "%0.1f" % (100 * resources.memory_percent) + resources = resourceTracker.get_resource_usage() + self._lastResourceFetch = resourceTracker.run_counter() + self.vals["stat/%torCpu"] = "%0.1f" % (100 * resources.cpu_sample) + self.vals["stat/rss"] = str(resources.memory_bytes) + self.vals["stat/%mem"] = "%0.1f" % (100 * resources.memory_percent)
# determines the cpu time for the arm process (including user and system # time of both the primary and child processes) diff --git a/arm/util/tracker.py b/arm/util/tracker.py index 7f8ae02..2e964db 100644 --- a/arm/util/tracker.py +++ b/arm/util/tracker.py @@ -19,8 +19,7 @@ Background tasks for gathering informatino about the tor process. +- get_connections - provides our latest connection results
ResourceTracker - periodically checks the resource usage of tor - |- get_resource_usage - provides our latest resource usage results - +- last_query_failed - checks if we failed to fetch newer results + +- get_resource_usage - provides our latest resource usage results """
import collections @@ -89,10 +88,10 @@ class Daemon(threading.Thread): """
def __init__(self, rate): - threading.Thread.__init__(self) + super(Daemon, self).__init__() self.setDaemon(True)
- self._daemon_lock = threading.RLock() + self._process_lock = threading.RLock() self._process_pid = None self._process_name = None
@@ -121,7 +120,7 @@ class Daemon(threading.Thread):
continue # done waiting, try again
- with self._daemon_lock: + with self._process_lock: if self._process_pid is not None: is_successful = self._task(self._process_pid, self._process_name) else: @@ -193,7 +192,7 @@ class Daemon(threading.Thread): self._pause_condition.notifyAll()
def _tor_status_listener(self, controller, event_type, _): - with self._daemon_lock: + with self._process_lock: if not self._halt and event_type in (State.INIT, State.RESET): tor_pid = controller.get_pid(None) tor_cmd = system.get_name_by_pid(tor_pid) if tor_pid else None @@ -208,10 +207,10 @@ class ConnectionTracker(Daemon): """
def __init__(self): - Daemon.__init__(self, CONFIG['queries.connections.rate']) + super(ConnectionTracker, self).__init__(CONFIG['queries.connections.rate'])
- self._resolvers = connection.get_system_resolvers() self._connections = [] + self._resolvers = connection.get_system_resolvers() self._custom_resolver = None
# Number of times in a row we've either failed with our current resolver or @@ -228,7 +227,7 @@ class ConnectionTracker(Daemon): resolver = self._resolvers[0] is_default_resolver = True else: - return # nothing to resolve with + return False # nothing to resolve with
try: start_time = time.time() @@ -289,7 +288,7 @@ class ConnectionTracker(Daemon): Provides the custom resolver the user has selected. This is **None** if we're picking resolvers dynamically.
- :returns: :data:`stem.util.connection.Resolver` we're overwritten to use + :returns: :data:`~stem.util.connection.Resolver` we're overwritten to use """
return self._custom_resolver @@ -306,10 +305,10 @@ class ConnectionTracker(Daemon):
def get_connections(self): """ - Provides the last queried connection results, an empty list if resolver - has been stopped. + Provides a listing of tor's latest connections.
- :returns: **list** of :class:`~stem.util.connection.Connection` we last retrieved + :returns: **list** of :class:`~stem.util.connection.Connection` we last + retrieved, an empty list if our tracker's been stopped """
if self._halt: @@ -317,15 +316,16 @@ class ConnectionTracker(Daemon): else: return list(self._connections)
+ class ResourceTracker(Daemon): """ Periodically retrieves the resource usage of tor. """
def __init__(self): - Daemon.__init__(self, CONFIG['queries.resources.rate']) + super(ResourceTracker, self).__init__(CONFIG['queries.resources.rate'])
- self._last_sample = None + self._resources = None
# resolves usage via proc results if true, ps otherwise self._use_proc = proc.is_available() @@ -340,20 +340,13 @@ class ResourceTracker(Daemon):
def get_resource_usage(self): """ - Provides the last cached resource usage as a named tuple of the form: - (cpuUsage_sampling, cpuUsage_avg, memUsage_bytes, memUsage_percent) - """ + Provides tor's latest resource usage.
- with self._daemon_lock: - return self._last_sample if self._last_sample else Resources(0.0, 0.0, 0, 0.0) - - def last_query_failed(self): - """ - Provides true if, since we fetched the currently cached results, we've - failed to get new results. False otherwise. + :returns: latest :data:`~arm.util.tracker.Resources` we've polled """
- return self._failure_count != 0 + result = self._resources + return result if result else Resources(0.0, 0.0, 0, 0.0)
def _task(self, process_pid, process_name): if process_pid is None: @@ -419,7 +412,7 @@ class ResourceTracker(Daemon): log.info("Failed three attempts to get process resource usage from proc, falling back to ps (%s)" % exc)
self._use_proc = False - self._failure_count = 1 # prevents last_query_failed() from thinking that we succeeded + self._failure_count = 0 else: # wait a bit and try again log.debug("Unable to query process resource usage from proc (%s)" % exc) @@ -437,7 +430,7 @@ class ResourceTracker(Daemon): new_values["cpuSampling"] = new_values["cpuAvg"]
with self.val_lock: - self._last_sample = Resources(new_values["cpuSampling"], new_values["cpuAvg"], new_values["memUsage"], new_values["memUsagePercentage"]) + self._resources = Resources(new_values["cpuSampling"], new_values["cpuAvg"], new_values["memUsage"], new_values["memUsagePercentage"]) self._last_cpu_total = new_values["_lastCpuTotal"] self.last_lookup = time.time() self._failure_count = 0