From: Brian Warner Date: Mon, 14 Apr 2008 21:17:08 +0000 (-0700) Subject: stats: add /statistics web page to show them, add tests X-Git-Url: https://git.rkrishnan.org/components/architecture.txt?a=commitdiff_plain;h=5b8320442a836cc145e4982f3f6bb9b2f841abe1;p=tahoe-lafs%2Ftahoe-lafs.git stats: add /statistics web page to show them, add tests --- diff --git a/src/allmydata/stats.py b/src/allmydata/stats.py index 96fea7a6..1a0ae0d8 100644 --- a/src/allmydata/stats.py +++ b/src/allmydata/stats.py @@ -103,15 +103,17 @@ class StatsProvider(foolscap.Referenceable, service.MultiService): def register_producer(self, stats_producer): self.stats_producers.append(IStatsProducer(stats_producer)) - def remote_get_stats(self): + def get_stats(self): stats = {} for sp in self.stats_producers: stats.update(sp.get_stats()) - #return { 'counters': self.counters, 'stats': stats } ret = { 'counters': self.counters, 'stats': stats } - log.msg(format='get_stats() -> %s', args=(pprint.pformat(ret),), level=12) + log.msg(format='get_stats() -> %(stats)s', stats=ret, level=log.NOISY) return ret + def remote_get_stats(self): + return self.get_stats() + def _connected(self, gatherer, nickname): gatherer.callRemoteOnly('provide', self, nickname or '') diff --git a/src/allmydata/test/test_system.py b/src/allmydata/test/test_system.py index c191671b..970c5ada 100644 --- a/src/allmydata/test/test_system.py +++ b/src/allmydata/test/test_system.py @@ -1354,6 +1354,18 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase): self.failUnlessEqual(data, {}) d.addCallback(_got_non_helper_status_json) + # see if the statistics page exists + d.addCallback(lambda res: self.GET("statistics")) + def _got_stats(res): + self.failUnless("Node Statistics" in res) + self.failUnless(" 'downloader.files_downloaded': 8," in res) + d.addCallback(_got_stats) + d.addCallback(lambda res: self.GET("statistics?t=json")) + def _got_stats_json(res): + data = simplejson.loads(res) + self.failUnlessEqual(data["counters"]["uploader.files_uploaded"], 5) + self.failUnlessEqual(data["stats"]["chk_upload_helper.upload_need_upload"], 1) + d.addCallback(_got_stats_json) # TODO: mangle the second segment of a file, to test errors that # occur after we've already sent some good data, which uses a diff --git a/src/allmydata/web/statistics.xhtml b/src/allmydata/web/statistics.xhtml new file mode 100644 index 00000000..fa956ab7 --- /dev/null +++ b/src/allmydata/web/statistics.xhtml @@ -0,0 +1,28 @@ + + + Stats - AllMyData Tahoe + + + + + + +

Node Statistics

+ + + +

Raw Stats:

+
+
+
Return to the Welcome Page
+ + + diff --git a/src/allmydata/web/status.py b/src/allmydata/web/status.py index 49518f98..1b07045d 100644 --- a/src/allmydata/web/status.py +++ b/src/allmydata/web/status.py @@ -1,11 +1,11 @@ -import time +import time, pprint import simplejson from twisted.internet import defer from nevow import rend, inevow, tags as T from allmydata.util import base32, idlib from allmydata.web.common import IClient, getxmlfile, abbreviate_time, \ - abbreviate_rate, get_arg + abbreviate_rate, abbreviate_size, get_arg from allmydata.interfaces import IUploadStatus, IDownloadStatus, \ IPublishStatus, IRetrieveStatus @@ -808,3 +808,48 @@ class HelperStatus(rend.Page): def render_upload_bytes_encoded(self, ctx, data): return str(data["chk_upload_helper.encoded_bytes"]) + +class Statistics(rend.Page): + docFactory = getxmlfile("statistics.xhtml") + + def renderHTTP(self, ctx): + provider = IClient(ctx).stats_provider + stats = {'stats': {}, 'counters': {}} + if provider: + stats = provider.get_stats() + t = get_arg(inevow.IRequest(ctx), "t") + if t == "json": + return simplejson.dumps(stats, indent=1) + # is there a better way to provide 'data' to all rendering methods? + self.original = stats + return rend.Page.renderHTTP(self, ctx) + + def render_load_average(self, ctx, data): + return str(data["stats"].get("load_monitor.avg_load")) + + def render_peak_load(self, ctx, data): + return str(data["stats"].get("load_monitor.max_load")) + + def render_uploads(self, ctx, data): + files = data["counters"].get("uploader.files_uploaded") + bytes = data["counters"].get("uploader.bytes_uploaded") + return ("%s files / %s bytes (%s)" % + (files, bytes, abbreviate_size(bytes))) + + def render_downloads(self, ctx, data): + files = data["counters"].get("downloader.files_uploaded") + bytes = data["counters"].get("downloader.bytes_uploaded") + return ("%s files / %s bytes (%s)" % + (files, bytes, abbreviate_size(bytes))) + + def render_publishes(self, ctx, data): + files = data["counters"].get("mutable.files_published") + return "%s files" % (files,) + + def render_retrieves(self, ctx, data): + files = data["counters"].get("mutable.files_retrieved") + return "%s files" % (files,) + + def render_raw(self, ctx, data): + raw = pprint.pformat(data) + return ctx.tag[raw] diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py index 5afc3fb9..4f0bebf6 100644 --- a/src/allmydata/webish.py +++ b/src/allmydata/webish.py @@ -1446,6 +1446,7 @@ class Root(rend.Page): child_provisioning = provisioning.ProvisioningTool() child_status = status.Status() child_helper_status = status.HelperStatus() + child_statistics = status.Statistics() def data_version(self, ctx, data): return get_package_versions_string()