From 63a9d6d725491050d9cb28c397b58edd584e11d8 Mon Sep 17 00:00:00 2001 From: Cameron Dale Date: Mon, 17 Mar 2008 16:43:30 -0700 Subject: [PATCH] Move the HTML stats page generation for the DHT into the stats module. --- apt_p2p_Khashmir/DHT.py | 29 +----- apt_p2p_Khashmir/khashmir.py | 2 +- apt_p2p_Khashmir/stats.py | 169 +++++++++++++---------------------- 3 files changed, 66 insertions(+), 134 deletions(-) diff --git a/apt_p2p_Khashmir/DHT.py b/apt_p2p_Khashmir/DHT.py index e9baaa8..edb626d 100644 --- a/apt_p2p_Khashmir/DHT.py +++ b/apt_p2p_Khashmir/DHT.py @@ -5,7 +5,6 @@ """ from datetime import datetime -from StringIO import StringIO import os, sha, random from twisted.internet import defer, reactor @@ -276,33 +275,7 @@ class DHT: def getStats(self): """See L{apt_p2p.interfaces.IDHTStats}.""" - stats = self.khashmir.getStats() - out = StringIO() - out.write('

DHT Statistics

\n') - old_group = None - for stat in stats: - if stat['group'] != old_group: - if old_group is not None: - out.write('\n') - out.write('\n

' + stat['group'] + '

\n') - out.write("\n") - if stat['group'] != 'Actions': - out.write("\n") - else: - out.write("\n") - old_group = stat['group'] - if stat['group'] != 'Actions': - out.write("\n') - else: - actions = stat['value'].keys() - actions.sort() - for action in actions: - out.write("") - for i in xrange(6): - out.write("") - out.write('\n') - - return out.getvalue() + return self.khashmir.getStats() def getStatsFactory(self): """See L{apt_p2p.interfaces.IDHTStatsFactory}.""" diff --git a/apt_p2p_Khashmir/khashmir.py b/apt_p2p_Khashmir/khashmir.py index 48a0c0c..3ed7baf 100644 --- a/apt_p2p_Khashmir/khashmir.py +++ b/apt_p2p_Khashmir/khashmir.py @@ -301,7 +301,7 @@ class KhashmirBase(protocol.Factory): def getStats(self): """Gather the statistics for the DHT.""" - return self.stats.gather() + return self.stats.formatHTML() #{ Remote interface def krpc_ping(self, id, _krpc_sender): diff --git a/apt_p2p_Khashmir/stats.py b/apt_p2p_Khashmir/stats.py index e2752dd..5afc17a 100644 --- a/apt_p2p_Khashmir/stats.py +++ b/apt_p2p_Khashmir/stats.py @@ -2,12 +2,11 @@ """Store statistics for the Khashmir DHT.""" from datetime import datetime, timedelta -from copy import deepcopy +from StringIO import StringIO class StatsLogger: """Store the statistics for the Khashmir DHT. - @ivar _StatsTemplate: a template for returning all the statistics @type config: C{dictionary} @ivar config: the configuration parameters for the DHT @ivar startTime: the time the program was started @@ -32,86 +31,6 @@ class StatsLogger: generated an error """ - _StatsTemplate = [{'name': 'uptime', - 'group': 'General', - 'desc': 'Up time', - 'tip': 'The elapsed time since the program started', - 'value': None, - }, - {'name': 'reachable', - 'group': 'General', - 'desc': 'Reachable', - 'tip': 'Whether other nodes can contact us (not NATted or firewalled)', - 'value': None, - }, - {'name': 'nodes', - 'group': 'Routing Table', - 'desc': 'Number of nodes', - 'tip': 'The number of nodes we are connected to', - 'value': None, - }, - {'name': 'users', - 'group': 'Routing Table', - 'desc': 'Total number of users', - 'tip': 'The estimated total number of users in the DHT', - 'value': None, - }, - {'name': 'keys', - 'group': 'Database', - 'desc': 'Keys', - 'tip': 'The number of distinct keys in the database', - 'value': None, - }, - {'name': 'values', - 'group': 'Database', - 'desc': 'Values', - 'tip': 'The total number of values in the database', - 'value': None, - }, - {'name': 'downPackets', - 'group': 'Transport', - 'desc': 'Downloaded packets', - 'tip': 'The number of received packets', - 'value': None, - }, - {'name': 'upPackets', - 'group': 'Transport', - 'desc': 'Uploaded packets', - 'tip': 'The number of sent packets', - 'value': None, - }, - {'name': 'downBytes', - 'group': 'Transport', - 'desc': 'Downloaded bytes', - 'tip': 'The number of bytes received by the DHT', - 'value': None, - }, - {'name': 'upBytes', - 'group': 'Transport', - 'desc': 'Uploaded bytes', - 'tip': 'The number of bytes sent by the DHT', - 'value': None, - }, - {'name': 'downSpeed', - 'group': 'Transport', - 'desc': 'Downloaded bytes/second', - 'tip': 'The number of bytes received by the DHT per second', - 'value': None, - }, - {'name': 'upSpeed', - 'group': 'Transport', - 'desc': 'Uploaded bytes/second', - 'tip': 'The number of bytes sent by the DHT per second', - 'value': None, - }, - {'name': 'actions', - 'group': 'Actions', - 'desc': 'Actions', - 'tip': 'The number of requests for each action', - 'value': None, - }, - ] - def __init__(self, table, store, config): """Initialize the statistics. @@ -124,7 +43,7 @@ class StatsLogger: """ # General self.config = config - self.startTime = datetime.now() + self.startTime = datetime.now().replace(microsecond=0) self.reachable = False # Routing Table @@ -170,32 +89,72 @@ class StatsLogger: self.keys, self.values = self.store.keyStats() return (self.keys, self.values) - def gather(self): - """Gather all the statistics for the DHT. + def formatHTML(self): + """Gather statistics for the DHT and format them for display in a browser. - @rtype: C{list} of C{dictionary} - @return: each dictionary has keys describing the statistic: - name, group, desc, tip, and value + @rtype: C{string} + @return: the stats, formatted for display in the body of an HTML page """ self.tableStats() self.dbStats() - stats = self._StatsTemplate[:] - elapsed = datetime.now() - self.startTime - for stat in stats: - val = getattr(self, stat['name'], None) - if stat['name'] == 'uptime': - stat['value'] = elapsed - elif stat['name'] == 'actions': - stat['value'] = deepcopy(self.actions) - elif stat['name'] == 'downSpeed': - stat['value'] = self.downBytes / (elapsed.days*86400.0 + elapsed.seconds + elapsed.microseconds/1000000.0) - elif stat['name'] == 'upSpeed': - stat['value'] = self.upBytes / (elapsed.days*86400.0 + elapsed.seconds + elapsed.microseconds/1000000.0) - elif val is not None: - stat['value'] = val - - return stats - + elapsed = datetime.now().replace(microsecond=0) - self.startTime + out = StringIO() + out.write('

DHT Statistics

\n') + out.write("
StatisticValue
ActionStartedSentOKFailedReceivedError
" + stat['desc'] + '' + str(stat['value']) + '
" + action + "" + str(stat['value'][action][i]) + "
\n\n") + out.write('\n") + out.write("
\n') + out.write("\n") + + # General + out.write("\n") + out.write("\n') + out.write("\n') + out.write("

General

Value
Up time" + str(elapsed) + '
Reachable" + str(self.reachable) + '
\n") + out.write('
\n') + out.write("\n") + + # Routing + out.write("\n") + out.write("\n') + out.write("\n') + out.write("

Routing Table

Value
Number of nodes" + str(self.nodes) + '
Total number of users" + str(self.users) + '
\n") + out.write('
\n') + out.write("\n") + + # Database + out.write("\n") + out.write("\n') + out.write("\n') + out.write("

Database

Value
Keys" + str(self.keys) + '
Values" + str(self.values) + '
\n") + out.write("
\n") + out.write("\n") + out.write("\n") + out.write("") + out.write('') + out.write('') + out.write('\n' % (self.downBytes / (elapsed.days*86400.0 + elapsed.seconds), )) + out.write("") + out.write('') + out.write('') + out.write('\n' % (self.upBytes / (elapsed.days*86400.0 + elapsed.seconds), )) + out.write("

Transport

PacketsBytesBytes/second
Downloaded' + str(self.downPackets) + '' + str(self.downBytes) + '%0.2f
Uploaded' + str(self.upPackets) + '' + str(self.upBytes) + '%0.2f
\n") + out.write("
\n") + out.write("\n") + + # Actions + out.write("\n") + actions = self.actions.keys() + actions.sort() + for action in actions: + out.write("") + for i in xrange(6): + out.write("") + out.write('\n') + out.write("

Actions

StartedSentOKFailedReceivedError
" + action + "" + str(self.actions[action][i]) + "
\n") + out.write("
\n") + + return out.getvalue() + #{ Called by the action def startedAction(self, action): """Record that an action was started. -- 2.39.5