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.
This commit is contained in:
robk-tahoe 2008-01-31 21:10:15 -07:00
parent b80cfeb186
commit e5487bbe21
4 changed files with 24 additions and 10 deletions

View File

@ -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

View File

@ -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.
"""

View File

@ -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):

View File

@ -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):