使用 aiohttp.ClientSession() 发出请求时如何为 aiohttp.client 设置日志记录?
How to set up logging for aiohttp.client when making request with aiohttp.ClientSession()?
我有一些代码对某些 API 进行请求序列。我想为所有人设置通用日志记录,我该如何设置?
假设我的代码如下所示
import aiohttp
import asyncio
async def fetch(client):
async with client.get('http://httpbin.org/get') as resp:
assert resp.status == 200
return await resp.text()
async def post_data(client):
async with client.post('http://httpbin.org/post', data={'foo': 'bar'}) as resp:
assert resp.status == 200
return await resp.text()
async def main(loop):
async with aiohttp.ClientSession(loop=loop) as client:
html = await fetch(client)
print(html)
other_html = await post_data(client)
print(other_html)
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
现在我想查看状态代码,url,headers 以及所有发出的所有请求,因此日志中的输出如下所示:
2017-08-09 08:44:30 DEBUG (200) <GET http://httpbin.org/get>
2017-08-09 08:44:30 DEBUG (200) <POST http://httpbin.org/post>
我知道我可以在每个请求后添加 logger.log() 调用,但那会是重复的。如果我有更多请求,我将不得不在每个调用 logger.log 的请求下编写重复代码。似乎效率低下。
有aiohttp.client logger,但没有详细说明如何设置。
我正在尝试这样设置
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
logging.getLogger('aiohttp.client').addHandler(ch)
但它不打印我想看到的信息(例如响应状态代码,url)。
有什么方法可以实现我所需要的吗?也许我可以订阅来自客户端的一些信号并在发送信号时记录一些消息?例如。有一些机制可以订阅客户端收到响应时发送的信号,然后在上面记录消息吗?
正如您在 aiohttp 的代码中看到的,aiohttp.client 记录器不用于记录请求,但只能在响应中的 cookie 无效时记录警告
https://github.com/aio-libs/aiohttp/search?utf8=%E2%9C%93&q=client_logger&type=
要记录您正在执行的每个请求,您需要创建一个自定义 ClientSession
来执行您想要的操作。类似于:
class LoggingClientSession(aiohttp.ClientSession):
def request(self, method, url, **kwargs):
logger.debug('Starting request <%s %r>', method, url)
return super().request(method, url, **kwargs)
-
正如 Jaanus 在此处的评论中指出的那样,post
、get
、……助手现在直接调用 ClientSession._request
,而不是 request
。因此覆盖后者不会拦截使用速记助手进行的调用。
因此您可以:
在你的助手中覆盖 _request
而不是 request
或者确保您的代码从不使用 get
/... 助手,并且总是直接调用 request
。
或者在 LoggingClientSession
中定义所有辅助方法
-
正如 Romuald 所指出的,_request
现在是一个协程,因此用常规函数覆盖它不会在正确的时间记录。这是一个更新的示例:
class LoggingClientSession(aiohttp.ClientSession):
async def _request(self, method, url, **kwargs):
logger.debug('Starting request <%s %r>', method, url)
return await super()._request(method, url, **kwargs)
在撰写本文时 (11/2020),您应该使用 tracing functionality of aiohttp:
import asyncio
import logging
import aiohttp
async def on_request_start(session, context, params):
logging.getLogger('aiohttp.client').debug(f'Starting request <{params}>')
async def main():
logging.basicConfig(level=logging.DEBUG)
trace_config = aiohttp.TraceConfig()
trace_config.on_request_start.append(on_request_start)
async with aiohttp.ClientSession(trace_configs=[trace_config]) as session:
await session.get('https://google.com')
asyncio.run(main())
我有一些代码对某些 API 进行请求序列。我想为所有人设置通用日志记录,我该如何设置?
假设我的代码如下所示
import aiohttp
import asyncio
async def fetch(client):
async with client.get('http://httpbin.org/get') as resp:
assert resp.status == 200
return await resp.text()
async def post_data(client):
async with client.post('http://httpbin.org/post', data={'foo': 'bar'}) as resp:
assert resp.status == 200
return await resp.text()
async def main(loop):
async with aiohttp.ClientSession(loop=loop) as client:
html = await fetch(client)
print(html)
other_html = await post_data(client)
print(other_html)
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
现在我想查看状态代码,url,headers 以及所有发出的所有请求,因此日志中的输出如下所示:
2017-08-09 08:44:30 DEBUG (200) <GET http://httpbin.org/get>
2017-08-09 08:44:30 DEBUG (200) <POST http://httpbin.org/post>
我知道我可以在每个请求后添加 logger.log() 调用,但那会是重复的。如果我有更多请求,我将不得不在每个调用 logger.log 的请求下编写重复代码。似乎效率低下。
有aiohttp.client logger,但没有详细说明如何设置。
我正在尝试这样设置
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
logging.getLogger('aiohttp.client').addHandler(ch)
但它不打印我想看到的信息(例如响应状态代码,url)。
有什么方法可以实现我所需要的吗?也许我可以订阅来自客户端的一些信号并在发送信号时记录一些消息?例如。有一些机制可以订阅客户端收到响应时发送的信号,然后在上面记录消息吗?
正如您在 aiohttp 的代码中看到的,aiohttp.client 记录器不用于记录请求,但只能在响应中的 cookie 无效时记录警告 https://github.com/aio-libs/aiohttp/search?utf8=%E2%9C%93&q=client_logger&type=
要记录您正在执行的每个请求,您需要创建一个自定义 ClientSession
来执行您想要的操作。类似于:
class LoggingClientSession(aiohttp.ClientSession):
def request(self, method, url, **kwargs):
logger.debug('Starting request <%s %r>', method, url)
return super().request(method, url, **kwargs)
-
正如 Jaanus 在此处的评论中指出的那样,post
、get
、……助手现在直接调用 ClientSession._request
,而不是 request
。因此覆盖后者不会拦截使用速记助手进行的调用。
因此您可以:
在你的助手中覆盖
_request
而不是request
或者确保您的代码从不使用
get
/... 助手,并且总是直接调用request
。或者在
LoggingClientSession
中定义所有辅助方法
-
正如 Romuald 所指出的,_request
现在是一个协程,因此用常规函数覆盖它不会在正确的时间记录。这是一个更新的示例:
class LoggingClientSession(aiohttp.ClientSession):
async def _request(self, method, url, **kwargs):
logger.debug('Starting request <%s %r>', method, url)
return await super()._request(method, url, **kwargs)
在撰写本文时 (11/2020),您应该使用 tracing functionality of aiohttp:
import asyncio
import logging
import aiohttp
async def on_request_start(session, context, params):
logging.getLogger('aiohttp.client').debug(f'Starting request <{params}>')
async def main():
logging.basicConfig(level=logging.DEBUG)
trace_config = aiohttp.TraceConfig()
trace_config.on_request_start.append(on_request_start)
async with aiohttp.ClientSession(trace_configs=[trace_config]) as session:
await session.get('https://google.com')
asyncio.run(main())