我正在尝试使用标准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
如果有任何更好的建议,请随时发表。
答案 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!')