logconfig.py
博客专区 > kuerant 的博客 > 博客详情
logconfig.py
kuerant 发表于5年前
logconfig.py
  • 发表于 5年前
  • 阅读 102
  • 收藏 0
  • 点赞 0
  • 评论 0

实现 python logging client & server的配置,借鉴了 tornadoweb的日志配置模块。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#

__VERSION__='0.1.0'


import datetime
import logging
import logging.handlers
import re
import sys
import time

import pickle
import SocketServer
import struct


# For pretty log messages, if available
try:
    import curses
except:
    curses = None


# max size of log files before rollover
LOG_FILE_MAX_SIZE = 128 * 1024 * 1024

# number of log files to keep
LOG_FILE_NUM_BACKUPS = 10


def configure( level='info', file_prefix=None, file_max_size=0, file_num_backups=0, servers='' ) :
    """Turns on formatted logging output as configured."""

    root_logger = logging.getLogger()

    if not level :
        level = 'info'
    root_logger.setLevel(getattr(logging, level.upper()))

    if file_prefix:
        if not file_max_size :
            file_max_size = LOG_FILE_MAX_SIZE
        if not file_num_backups :
            file_num_backups = LOG_FILE_NUM_BACKUPS

        channel = logging.handlers.RotatingFileHandler(
                        filename = file_prefix,
                        maxBytes = file_max_size,
                        backupCount = file_num_backups )
        channel.setFormatter( _LogFormatter(color=False) )
        root_logger.addHandler( channel )

    elif not root_logger.handlers :
        # Set up color if we are in a tty and curses is installed
        color = False
        if curses and sys.stderr.isatty():
            try:
                curses.setupterm()
                if curses.tigetnum("colors") > 0:
                    color = True
            except:
                pass
        channel = logging.StreamHandler()
        channel.setFormatter(_LogFormatter(color=color))
        root_logger.addHandler(channel)

    #host = '127.0.0.1'
    #port = logging.handlers.DEFAULT_TCP_LOGGING_PORT
    ## servers FORMAT : SERVER1:PORT1,SERVER2:PORT2,SERVER3:PORT3
    if servers :
        server_list = [ x.strip() for x in servers.split(',') ]
        for server in server_list :
            host,port = server.split(':')
            socketHandler = logging.handlers.SocketHandler(host, int(port))
            root_logger.addHandler(socketHandler)

    #### configure()



class _LogFormatter(logging.Formatter):

    def __init__(self, color, *args, **kwargs):
        logging.Formatter.__init__(self, *args, **kwargs)
        self._color = color
        if color:
            fg_color = curses.tigetstr("setaf") or curses.tigetstr("setf") or ""
            self._colors = {
                logging.DEBUG: curses.tparm(fg_color, 4), # Blue
                logging.INFO: curses.tparm(fg_color, 2), # Green
                logging.WARNING: curses.tparm(fg_color, 3), # Yellow
                logging.ERROR: curses.tparm(fg_color, 1), # Red
            }
            self._normal = curses.tigetstr("sgr0")

    def format(self, record):
        try:
            record.message = record.getMessage()
        except Exception, e:
            record.message = "Bad message (%r): %r" % (e, record.__dict__)
        record.asctime = time.strftime(
            "%Y-%m-%d %H:%M:%S", self.converter(record.created))
        prefix = '%(asctime)s %(levelname)1.1s %(name)s %(process)d %(module)s:%(lineno)d' % \
            record.__dict__
        if self._color:
            prefix = (self._colors.get(record.levelno, self._normal) +
                      prefix + self._normal)
        formatted = prefix + " " + record.message
        if record.exc_info:
            if not record.exc_text:
                record.exc_text = self.formatException(record.exc_info)
        if record.exc_text:
            formatted = formatted.rstrip() + "\n" + record.exc_text
        return formatted.replace("\n", "\n    ")


    #### _LogFormatter


########----------------        ########        ----------------########


class LogRecordStreamHandler(SocketServer.StreamRequestHandler):
    """Handler for a streaming logging request.

    This basically logs the record using whatever logging policy is
    configured locally.
    """

    def handle(self):
        """
        Handle multiple requests - each expected to be a 4-byte length,
        followed by the LogRecord in pickle format. Logs the record
        according to whatever policy is configured locally.
        """
        while True:
            chunk = self.connection.recv(4)
            if len(chunk) < 4:
                break
            slen = struct.unpack('>L', chunk)[0]
            chunk = self.connection.recv(slen)
            while len(chunk) < slen:
                chunk = chunk + self.connection.recv(slen - len(chunk))
            obj = self.unPickle(chunk)
            record = logging.makeLogRecord(obj)
            self.handleLogRecord(record)

    def unPickle(self, data):
        return pickle.loads(data)

    def handleLogRecord(self, record):
        # if a name is specified, we use the named logger rather than the one
        # implied by the record.
        if self.server.logname is not None:
            name = self.server.logname
        else:
            name = record.name
        logger = logging.getLogger(name)
        # N.B. EVERY record gets logged. This is because Logger.handle
        # is normally called AFTER logger-level filtering. If you want
        # to do filtering, do it at the client end to save wasting
        # cycles and network bandwidth!
        logger.handle(record)

class LogServer(SocketServer.ThreadingTCPServer):
    """
    Simple TCP socket-based logging receiver suitable for testing.
    """

    allow_reuse_address = 1

    def __init__(self, host='0.0.0.0',
                 port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
                 handler=LogRecordStreamHandler,
                 level='info', file_prefix=None, file_max_size=0, file_num_backups=0 ):
        SocketServer.ThreadingTCPServer.__init__(self, (host, port), handler)
        self.abort = 0
        self.timeout = 1
        self.logname = None

        configure( level, file_prefix, file_max_size, file_num_backups )
        #### __init__()


    def serve_until_stopped(self):
        import select
        abort = 0
        while not abort:
            rd, wr, ex = select.select([self.socket.fileno()],
                                       [], [],
                                       self.timeout)
            if rd:
                self.handle_request()
            abort = self.abort

        #### serve_until_stopped()            

    #### class LogServer

#def main():
#    s = LogServer()
#    #print('start LOG server...')
#    s.serve_until_stopped()
def test3() :
    configure(level='debug', file_prefix='test.log')

    logger = logging.getLogger()
    logger.fatal(">>>FATAL<<< %s", 'Hello, World.')
    logger.error(">>>ERROR<<< %s", 'Hello, World.')
    logger.warn(">>> WARN<<< %s", 'Hello, World.')
    logger.info(">>> INFO<<< %s", 'Hello, World.')
    logger.debug(">>>DEBUG<<< %s", 'Hello, World.')

    logger = logging.getLogger('test3')
    logger.fatal(">>>FATAL<<< %s", 'Hello, World.')
    logger.error(">>>ERROR<<< %s", 'Hello, World.')
    logger.warn(">>> WARN<<< %s", 'Hello, World.')
    logger.info(">>> INFO<<< %s", 'Hello, World.')
    logger.debug(">>>DEBUG<<< %s", 'Hello, World.')

    #### test3()

 

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#

import sys, os, os.path, time
import signal

from tbox import logconfig


HOST = '0.0.0.0'
PORT = 9020

LOG_PREFIX = '/home/s/logs/pylogd/9020.log'
LOG_SIZE   = 512 * 1024 * 1024
LOG_BACKUP = 2000
log_server = None

def signal_handler(sig, flags) :
    global  log_server
    
    if log_server : log_server.shutdown()
    #### signal_handler()
 

if __name__ == '__main__' :
    signal.signal( signal.SIGINT, signal_handler )
    signal.signal( signal.SIGQUIT, signal_handler )
    signal.signal( signal.SIGTERM, signal_handler )
    log_server = logconfig.LogServer( host=HOST, port=PORT, file_prefix=LOG_PREFIX, file_max_size=LOG_SIZE, file_num_backups=LOG_BACKUP )
    #s.serve_until_stopped()
    log_server.serve_forever()

logging setting code

# Logging, obviously
logger = logging.getLogger('nsq')
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(filename)s@%(lineno)d: %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)

共有 人打赏支持
粉丝 9
博文 52
码字总数 12502
×
kuerant
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: