如何使用aiohttp.ClientSession()发出请求时为aiohttp.client设置日志记录?

如何使用aiohttp.ClientSession()发出请求时为aiohttp.client设置日志记录?

问题描述:

我有一些代码向某些API发出请求的请求序列。我想为所有人建立通用日志记录,我如何设置它?如何使用aiohttp.ClientSession()发出请求时为aiohttp.client设置日志记录?

比方说,我的代码看起来像这样

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记录不用于登录请求,但是只能登录一个警告,如果在响应中的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直接。

  • 或还定义所有的helper方法在LoggingClientSession

+1

大包裹它在类中。很干净! –

+0

它看起来像'request'已被重命名'_request'。 –

+0

@JeremyBanks不,'_request'是一个不应该被修改的aiohttp内部。 'request'方法仍然存在,可以用来拦截所有的请求。参考https://github.com/aio-libs/aiohttp/blob/master/aiohttp/client。py#L139 – Arthur