Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logging error #816

Closed
AndreLouisCaron opened this issue Mar 7, 2016 · 19 comments
Closed

Logging error #816

AndreLouisCaron opened this issue Mar 7, 2016 · 19 comments
Labels
Milestone

Comments

@AndreLouisCaron
Copy link

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!

@asvetlov
Copy link
Member

asvetlov commented Mar 7, 2016

Showing args content would be nice.

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

@AndreLouisCaron
Copy link
Author

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
 ].

@AndreLouisCaron
Copy link
Author

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é

@asvetlov
Copy link
Member

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.

@asvetlov asvetlov added this to the 0.22 milestone Mar 10, 2016
@AndreLouisCaron
Copy link
Author

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

@AndreLouisCaron
Copy link
Author

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

@AndreLouisCaron
Copy link
Author

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()

@valpackett
Copy link

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.

@asvetlov
Copy link
Member

Fixed by #889

@AndreLouisCaron
Copy link
Author

Thanks!

@shvechikov
Copy link
Contributor

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.

@asvetlov
Copy link
Member

Should be fixed in next aiohttp release

@satarsa
Copy link

satarsa commented Jul 28, 2016

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

@satarsa
Copy link

satarsa commented Jul 28, 2016

print(args[3].get_extra_info('peername'))

gives

b''

@asvetlov
Copy link
Member

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.

@asvetlov
Copy link
Member

Fixed by 8e8469b

@satarsa
Copy link

satarsa commented Jul 30, 2016

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?

@asvetlov
Copy link
Member

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.

@lock
Copy link

lock bot commented Oct 29, 2019

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.

@lock lock bot added the outdated label Oct 29, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Oct 29, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

5 participants