2 """Store statistics for the Apt-P2P downloader."""
4 from datetime import datetime, timedelta
5 from StringIO import StringIO
7 from util import uncompact, byte_format
10 """Store the statistics for the Khashmir DHT.
12 @ivar startTime: the time the program was started
13 @ivar reachable: whether we can be contacted by other nodes
14 @type table: L{ktable.KTable}
15 @ivar table: the routing table for the DHT
16 @ivar lastTableUpdate: the last time an update of the table stats was done
17 @ivar nodes: the number of nodes connected
18 @ivar users: the estimated number of total users in the DHT
20 @ivar store: the database for the DHT
21 @ivar lastDBUpdate: the last time an update of the database stats was done
22 @ivar keys: the number of distinct keys in the database
23 @ivar values: the number of values in the database
24 @ivar downPackets: the number of packets received
25 @ivar upPackets: the number of packets sent
26 @ivar downBytes: the number of bytes received
27 @ivar upBytes: the number of bytes sent
28 @ivar actions: a dictionary of the actions and their statistics, keys are
29 the action name, values are a list of 5 elements for the number of
30 times the action was sent, responded to, failed, received, and
34 def __init__(self, db):
35 """Initialize the statistics.
38 @param db: the database for the Apt-P2P downloader
42 self.hashes, self.files = 0, 0
50 stats = self.db.getStats()
51 self.mirrorAllDown = long(stats.get('mirror_down', 0L))
52 self.peerAllDown = long(stats.get('peer_down', 0L))
53 self.peerAllUp = long(stats.get('peer_up', 0L))
56 """Save the persistent statistics to the DB."""
57 stats = {'mirror_down': self.mirrorAllDown,
58 'peer_down': self.peerAllDown,
59 'peer_up': self.peerAllUp,
61 self.db.saveStats(stats)
63 def formatHTML(self, contactAddress):
64 """Gather statistics for the DHT and format them for display in a browser.
66 @param contactAddress: the external IP address in use
68 @return: the stats, formatted for display in the body of an HTML page
70 self.hashes, self.files = self.db.dbStats()
73 out.write('<h2>Downloader Statistics</h2>\n')
74 out.write("<table border='0' cellspacing='20px'>\n<tr>\n")
78 out.write("<table border='1' cellpadding='4px'>\n")
79 out.write("<tr><th><h3>General</h3></th><th>Value</th></tr>\n")
80 out.write("<tr title='Contact address for this peer'><td>Contact</td><td>" + str(contactAddress) + '</td></tr>\n')
81 out.write("</table>\n")
82 out.write('</td><td>\n')
85 out.write("<table border='1' cellpadding='4px'>\n")
86 out.write("<tr><th><h3>Database</h3></th><th>Value</th></tr>\n")
87 out.write("<tr title='Number of distinct files in the database'><td>Distinct Files</td><td>" + str(self.hashes) + '</td></tr>\n')
88 out.write("<tr title='Total number of files being shared'><td>Total Files</td><td>" + str(self.files) + '</td></tr>\n')
89 out.write("</table>\n")
90 out.write("</td></tr><tr><td colspan='3'>\n")
93 out.write("<table border='1' cellpadding='4px'>\n")
94 out.write("<tr><th><h3>Transport</h3></th><th>Mirror Downloads</th><th>Peer Downloads</th><th>Peer Uploads</th></tr>\n")
95 out.write("<tr><td title='Since the program was last restarted'>This Session</td>")
96 out.write("<td title='Amount downloaded from mirrors'>" + byte_format(self.mirrorDown) + '</td>')
97 out.write("<td title='Amount downloaded from peers'>" + byte_format(self.peerDown) + '</td>')
98 out.write("<td title='Amount uploaded to peers'>" + byte_format(self.peerUp) + '</td></tr>\n')
99 out.write("<tr><td title='Since the program was last restarted'>Session Ratio</td>")
100 out.write("<td title='Percent of download from mirrors'>%0.2f%%</td>" %
101 (100.0 * float(self.mirrorDown) / float(max(self.mirrorDown + self.peerDown, 1)), ))
102 out.write("<td title='Percent of download from peers'>%0.2f%%</td>" %
103 (100.0 * float(self.peerDown) / float(max(self.mirrorDown + self.peerDown, 1)), ))
104 out.write("<td title='Percent uploaded to peers compared with all downloaded'>%0.2f%%</td></tr>\n" %
105 (100.0 * float(self.peerUp) / float(max(self.mirrorDown + self.peerDown, 1)), ))
106 out.write("<tr><td title='Since the program was installed'>All-Time</td>")
107 out.write("<td title='Amount downloaded from mirrors'>" + byte_format(self.mirrorAllDown) + '</td>')
108 out.write("<td title='Amount downloaded from peers'>" + byte_format(self.peerAllDown) + '</td>')
109 out.write("<td title='Amount uploaded to peers'>" + byte_format(self.peerAllUp) + '</td></tr>\n')
110 out.write("<tr><td title='Since the program was installed'>All-Time Ratio</td>")
111 out.write("<td title='Percent of download from mirrors'>%0.2f%%</td>" %
112 (100.0 * float(self.mirrorAllDown) / float(max(self.mirrorAllDown + self.peerAllDown, 1)), ))
113 out.write("<td title='Percent of download from peers'>%0.2f%%</td>" %
114 (100.0 * float(self.peerAllDown) / float(max(self.mirrorAllDown + self.peerAllDown, 1)), ))
115 out.write("<td title='Percent uploaded to peers compared with all downloaded'>%0.2f%%</td></tr\n>" %
116 (100.0 * float(self.peerAllUp) / float(max(self.mirrorAllDown + self.peerAllDown, 1)), ))
117 out.write("</table>\n")
118 out.write("</td></tr>\n")
119 out.write("</table>\n")
121 return out.getvalue()
124 def sentBytes(self, bytes):
125 """Record that some bytes were sent.
127 @param bytes: the number of bytes sent
130 self.peerAllUp += bytes
132 def receivedBytes(self, bytes, mirror = False):
133 """Record that some bytes were received.
135 @param bytes: the number of bytes received
136 @param mirror: whether the bytes were sent to a mirror
139 self.mirrorDown += bytes
140 self.mirrorAllDown += bytes
142 self.peerDown += bytes
143 self.peerAllDown += bytes