如何设置HTTPHandler进行python日志记录

时间:2018-07-25 18:10:04

标签: python python-3.x logging python-requests httphandler

我正在尝试使用标准python日志记录库的HTTPHandler类发送日志。我需要使用基本凭据(用户名和密码)发出https发布请求。这就是我设置HTTPHandler-

的方式
    host = 'example.com'
    url = '/path'
    handler = logging.handlers.HTTPHandler(host, url, method='POST', secure=True, credentials=('username','password'), context=None)
    logger.addHandler(handler)

但是问题是,我在远程服务器上没有收到任何日志,甚至没有从处理程序中看到任何异常。我是否错误地设置了处理程序参数?我可以使用简单的pythong http request-

发送类似的日志
url = 'https://username:password@example.com/path'
headers = {'content-type': 'application/json'}
jsonLog = { 'id': '4444','level': 'info', 'message': 'python log' };

r = requests.post(url, data = json.dumps(jsonLog), headers=headers)

由于json内容类型,我是否需要以某种方式设置标头?如果可以,那么如何在httphandler中进行设置?

更新

我认为我应该更新自己最终做的事情。经过大量搜索之后,我发现我可以通过覆盖logging.Handler的emit()创建一个自定义处理程序。

class CustomHandler(logging.Handler):
def emit(self, record):
    log_entry = self.format(record)
    # some code....
    url = 'url'
    # some code....
    return requests.post(url, log_entry, headers={"Content-type": "application/json"}).content

如果有任何更好的建议,请随时发表。

2 个答案:

答案 0 :(得分:2)

您将需要继承HTTPHandler的子类并重写emit()方法以执行所需的操作。您可以使用HTTPHandler.emit()的当前实现作为指导。

答案 1 :(得分:0)

扩展提供的解决方案saz,以下是添加自定义HTTP处理程序的方法: 将使用承载令牌将发出的日志转发到指定的URL。

它使用请求会话,而不必在每个日志中都建立一个新会话 事件。

此外,如果请求失败,它将尝试为给定的重试次数重新发送日志。

注意:请确保您的日志记录处理程序尽可能简单,以防止由于发生日志事件而导致应用程序停止运行。

我用一个简单的localhost回显服务器对其进行了测试,并且可以正常工作。

请随时提出任何更改。

import json
import logging
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

class CustomHttpHandler(logging.Handler):
    def __init__(self, url: str, token: str, silent: bool = True):
        '''
        Initializes the custom http handler
        Parameters:
            url (str): The URL that the logs will be sent to
            token (str): The Authorization token being used
            silent (bool): If False the http response and logs will be sent 
                           to STDOUT for debug
        '''
        self.url = url
        self.token = token
        self.silent = silent

        # sets up a session with the server
        self.MAX_POOLSIZE = 100
        self.session = session = requests.Session()
        session.headers.update({
            'Content-Type': 'application/json',
            'Authorization': 'Bearer %s' % (self.token)
        })
        self.session.mount('https://', HTTPAdapter(
            max_retries=Retry(
                total=5,
                backoff_factor=0.5,
                status_forcelist=[403, 500]
            ),
            pool_connections=self.MAX_POOLSIZE,
            pool_maxsize=self.MAX_POOLSIZE
        ))

        super().__init__()

    def emit(self, record):
        '''
        This function gets called when a log event gets emitted. It recieves a
        record, formats it and sends it to the url
        Parameters:
            record: a log record
        '''
        logEntry = self.format(record)
        response = self.session.post(self.url, data=logEntry)

        if not self.silent:
            print(logEntry)
            print(response.content)

# create logger
log = logging.getLogger('')
log.setLevel(logging.INFO)

# create formatter - this formats the log messages accordingly
formatter = logging.Formatter(json.dumps({
    'time': '%(asctime)s',
    'pathname': '%(pathname)s',
    'line': '%(lineno)d',
    'logLevel': '%(levelname)s',
    'message': '%(message)s'
}))

# create a custom http logger handler
httpHandler = CustomHttpHandler(
    url='<YOUR_URL>',
    token='<YOUR_TOKEN>',
    silent=False
)

httpHandler.setLevel(logging.INFO)

# add formatter to custom http handler
httpHandler.setFormatter(formatter)

# add handler to logger
log.addHandler(httpHandler)

log.info('Hello world!')