mirror of
https://github.com/aykhans/AzSuicideDataVisualization.git
synced 2025-07-02 06:22:25 +00:00
first commit
This commit is contained in:
0
.venv/Lib/site-packages/zmq/log/__init__.py
Normal file
0
.venv/Lib/site-packages/zmq/log/__init__.py
Normal file
132
.venv/Lib/site-packages/zmq/log/__main__.py
Normal file
132
.venv/Lib/site-packages/zmq/log/__main__.py
Normal file
@ -0,0 +1,132 @@
|
||||
"""pyzmq log watcher.
|
||||
|
||||
Easily view log messages published by the PUBHandler in zmq.log.handlers
|
||||
|
||||
Designed to be run as an executable module - try this to see options:
|
||||
python -m zmq.log -h
|
||||
|
||||
Subscribes to the '' (empty string) topic by default which means it will work
|
||||
out-of-the-box with a PUBHandler object instantiated with default settings.
|
||||
If you change the root topic with PUBHandler.setRootTopic() you must pass
|
||||
the value to this script with the --topic argument.
|
||||
|
||||
Note that the default formats for the PUBHandler object selectively include
|
||||
the log level in the message. This creates redundancy in this script as it
|
||||
always prints the topic of the message, which includes the log level.
|
||||
Consider overriding the default formats with PUBHandler.setFormat() to
|
||||
avoid this issue.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# encoding: utf-8
|
||||
|
||||
# Copyright (C) PyZMQ Developers
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
from typing import Dict
|
||||
|
||||
import zmq
|
||||
|
||||
parser = argparse.ArgumentParser('ZMQ Log Watcher')
|
||||
parser.add_argument('zmq_pub_url', type=str, help='URL to a ZMQ publisher socket.')
|
||||
parser.add_argument(
|
||||
'-t',
|
||||
'--topic',
|
||||
type=str,
|
||||
default='',
|
||||
help='Only receive messages that start with this topic.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--timestamp', action='store_true', help='Append local time to the log messages.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--separator',
|
||||
type=str,
|
||||
default=' | ',
|
||||
help='String to print between topic and message.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--dateformat',
|
||||
type=str,
|
||||
default='%Y-%d-%m %H:%M',
|
||||
help='Set alternative date format for use with --timestamp.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--align',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Try to align messages by the width of their topics.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--color',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Color the output based on the error level. Requires the colorama module.',
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
if args.color:
|
||||
import colorama
|
||||
|
||||
colorama.init()
|
||||
colors = {
|
||||
'DEBUG': colorama.Fore.LIGHTCYAN_EX,
|
||||
'INFO': colorama.Fore.LIGHTWHITE_EX,
|
||||
'WARNING': colorama.Fore.YELLOW,
|
||||
'ERROR': colorama.Fore.LIGHTRED_EX,
|
||||
'CRITICAL': colorama.Fore.LIGHTRED_EX,
|
||||
'__RESET__': colorama.Fore.RESET,
|
||||
}
|
||||
else:
|
||||
colors = {}
|
||||
|
||||
|
||||
ctx = zmq.Context()
|
||||
sub = ctx.socket(zmq.SUB)
|
||||
sub.subscribe(args.topic.encode("utf8"))
|
||||
sub.connect(args.zmq_pub_url)
|
||||
|
||||
topic_widths: Dict[int, int] = {}
|
||||
|
||||
while True:
|
||||
try:
|
||||
if sub.poll(10, zmq.POLLIN):
|
||||
topic, msg = sub.recv_multipart()
|
||||
topics = topic.decode('utf8').strip().split('.')
|
||||
|
||||
if args.align:
|
||||
topics.extend(' ' for extra in range(len(topics), len(topic_widths)))
|
||||
aligned_parts = []
|
||||
for key, part in enumerate(topics):
|
||||
topic_widths[key] = max(len(part), topic_widths.get(key, 0))
|
||||
fmt = ''.join(('{:<', str(topic_widths[key]), '}'))
|
||||
aligned_parts.append(fmt.format(part))
|
||||
|
||||
if len(topics) == 1:
|
||||
level = topics[0]
|
||||
else:
|
||||
level = topics[1]
|
||||
|
||||
fields = {
|
||||
'msg': msg.decode('utf8').strip(),
|
||||
'ts': datetime.now().strftime(args.dateformat) + ' '
|
||||
if args.timestamp
|
||||
else '',
|
||||
'aligned': '.'.join(aligned_parts)
|
||||
if args.align
|
||||
else topic.decode('utf8').strip(),
|
||||
'color': colors.get(level, ''),
|
||||
'color_rst': colors.get('__RESET__', ''),
|
||||
'sep': args.separator,
|
||||
}
|
||||
print('{ts}{color}{aligned}{sep}{msg}{color_rst}'.format(**fields))
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
|
||||
sub.disconnect(args.zmq_pub_url)
|
||||
if args.color:
|
||||
print(colorama.Fore.RESET)
|
197
.venv/Lib/site-packages/zmq/log/handlers.py
Normal file
197
.venv/Lib/site-packages/zmq/log/handlers.py
Normal file
@ -0,0 +1,197 @@
|
||||
"""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:
|
||||
|
||||
https://github.com/jtriley/StarCluster/blob/StarCluster-0.91/starcluster/logger.py
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
# Copyright (C) PyZMQ Developers
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
from typing import Optional, Union
|
||||
|
||||
import zmq
|
||||
|
||||
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")
|
||||
"""
|
||||
|
||||
ctx: zmq.Context
|
||||
socket: zmq.Socket
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
interface_or_socket: Union[str, zmq.Socket],
|
||||
context: Optional[zmq.Context] = None,
|
||||
root_topic: str = '',
|
||||
) -> None:
|
||||
logging.Handler.__init__(self)
|
||||
self.root_topic = root_topic
|
||||
self.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"
|
||||
),
|
||||
}
|
||||
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)
|
||||
|
||||
@property
|
||||
def root_topic(self) -> str:
|
||||
return self._root_topic
|
||||
|
||||
@root_topic.setter
|
||||
def root_topic(self, value: str):
|
||||
self.setRootTopic(value)
|
||||
|
||||
def setRootTopic(self, root_topic: str):
|
||||
"""Set the root topic for this handler.
|
||||
|
||||
This value is prepended to all messages published by this handler, and it
|
||||
defaults to the empty string ''. When you subscribe to this socket, you must
|
||||
set your subscription to an empty string, or to at least the first letter of
|
||||
the binary representation of this string to ensure you receive any messages
|
||||
from this handler.
|
||||
|
||||
If you use the default empty string root topic, messages will begin with
|
||||
the binary representation of the log level string (INFO, WARN, etc.).
|
||||
Note that ZMQ SUB sockets can have multiple subscriptions.
|
||||
"""
|
||||
if isinstance(root_topic, bytes):
|
||||
root_topic = root_topic.decode("utf8")
|
||||
self._root_topic = root_topic
|
||||
|
||||
def setFormatter(self, fmt, level=logging.NOTSET):
|
||||
"""Set the Formatter for this handler.
|
||||
|
||||
If no level is provided, the same format is used for all levels. This
|
||||
will overwrite all selective formatters set in the object constructor.
|
||||
"""
|
||||
if level == logging.NOTSET:
|
||||
for fmt_level in self.formatters.keys():
|
||||
self.formatters[fmt_level] = fmt
|
||||
else:
|
||||
self.formatters[level] = fmt
|
||||
|
||||
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 ValueError:
|
||||
topic = ""
|
||||
try:
|
||||
bmsg = self.format(record).encode("utf8")
|
||||
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 = '.'.join(topic_list).encode("utf8")
|
||||
|
||||
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, f'{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
|
||||
),
|
||||
)
|
Reference in New Issue
Block a user