/usr/lib/python2.7/dist-packages/zmq/log/handlers.py is in python-zmq 15.2.0-0ubuntu4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | """pyzmq logging handlers.
This mainly defines the PUBHandler object for publishing logging messages over
a zmq.PUB socket.
The PUBHandler can be used with the regular logging module, as in::
>>> import logging
>>> handler = PUBHandler('tcp://127.0.0.1:12345')
>>> handler.root_topic = 'foo'
>>> logger = logging.getLogger('foobar')
>>> logger.setLevel(logging.DEBUG)
>>> logger.addHandler(handler)
After this point, all messages logged by ``logger`` will be published on the
PUB socket.
Code adapted from StarCluster:
http://github.com/jtriley/StarCluster/blob/master/starcluster/logger.py
"""
# Copyright (C) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
import logging
from logging import INFO, DEBUG, WARN, ERROR, FATAL
import zmq
from zmq.utils.strtypes import bytes, unicode, cast_bytes
TOPIC_DELIM="::" # delimiter for splitting topics on the receiving end.
class PUBHandler(logging.Handler):
"""A basic logging handler that emits log messages through a PUB socket.
Takes a PUB socket already bound to interfaces or an interface to bind to.
Example::
sock = context.socket(zmq.PUB)
sock.bind('inproc://log')
handler = PUBHandler(sock)
Or::
handler = PUBHandler('inproc://loc')
These are equivalent.
Log messages handled by this handler are broadcast with ZMQ topics
``this.root_topic`` comes first, followed by the log level
(DEBUG,INFO,etc.), followed by any additional subtopics specified in the
message by: log.debug("subtopic.subsub::the real message")
"""
root_topic=""
socket = None
formatters = {
logging.DEBUG: logging.Formatter(
"%(levelname)s %(filename)s:%(lineno)d - %(message)s\n"),
logging.INFO: logging.Formatter("%(message)s\n"),
logging.WARN: logging.Formatter(
"%(levelname)s %(filename)s:%(lineno)d - %(message)s\n"),
logging.ERROR: logging.Formatter(
"%(levelname)s %(filename)s:%(lineno)d - %(message)s - %(exc_info)s\n"),
logging.CRITICAL: logging.Formatter(
"%(levelname)s %(filename)s:%(lineno)d - %(message)s\n")}
def __init__(self, interface_or_socket, context=None):
logging.Handler.__init__(self)
if isinstance(interface_or_socket, zmq.Socket):
self.socket = interface_or_socket
self.ctx = self.socket.context
else:
self.ctx = context or zmq.Context()
self.socket = self.ctx.socket(zmq.PUB)
self.socket.bind(interface_or_socket)
def format(self,record):
"""Format a record."""
return self.formatters[record.levelno].format(record)
def emit(self, record):
"""Emit a log message on my socket."""
try:
topic, record.msg = record.msg.split(TOPIC_DELIM,1)
except Exception:
topic = ""
try:
bmsg = cast_bytes(self.format(record))
except Exception:
self.handleError(record)
return
topic_list = []
if self.root_topic:
topic_list.append(self.root_topic)
topic_list.append(record.levelname)
if topic:
topic_list.append(topic)
btopic = b'.'.join(cast_bytes(t) for t in topic_list)
self.socket.send_multipart([btopic, bmsg])
class TopicLogger(logging.Logger):
"""A simple wrapper that takes an additional argument to log methods.
All the regular methods exist, but instead of one msg argument, two
arguments: topic, msg are passed.
That is::
logger.debug('msg')
Would become::
logger.debug('topic.sub', 'msg')
"""
def log(self, level, topic, msg, *args, **kwargs):
"""Log 'msg % args' with level and topic.
To pass exception information, use the keyword argument exc_info
with a True value::
logger.log(level, "zmq.fun", "We have a %s",
"mysterious problem", exc_info=1)
"""
logging.Logger.log(self, level, '%s::%s'%(topic,msg), *args, **kwargs)
# Generate the methods of TopicLogger, since they are just adding a
# topic prefix to a message.
for name in "debug warn warning error critical fatal".split():
meth = getattr(logging.Logger,name)
setattr(TopicLogger, name,
lambda self, level, topic, msg, *args, **kwargs:
meth(self, level, topic+TOPIC_DELIM+msg,*args, **kwargs))
|