我有一个利用多线程的应用程序,它在服务器的后台运行。为了监视应用程序而不必登录服务器,我决定包括Bottle以便响应一些HTTP端点并报告状态,执行远程关闭等。
我还想添加一种查询日志文件的方法。我可以使用FileHandler
登录并在请求网址时发送目标文件(例如/log
)。
但是,我想知道是否可以实现类似RotatingFileHandler
的东西,而不是登录到文件,而是登录到变量(例如BytesIO
)。这样,我可以将日志限制为最新信息,而同时又可以将文本作为文本而不是单独的文件下载返回给浏览器。RotatingFileHandler
需要文件名,因此不能将BytesIO
流传递给它。记录到变量本身是完全可行的(例如Capturing Python Log Output In A Variable),但是我对如何执行滚动部分有些困惑。
任何想法,暗示,建议将不胜感激。
最佳答案
使用Capturing Python Log Output In A Variable中描述的技术,但是将其捕获到一个自定义流中,该流将丢弃旧数据。
像这样:
# Adapted from http://alanwsmith.com/capturing-python-log-output-in-a-variable
import logging
import io
import collections
class FIFOIO(io.TextIOBase):
def __init__(self, size, *args):
self.maxsize = size
io.TextIOBase.__init__(self, *args)
self.deque = collections.deque()
def getvalue(self):
return ''.join(self.deque)
def write(self, x):
self.deque.append(x)
self.shrink()
def shrink(self):
if self.maxsize is None:
return
size = sum(len(x) for x in self.deque)
while size > self.maxsize:
x = self.deque.popleft()
size -= len(x)
### Create the logger
logger = logging.getLogger('basic_logger')
logger.setLevel(logging.DEBUG)
### Setup the console handler with a FIFOIO object
log_capture_string = FIFOIO(256)
ch = logging.StreamHandler(log_capture_string)
ch.setLevel(logging.DEBUG)
### Optionally add a formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
### Add the console handler to the logger
logger.addHandler(ch)
### Send log messages.
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
### Pull the contents back into a string and close the stream
log_contents = log_capture_string.getvalue()
log_capture_string.close()
### Output as lower case to prove it worked.
print(log_contents.lower())