From e5487bbe21883860d2699733c8a98e880a1a7433 Mon Sep 17 00:00:00 2001 From: robk-tahoe Date: Thu, 31 Jan 2008 21:10:15 -0700 Subject: [PATCH] stats: added IStatsProducer interface, fixed stats provider startup this adds an interface, IStatsProducer, defining the get_stats() method which the stats provider calls upon and registered producer, and made the register_producer() method check that interface is implemented. also refine the startup logic, so that the stats provider doesn't try and connect out to the stats gatherer until after the node declares the tub 'ready'. this is to address an issue whereby providers would attach to the gatherer without providing a valid furl, and hence the gatherer would be unable to determine the tubid of the connected client, leading to lost samples. --- src/allmydata/client.py | 3 +-- src/allmydata/interfaces.py | 7 +++++++ src/allmydata/stats.py | 20 ++++++++++++++------ src/allmydata/storage.py | 4 ++-- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/allmydata/client.py b/src/allmydata/client.py index 65a49a58..92ea6fa2 100644 --- a/src/allmydata/client.py +++ b/src/allmydata/client.py @@ -84,8 +84,7 @@ class Client(node.Node, Referenceable, testutil.PollMixin): def init_stats_provider(self): gatherer_furl = self.get_config('stats_gatherer.furl') if gatherer_furl: - nickname = self.get_config('nickname') - self.stats_provider = StatsProvider(self.tub, nickname, gatherer_furl) + self.stats_provider = StatsProvider(self, gatherer_furl) self.add_service(self.stats_provider) else: self.stats_provider = None diff --git a/src/allmydata/interfaces.py b/src/allmydata/interfaces.py index 0ea9d3bd..c65af491 100644 --- a/src/allmydata/interfaces.py +++ b/src/allmydata/interfaces.py @@ -1341,3 +1341,10 @@ class RIStatsGatherer(RemoteInterface): return None +class IStatsProducer(Interface): + def get_stats(): + """ + returns a dictionary, with str keys representing the names of stats + to be monitored, and numeric values. + """ + diff --git a/src/allmydata/stats.py b/src/allmydata/stats.py index dbdaf79e..7e3c64f6 100644 --- a/src/allmydata/stats.py +++ b/src/allmydata/stats.py @@ -14,9 +14,11 @@ import foolscap from foolscap.logging.gatherer import get_local_ip_for from allmydata.util import log -from allmydata.interfaces import RIStatsProvider, RIStatsGatherer +from allmydata.interfaces import RIStatsProvider, RIStatsGatherer, IStatsProducer class LoadMonitor(service.MultiService): + implements(IStatsProducer) + loop_interval = 1 num_samples = 60 @@ -65,8 +67,9 @@ class LoadMonitor(service.MultiService): class StatsProvider(foolscap.Referenceable, service.MultiService): implements(RIStatsProvider) - def __init__(self, tub, nickname, gatherer_furl): + def __init__(self, node, gatherer_furl): service.MultiService.__init__(self) + self.node = node self.gatherer_furl = gatherer_furl self.counters = {} @@ -76,15 +79,20 @@ class StatsProvider(foolscap.Referenceable, service.MultiService): self.load_monitor.setServiceParent(self) self.register_producer(self.load_monitor) - if tub: - tub.connectTo(gatherer_furl, self._connected_to_gatherer, nickname) + def startService(self): + if self.node: + d = self.node.when_tub_ready() + def connect(junk): + nickname = self.node.get_config('nickname') + self.node.tub.connectTo(self.gatherer_furl, self._connected, nickname) + d.addCallback(connect) def count(self, name, delta): val = self.counters.setdefault(name, 0) self.counters[name] = val + delta def register_producer(self, stats_producer): - self.stats_producers.append(stats_producer) + self.stats_producers.append(IStatsProducer(stats_producer)) def remote_get_stats(self): stats = {} @@ -92,7 +100,7 @@ class StatsProvider(foolscap.Referenceable, service.MultiService): stats.update(sp.get_stats()) return { 'counters': self.counters, 'stats': stats } - def _connected_to_gatherer(self, gatherer, nickname): + def _connected(self, gatherer, nickname): gatherer.callRemote('provide', self, nickname or '') class StatsGatherer(foolscap.Referenceable, service.MultiService): diff --git a/src/allmydata/storage.py b/src/allmydata/storage.py index b2ac17e8..49fa7eae 100644 --- a/src/allmydata/storage.py +++ b/src/allmydata/storage.py @@ -8,7 +8,7 @@ from twisted.internet import defer from zope.interface import implements from allmydata.interfaces import RIStorageServer, RIBucketWriter, \ RIBucketReader, IStorageBucketWriter, IStorageBucketReader, HASH_SIZE, \ - BadWriteEnablerError + BadWriteEnablerError, IStatsProducer from allmydata.util import fileutil, idlib, mathutil, log from allmydata.util.assertutil import precondition, _assert @@ -666,7 +666,7 @@ def create_mutable_sharefile(filename, my_nodeid, write_enabler, parent): class StorageServer(service.MultiService, Referenceable): - implements(RIStorageServer) + implements(RIStorageServer, IStatsProducer) name = 'storageserver' def __init__(self, storedir, sizelimit=None, no_storage=False, stats_provider=None): -- 2.45.2