1
.. PyZMQ logging doc, by Min Ragan-Kelley, 2011
5
Asynchronous Logging via PyZMQ
6
==============================
10
* The ØMQ guide `coverage <http://zguide.zeromq.org/chapter:all#toc7>`_ of PUB/SUB
12
* Python logging module `documentation <http://docs.python.org/library/logging.html>`_
14
Python provides extensible logging facilities through its :py:mod:`logging` module. This
15
module allows for easily extensible logging functionality through the use of
16
:py:class:`~logging.Handler` objects. The most obvious case for hooking up pyzmq to
17
logging would be to broadcast log messages over a PUB socket, so we have provides a
18
:class:`.PUBHandler` class for doing just that.
23
The ØMQ PUB/SUB pattern consists of a PUB socket broadcasting messages, and a collection
24
of SUB sockets that receive those messages. Each PUB message is a multipart-message, where
25
the first part is interpreted as a topic. SUB sockets can subscribe to topics by setting
26
their ``SUBSCRIBE`` sockopt, e.g.::
28
sub = ctx.socket(zmq.SUB)
29
sub.setsockopt(zmq.SUBSCRIBE, 'topic1')
30
sub.setsockopt(zmq.SUBSCRIBE, 'topic2')
32
When subscribed, the SUB socket will only receive messages where the first part *starts
33
with* one of the topics set via ``SUBSCRIBE``. The default behavior is to exclude all
34
messages, and subscribing to the empty string '' will receive all messages.
39
The :class:`.PUBHandler` object is created for allowing the python logging to be emitted
40
on a PUB socket. The main difference between a PUBHandler and a regular logging Handler is
41
the inclusion of topics. For the most basic logging, you can simply create a PUBHandler
42
with an interface or a configured PUB socket, and just let it go::
44
pub = context.socket(zmq.PUB)
45
pub.bind('tcp://*:12345')
46
handler = PUBHandler(pub)
47
logger = logging.getLogger()
48
logger.addHandler(handler)
50
At this point, all messages logged with the default logger will be broadcast on the pub
53
the PUBHandler does work with topics, and the handler has an attribute ``root_topic``::
55
handler.root_topic = 'myprogram'
57
Python loggers also have loglevels. The base topic of messages emitted by the PUBHandler
58
will be of the form: ``<handler.root_topic>.<loglevel>``, e.g. 'myprogram.INFO' or
59
'whatever.ERROR'. This way, subscribers can easily subscribe to subsets of the logging
60
messages. Log messages are always two-part, where the first part is the topic tree, and
61
the second part is the actual log message.
63
>>> logger.info('hello there')
64
>>> print sub.recv_multipart()
65
['myprogram.INFO', 'hello there']
70
You can also add to the topic tree below the loglevel on an individual message basis.
71
Assuming your logger is connected to a PUBHandler, you can add as many additional topics
72
on the front of the message, which will be added always after the loglevel. A special
73
delimiter defined at ``zmq.log.handlers.TOPIC_DELIM`` is scanned by the PUBHandler, so if
74
you pass your own subtopics prior to that symbol, they will be stripped from the message
75
and added to the topic tree::
77
>>> log_msg = "hello there"
78
>>> subtopic = "sub.topic"
79
>>> msg = zmq.log.handlers.TOPIC_DELIM.join([subtopic, log_msg])
81
>>> print sub.recv_multipart()
82
['myprogram.WARN.sub.topic', 'hello there']