繁体   English   中英

使用 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、标题和所有内容,因此日志中的输出如下所示:

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 logger 不是用来记录请求的,而是只能在响应中的 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 在此处的评论中所指出的, postget 、 ... 助手现在直接调用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),您应该使用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())

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM