Aiohttp: Logging error

Created on 7 Mar 2016  路  19Comments  路  Source: aio-libs/aiohttp

I'm getting an error in the aiohttp.access logger related to an invalid log format.

ERROR:aiohttp.access:Error in logging
Traceback (most recent call last):
  File "aiohttp\helpers.py", line 365, in log
    [message, environ, response, transport, time]))
  File "aiohttp\helpers.py", line 352, in _format_line
    return tuple(m(args) for m in self._methods)
  File "aiohttp\helpers.py", line 352, in <genexpr>
    return tuple(m(args) for m in self._methods)
  File "aiohttp\helpers.py", line 309, in _format_a
    return args[3].get_extra_info('peername')[0]
AttributeError: 'NoneType' object has no attribute 'get_extra_info'

I'm using version 0.21.2 on Python 3.5.1 for Windows (x86 build).

The stack trace doesn't include any spec of the message, but from what I can make of it, the transport is None. I'm not sure why that would be the case for successful connections.

I'm getting this using the WebSocket server from a browser on the same machine as the WebSocket server (haven't tried remote to see if it makes a difference).

Is there any additional info I can get you that will help fix this?

Thanks!

outdated

All 19 comments

Showing args content would be nice.

Also might you provide access_log_format parameter from app.make_handler() if you specify it explicitly?

I use the default in app.make_handler().

I added this code:

    @staticmethod
    def _format_a(args):
        try:
            return args[3].get_extra_info('peername')[0]
        except AttributeError:
            import logging
            logging.exception('Accessing `peername` with args: %r.', args)
            raise

And I got this output when reproducing the problem (I indented for ease of reading):

ERROR:root:Accessing `peername` with args:
[
 RawRequestMessage(
  method='GET',
  path='/tunnel/cafebabe-0000-0000-0000-000000000001',
  version=HttpVersion(major=1, minor=1),
  headers=<CIMultiDict(
   'HOST': '127.0.0.1:8080',
   'CONNECTION': 'Upgrade',
   'PRAGMA': 'no-cache',
   'CACHE-CONTROL': 'no-cache',
   'UPGRADE': 'websocket',
   'ORIGIN': 'file://',
   'SEC-WEBSOCKET-VERSION': '13',
   'USER-AGENT': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36',
   'ACCEPT-ENCODING': 'gzip, deflate, sdch',
   'ACCEPT-LANGUAGE': 'en-US,en;q=0.8,fr;q=0.6',
   'SEC-WEBSOCKET-KEY': 'tSUNQBPedRNnyrjR1SN2fg==',
   'SEC-WEBSOCKET-EXTENSIONS': 'permessage-deflate; client_max_window_bits'
   )>,
  raw_headers=[
   (bytearray(b'HOST'), bytearray(b'127.0.0.1:8080')),
   (bytearray(b'CONNECTION'), bytearray(b'Upgrade')),
   (bytearray(b'PRAGMA'), bytearray(b'no-cache')),
   (bytearray(b'CACHE-CONTROL'), bytearray(b'no-cache')),
   (bytearray(b'UPGRADE'), bytearray(b'websocket')),
   (bytearray(b'ORIGIN'), bytearray(b'file://')),
   (bytearray(b'SEC-WEBSOCKET-VERSION'), bytearray(b'13')),
   (bytearray(b'USER-AGENT'), bytearray(b'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36')),
   (bytearray(b'ACCEPT-ENCODING'), bytearray(b'gzip, deflate, sdch')),
   (bytearray(b'ACCEPT-LANGUAGE'), bytearray(b'en-US,en;q=0.8,fr;q=0.6')),
   (bytearray(b'SEC-WEBSOCKET-KEY'), bytearray(b'tSUNQBPedRNnyrjR1SN2fg==')),
   (bytearray(b'SEC-WEBSOCKET-EXTENSIONS'), bytearray(b'permessage-deflate; client_max_window_bits'))
  ],
  should_close=False,
  compression=None
 ),
 None,
 <aiohttp.protocol.Response object at 0x03474570>,
 None,
 2.714000000152737
 ].

Hi @asvetlov, does this help?

I've tried looking at the code, but I'm having a hard time following. For all I can tell, this is the culprit:

class ServerHttpProtocol(aiohttp.StreamProtocol):
    def log_access(self, message, environ, response, time):
        if self.access_logger:
            self.access_logger.log(message, environ, response,
                                   self.transport, time)

It seems like self.transport becomes None in the call to ServerHttpProtocol.closing() and that log_access() is somehow called after that.

However, I'm having a hard time explaining why this is the case. Any ideas?

Thanks,

Andr茅

Hmm. Yes, looks like the only line that makes self.transport = None is ServerHttpProtocol.closing().

But it's called only on server finishing. Is it your case?

I can easy add a workaround to don't log transport info if it is None but really prefer to fix initial issue.

After quick review I see just dropping self.transport = None may solve the problem but I want to make more investigation and write a test at least.

Yes, I usually get this error when I send CTRL-C/SIGINT.

I also only get the the error if there are any pending connections.

In case it helps, here is my setup/teardown sequence:

async def main(arguments):
    """Run application."""
    arguments = cli.parse_args(arguments)

    app = aiohttp.web.Application()
    app.router.add_route('GET', '/tunnel/{profileid}', connection)
    app.router.add_route('GET', '/', index)

    cancel = asyncio.Future()
    def shutdown():
        if cancel.done():
            return
        cancel.set_result(None)
        loop.remove_signal_handler(signal.SIGINT)
    loop.add_signal_handler(signal.SIGINT, shutdown)

    handler = app.make_handler()
    server = await loop.create_server(
        handler, arguments.host, arguments.port
    )
    try:
        print('Serving at: http//%s:%d (CTRL-C to stop).' % (
            arguments.host,
            arguments.port,
        ))
        await cancel
    finally:
        server.close()
        await server.wait_closed()
        await handler.finish_connections(arguments.linger)
        await app.finish()

Just got the same error. Using aiohttp-wsgi to serve on a unix socket. Yeah, unix sockets don't have peer names, you should handle that.

Fixed by #889

Thanks!

I have found the same traceback with the last stable build (0.21.6).

Error in logging
Traceback (most recent call last):
  File "/home/datingdev/.virtualenvs/xo/lib/python3.5/site-packages/aiohttp/helpers.py", line 365, in log
    [message, environ, response, transport, time]))
  File "/home/datingdev/.virtualenvs/xo/lib/python3.5/site-packages/aiohttp/helpers.py", line 352, in _format_line
    return tuple(m(args) for m in self._methods)
  File "/home/datingdev/.virtualenvs/xo/lib/python3.5/site-packages/aiohttp/helpers.py", line 352, in <genexpr>
    return tuple(m(args) for m in self._methods)
  File "/home/datingdev/.virtualenvs/xo/lib/python3.5/site-packages/aiohttp/helpers.py", line 309, in _format_a
    return args[3].get_extra_info('peername')[0]
AttributeError: 'NoneType' object has no attribute 'get_extra_info'

I'm going to add more info as soon as I catch it again.

Should be fixed in next aiohttp release

I still have a similar issue with aiohttp-0.22.4.
I also use unix sockets, if it helps.

Traceback (most recent call last):
  File "/home/feeds/.local/lib64/python3.5/site-packages/aiohttp/helpers.py", line 405, in log
    [message, environ, response, transport, time]))
  File "/home/feeds/.local/lib64/python3.5/site-packages/aiohttp/helpers.py", line 392, in _format_line
    return tuple(m(args) for m in self._methods)
  File "/home/feeds/.local/lib64/python3.5/site-packages/aiohttp/helpers.py", line 392, in <genexpr>
    return tuple(m(args) for m in self._methods)
  File "/home/feeds/.local/lib64/python3.5/site-packages/aiohttp/helpers.py", line 348, in _format_a
    return args[3].get_extra_info('peername')[0] if args[3] is not None \
IndexError: index out of range
print(args[3].get_extra_info('peername'))

gives

b''

I never tested it on unix sockets.
Will add a fix for the case to don't crash.
But in general I recommend to never use %a formatting for your case: unix socket has no peer name at all.

Fixed by 8e8469b

Andrew, thanks, but I do not really understand, what you are talking about, I don't use any format at all. I use aiohttp_wsgi, where a Unix socket lives. How could I trace the exact place where it happens?

Ok, you've got default format string containing '%a'.
WSGIServerHttpProtocol accepts optional access_log_format, '%a %l %u %t "%r" %s %b "%{Referrer}i" "%{User-Agent}i"' by default.

This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a [new issue] for
related bugs.

If you feel like there's important points made in this discussion,
please include those exceprts into that [new issue].

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thehesiod picture thehesiod  路  4Comments

kbaston picture kbaston  路  3Comments

JulienPalard picture JulienPalard  路  3Comments

deckar01 picture deckar01  路  4Comments

rubenvdham picture rubenvdham  路  5Comments