2017-10-15 49 views
0

我试图实现简单的日志处理程序,它使用Python的标准logging库来记录事件到远程服务器。所以我创建了自logging.Handler继承的自定义类,名为RemoteLogHandler,它接受LogRecord并将它发送到远程服务器。处理程序以标准addHandler()的方式附加到根记录器。实现无阻塞的远程日志处理程序

from urllib import requests 

class RemoteLogHandler(logging.Handler): 
    def emit(self, record): 
     remote_url = "http://foo.bar.baz" 
     req = request.Request(remote_url, data=record.msg) 
     request.urlopen(req, timeout=1) 

这按预期工作,但显然会导致调用线程锁定时remote_url变得不可访问或开始响应缓慢。所以我试图找出最好的方式使这个调用独立于调用线程。

我已经考虑:

  1. 包括一些非标准库,这将使HTTP请求的异步
  2. 使用QueueHandler和QueueListener所概述here
  3. 使用ASYNCIO

所有这些解决方案对于实现这样简单的任务似乎太复杂/不必要。为了使这个处理程序不被阻塞,是否有更好的方法来减少开销?

+0

您的应用程序不应该将其日志路由到任何地方,请参阅https://12factor.net/logs – jonrsharpe

+0

为什么你认为排队解决方案是过度复杂?这是唯一的解决方案:远程推送记录的工作线程,以及在发布记录时将记录添加到队列中的普通线程。 –

+0

您也可以切换到UDP流量,并只发送发送方法中的数据报,非阻塞。但是不能保证远程交付和处理(系统日志处理程序以这种方式工作,afaik)。 –

回答

0

对于任何将面对此问题的人来说,解决方案结果如简单here所述。

import queue 
from logging import QueueHandler, QueueListener 

# instantiate queue & attach it to handler 
log_queue = queue.Queue(-1) 
queue_handler = QueueHandler(log_queue) 

# instantiate our custom log handler (see question) 
remote_handler = RemoteLogHandler() 

# instantiate listener 
remote_listener = QueueListener(log_queue, remote_handler) 

# attach custom handler to root logger 
logging.getLogger().addHandler(queue_handler) 

# start the listener 
remote_listener.start() 

QueueListener运行在它自己的线程,听取由QueueHandlers导致非阻塞的日志发送的LogRecords。

相关问题