Python logging中集成Scribe

Scribe是跨语言的日志聚合框架,如何在Python中使用它呢?其在Python中的简单使用方法如下:

#!/usr/bin/env python
#
encoding: utf8

"""scribe_cat: A simple script for sending messages to scribe."""
__author__ = 'zhoubo'

import sys
from scribe import scribe
from thrift.transport import TTransport, TSocket
from thrift.protocol import TBinaryProtocol

if len(sys.argv) == 2:
category = sys.argv[1]
host = '127.0.0.1'
port = 1463
elif len(sys.argv) == 4 and sys.argv[1] == '-h':
category = sys.argv[3]
host_port = sys.argv[2].split(':')
host = host_port[0]
if len(host_port) > 1:
port = int(host_port[1])
else:
port = 1463
else:
sys.exit('usage (message is stdin): scribe_cat [-h host[:port]] category')

log_entry = scribe.LogEntry(category=category, message=sys.stdin.read())

socket = TSocket.TSocket(host=host, port=port)
transport = TTransport.TFramedTransport(socket)
protocol = TBinaryProtocol.TBinaryProtocol(trans=transport, strictRead=False, strictWrite=False)
client = scribe.Client(iprot=protocol, oprot=protocol)

transport.open()
result = client.Log(messages=[log_entry])
transport.close()

if result == scribe.ResultCode.OK:
sys.exit()
elif result == scribe.ResultCode.TRY_LATER:
print >> sys.stderr, "TRY_LATER"
sys.exit(84) # 'T'
else:
sys.exit("Unknown error code.")

使用方式如下:

$echo "hello world" | ./scribe_cat [-h host[:port]] category

为了使程序更方便的使用Scribe日志聚合架构,我将scribe日志处理集成到python logging中,使其作为python logging中的一个Handler来使用Scribe系统。

下面是我修改的python logging源代码,增加部分见下方:

from scribe import scribe
from thrift.transport import TTransport, TSocket
from thrift.protocol import TBinaryProtocol

class ScribeHandler(StreamHandler):
"""
A handler class which writes formatted logging records to Scrbie Server
"""
client = None

def __init__(self, host='127.0.0.1', port=1464, category=None, delay=0):
"""
Open the specified file and use it as the stream for logging.
"""
if category is None:
category = 'root'
self.host = host
self.port = port
self.category = category
if delay:
self.stream = None
else:
stream = self._open()
StreamHandler.__init__(self, stream)

def close(self):
"""
Closes the stream.
"""
if self.stream:
self.flush()
if hasattr(self.stream, "close"):
self.stream.close()
StreamHandler.close(self)
self.stream = None

def _open(self):
"""
Open the current base file with the (original) mode and encoding.
Return the resulting stream.
"""
socket = TSocket.TSocket(host=self.host, port=self.port)
transport = TTransport.TFramedTransport(socket)
protocol = TBinaryProtocol.TBinaryProtocol(trans=transport, strictRead=False, strictWrite=False)
self.client = scribe.Client(iprot=protocol, oprot=protocol)
transport.open()
return transport

def emit(self, record):
"""
Emit a record.

If the stream was not opened because 'delay' was specified in the
constructor, open it before calling the superclass's emit.
"""
if self.stream is None:
stream = self._open()
StreamHandler.__init__(self, stream)
self.record(record)

def record(self, record):
"""
Emit a record.

If a formatter is specified, it is used to format the record.
The record is then written to the stream with a trailing newline. If
exception information is present, it is formatted using
traceback.print_exception and appended to the stream. If the stream
has an 'encoding' attribute, it is used to encode the message before
output to the stream.
"""
try:
msg = self.format(record)
fs = "%s\n"
log_entry = scribe.LogEntry(category=self.category, message=fs%msg)
#print msg,log_entry
if self.client is not None:
result = self.client.Log(messages=[log_entry])
if result == scribe.ResultCode.TRY_LATER:
sys.stderr.write("TRY_LATE")
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)

将/usr/lib/python2.6/logging/__init__.py文件替换为附件__init__.py 
测试实例:

[loggers]
keys=root,test

[handlers]
keys=consoleHandler,scribeHandler

[formatters]
keys=simpleFormatter,scribeFormatter

[formatter_simpleFormatter]
format=[%(asctime)s] - (%(levelname)s) : %(message)s

[formatter_scribeFormatter]
format=[192.168.0.55] - [%(asctime)s] - (%(levelname)s) : %(message)s

[logger_root]
level=WARN
handlers=consoleHandler

[logger_test]
level=INFO
qualname=test
handlers=scribeHandler

[handler_consoleHandler]
class=StreamHandler
level=INFO
formatter=simpleFormatter
args=(sys.stdout,)

[handler_scribeHandler]
class=ScribeHandler
level=INFO
formatter=scribeFormatter
args=('localhost', 1464, 'zhoubo',)

测试小程序:

#!/usr/bin/env python
#
encoding: utf8

import logging
import logging.config

logging.config.fileConfig("logging.config")

#create logger
logger = logging.getLogger("test")

#"application" code
logger.debug("debug message")
logger.info("info message")
logger.warn("warn message")
logger.error("error message")
logger.critical("critical message")

logHello = logging.getLogger("hello")
logHello.info("Hello world!")

posted @ 2011-11-01 02:07  残夜  阅读(1854)  评论(0编辑  收藏  举报