mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-27 06:20:25 +00:00
logpublisher: implement subscribe/publish for log, add a sample client
This commit is contained in:
parent
c2765bd8c6
commit
b29ce1c30a
43
misc/get-logs.py
Normal file
43
misc/get-logs.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import foolscap
|
||||||
|
from foolscap.schema import DictOf, Any
|
||||||
|
from twisted.internet import reactor
|
||||||
|
from zope.interface import implements
|
||||||
|
from twisted.python import log
|
||||||
|
#log.startLogging(sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
class RILogObserver(foolscap.RemoteInterface):
|
||||||
|
def msg(logmsg=DictOf(str, Any())):
|
||||||
|
return None
|
||||||
|
|
||||||
|
class LogFetcher(foolscap.Referenceable):
|
||||||
|
implements(RILogObserver)
|
||||||
|
def start(self, target_furl):
|
||||||
|
print "Connecting.."
|
||||||
|
self._tub = foolscap.Tub()
|
||||||
|
self._tub.startService()
|
||||||
|
d = self._tub.getReference(target_furl)
|
||||||
|
d.addCallback(self._got_logpublisher)
|
||||||
|
d.addErrback(self._error)
|
||||||
|
|
||||||
|
def _error(self, f):
|
||||||
|
print "ERROR", f
|
||||||
|
reactor.stop()
|
||||||
|
|
||||||
|
def _got_logpublisher(self, publisher):
|
||||||
|
print "Connected"
|
||||||
|
d = publisher.callRemote("subscribe_to_all", self)
|
||||||
|
d.addErrback(self._error)
|
||||||
|
|
||||||
|
def remote_msg(self, d):
|
||||||
|
print d
|
||||||
|
|
||||||
|
|
||||||
|
target_furl = sys.argv[1]
|
||||||
|
lf = LogFetcher()
|
||||||
|
lf.start(target_furl)
|
||||||
|
#print "starting.."
|
||||||
|
reactor.run()
|
@ -2,23 +2,42 @@
|
|||||||
import os.path
|
import os.path
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from twisted.application import service
|
from twisted.application import service
|
||||||
|
from twisted.python import log
|
||||||
from foolscap import Referenceable, RemoteInterface
|
from foolscap import Referenceable, RemoteInterface
|
||||||
from foolscap.schema import DictOf
|
from foolscap.schema import DictOf, Any
|
||||||
|
from foolscap.eventual import eventually
|
||||||
|
|
||||||
|
class RILogObserver(RemoteInterface):
|
||||||
|
def msg(logmsg=DictOf(str, Any())):
|
||||||
|
return None
|
||||||
|
class RISubscription(RemoteInterface):
|
||||||
|
pass
|
||||||
|
|
||||||
class RILogPublisher(RemoteInterface):
|
class RILogPublisher(RemoteInterface):
|
||||||
def get_versions():
|
def get_versions():
|
||||||
return DictOf(str, str)
|
return DictOf(str, str)
|
||||||
|
def subscribe_to_all(observer=RILogObserver):
|
||||||
|
return RISubscription
|
||||||
|
def unsubscribe(subscription=Any()):
|
||||||
|
# I don't know how to get the constraint right: unsubscribe() should
|
||||||
|
# accept return value of subscribe_to_all()
|
||||||
|
return None
|
||||||
|
|
||||||
class RILogGatherer(RemoteInterface):
|
class RILogGatherer(RemoteInterface):
|
||||||
def logport(nodeid=str, logport=RILogPublisher):
|
def logport(nodeid=str, logport=RILogPublisher):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
class Subscription(Referenceable):
|
||||||
|
implements(RISubscription)
|
||||||
|
|
||||||
class LogPublisher(Referenceable, service.MultiService):
|
class LogPublisher(Referenceable, service.MultiService):
|
||||||
implements(RILogPublisher)
|
implements(RILogPublisher)
|
||||||
name = "log_publisher"
|
name = "log_publisher"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
service.MultiService.__init__(self)
|
service.MultiService.__init__(self)
|
||||||
|
self._subscribers = {}
|
||||||
|
self._notifyOnDisconnectors = {}
|
||||||
|
|
||||||
def startService(self):
|
def startService(self):
|
||||||
service.MultiService.startService(self)
|
service.MultiService.startService(self)
|
||||||
@ -26,6 +45,28 @@ class LogPublisher(Referenceable, service.MultiService):
|
|||||||
self.parent.tub.registerReference(self, furlFile=furlfile)
|
self.parent.tub.registerReference(self, furlFile=furlfile)
|
||||||
os.chmod(furlfile, 0600)
|
os.chmod(furlfile, 0600)
|
||||||
|
|
||||||
|
log.addObserver(self._twisted_log_observer)
|
||||||
|
|
||||||
|
def stopService(self):
|
||||||
|
log.removeObserver(self._twisted_log_observer)
|
||||||
|
return service.MultiService.stopService(self)
|
||||||
|
|
||||||
|
def _twisted_log_observer(self, d):
|
||||||
|
# Twisted will remove this for us if it fails.
|
||||||
|
|
||||||
|
# keys:
|
||||||
|
# ['message']: *args
|
||||||
|
# ['time']: float
|
||||||
|
# ['isError']: bool, usually False
|
||||||
|
# ['system']: string
|
||||||
|
|
||||||
|
for o in self._subscribers.values():
|
||||||
|
o.callRemoteOnly("msg", d)
|
||||||
|
|
||||||
|
#f = open("/tmp/f.out", "a")
|
||||||
|
#print >>f, d['message']
|
||||||
|
#f.close()
|
||||||
|
|
||||||
def remote_get_versions(self):
|
def remote_get_versions(self):
|
||||||
versions = self.parent.get_versions()
|
versions = self.parent.get_versions()
|
||||||
# our __version__ attributes are actually instances of
|
# our __version__ attributes are actually instances of
|
||||||
@ -34,3 +75,15 @@ class LogPublisher(Referenceable, service.MultiService):
|
|||||||
return dict([(k,str(v))
|
return dict([(k,str(v))
|
||||||
for k,v in versions.items()])
|
for k,v in versions.items()])
|
||||||
|
|
||||||
|
def remote_subscribe_to_all(self, observer):
|
||||||
|
s = Subscription()
|
||||||
|
self._subscribers[s] = observer
|
||||||
|
c = observer.notifyOnDisconnect(self.remote_unsubscribe, s)
|
||||||
|
self._notifyOnDisconnectors[s] = c
|
||||||
|
return s
|
||||||
|
|
||||||
|
def remote_unsubscribe(self, s):
|
||||||
|
observer = self._subscribers.pop(s)
|
||||||
|
c = self._notifyOnDisconnectors.pop(s)
|
||||||
|
observer.dontNotifyOnDisconnect(c)
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from twisted.internet import defer
|
|||||||
from twisted.python import log
|
from twisted.python import log
|
||||||
|
|
||||||
from foolscap import Tub, Referenceable
|
from foolscap import Tub, Referenceable
|
||||||
from foolscap.eventual import flushEventualQueue
|
from foolscap.eventual import fireEventually, flushEventualQueue
|
||||||
from twisted.application import service
|
from twisted.application import service
|
||||||
import allmydata
|
import allmydata
|
||||||
from allmydata.node import Node, formatTimeTahoeStyle
|
from allmydata.node import Node, formatTimeTahoeStyle
|
||||||
@ -61,6 +61,7 @@ class TestCase(unittest.TestCase, testutil.SignalMixin):
|
|||||||
def test_logpublisher(self):
|
def test_logpublisher(self):
|
||||||
basedir = "test_node/test_logpublisher"
|
basedir = "test_node/test_logpublisher"
|
||||||
fileutil.make_dirs(basedir)
|
fileutil.make_dirs(basedir)
|
||||||
|
observer = LogObserver()
|
||||||
n = TestNode(basedir)
|
n = TestNode(basedir)
|
||||||
n.setServiceParent(self.parent)
|
n.setServiceParent(self.parent)
|
||||||
d = n.when_tub_ready()
|
d = n.when_tub_ready()
|
||||||
@ -75,6 +76,23 @@ class TestCase(unittest.TestCase, testutil.SignalMixin):
|
|||||||
self.failUnlessEqual(versions["allmydata"],
|
self.failUnlessEqual(versions["allmydata"],
|
||||||
allmydata.__version__)
|
allmydata.__version__)
|
||||||
d.addCallback(_check)
|
d.addCallback(_check)
|
||||||
|
d.addCallback(lambda res:
|
||||||
|
logport.callRemote("subscribe_to_all", observer))
|
||||||
|
def _emit(subscription):
|
||||||
|
self._subscription = subscription
|
||||||
|
log.msg("message here")
|
||||||
|
d.addCallback(_emit)
|
||||||
|
d.addCallback(fireEventually)
|
||||||
|
d.addCallback(fireEventually)
|
||||||
|
def _check_observer(res):
|
||||||
|
msgs = observer.messages
|
||||||
|
self.failUnlessEqual(len(msgs), 1)
|
||||||
|
#print msgs
|
||||||
|
self.failUnlessEqual(msgs[0]["message"], ("message here",) )
|
||||||
|
d.addCallback(_check_observer)
|
||||||
|
def _done(res):
|
||||||
|
return logport.callRemote("unsubscribe", self._subscription)
|
||||||
|
d.addCallback(_done)
|
||||||
return d
|
return d
|
||||||
d.addCallback(_got_logport)
|
d.addCallback(_got_logport)
|
||||||
return d
|
return d
|
||||||
@ -122,3 +140,10 @@ class Gatherer(Referenceable):
|
|||||||
def remote_logport(self, nodeid, logport):
|
def remote_logport(self, nodeid, logport):
|
||||||
d = logport.callRemote("get_versions")
|
d = logport.callRemote("get_versions")
|
||||||
d.addCallback(self.d.callback)
|
d.addCallback(self.d.callback)
|
||||||
|
|
||||||
|
class LogObserver(Referenceable):
|
||||||
|
implements(logpublisher.RILogObserver)
|
||||||
|
def __init__(self):
|
||||||
|
self.messages = []
|
||||||
|
def remote_msg(self, d):
|
||||||
|
self.messages.append(d)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user