2

My python code is currently printing the following line to the logs at the conclusion of every REST API call (high-level info on the response it is sending back):

111.111.111.111 - - [15/Aug/2017:12:03:15 +0000] "POST /some_endpoint 
HTTP/1.1" 202 72 "-" "python-requests/2.2.1 CPython/3.4.3 Linux/3.13.0-83-generic"

Through other searches I've seen the following suggestions on how to get rid of it:

1) logging.getLogger('werkzeug').setLevel(logging.ERROR)

2) logging.getLogger('werkzeug').disabled = True

3) Same as above, but requests instead of werkzeug

These have no effect. Another solution offered up was to use a completely different stream for logging but that's not going to be an option for my needs.

This is obviously getting logged through a separate mechanism than the rest of my logs since the format is different, but I can't seem to pinpoint the culprit.

Alexander McFarlane
  • 10,643
  • 9
  • 59
  • 100

1 Answers1

1

In general, you can find the logging instance in any library and adjust the logging level

You can access the logging utility via werkzeug._internal

from werkzeug._internal import _logger

then I adjust the root logger to logging.CRITICAL (which is 50)

_logger.setLevel(50)

This means that Werkzeug will only print CRITICAL (or higher) output

You can then adjust the _logger level according got your needs

Direct example

This applies to your example by searching for the import logging command in the Werkzeug github page. This I found in werkzeug._internal then we can do

In [2]: from werkzeug.wrappers import Request, Response
   ...:
   ...: @Request.application
   ...: def application(request):
   ...:     return Response('Hello World!')
   ...:

In [3]: from werkzeug.serving import run_simple

In [4]: run_simple('localhost', 4000, application)
 * Running on http://localhost:4000/ (Press CTRL+C to quit)

In [5]: from werkzeug import _internal

In [6]: _internal._log('info', 'Setting logger level to Critical!')  # see below why this is required
Out[6]: 'Setting logger level to Critical!'

In [7]: _internal._logger.setLevel(50)

In [7]: run_simple('localhost', 4000, application)

In the case the _logger is None then this occurs because no Werkzeug logging instance has been called. See line 75 in _internal for more clarity

In [1]: from werkzeug import _internal

In [2]: type(_internal._logger)
Out[2]: NoneType

In [3]: _internal._log('info', 'removing logger!')
removing logger!

In [4]: type(_internal._logger)
Out[4]: logging.Logger
Alexander McFarlane
  • 10,643
  • 9
  • 59
  • 100
  • I suppose, the OP describes server side logging. Your answer, however, shows a way to modify the client side request, namely the requests module, logging Messages. – rocksteady Aug 15 '17 at 12:51
  • So I tried using `requests.logging.getLogger().setLevel(logging.INFO)` but I am still seeing the HTTP response debug line being printed out. Will investigate the possibility of the root logging level being set to DEBUG (though, as mentioned in an above comment, I have tried this in the past with that set higher with no effect). – Chris Twichell Aug 15 '17 at 12:56
  • I see you are using `werkzeug` - I will adjust – Alexander McFarlane Aug 15 '17 at 12:57
  • 1
    @ChrisTwichell I'll remove the `requests` references in a sec I just added the `Werkzeug` bit directly first so yuo can play with it – Alexander McFarlane Aug 15 '17 at 13:02
  • So when I try to access `werkzeug` directly I get the following exception: `AttributeError: 'NoneType' object has no attribute 'setLevel'` Had keyed in on `werkzeug` possibly being what was printing out the debug statement based on other SO searches that showed the exact same formatted messages I'm seeing. – Chris Twichell Aug 15 '17 at 13:10
  • Maybe we can tackle this a different way... The debug statement that I'm trying to get rid of is formatted with an IP address followed by something followed by a timestamp and other things. But what follows the timestamp is blank -- is that supposed to be the logger name? – Chris Twichell Aug 15 '17 at 13:28
  • can you not do `from werkzeug._internal import _logger` – Alexander McFarlane Aug 15 '17 at 13:30
  • @AlexanderMcFarlane Yes I can execute that step, but it appears that `_logger` comes back as `None` (hence the NoneType exception). – Chris Twichell Aug 15 '17 at 13:34
  • @ChrisTwichell that is occuring because you haven't yet ran any Werkzeug functions. See github.com/pallets/werkzeug/blob/master/werkzeug/… On this line the _logger is only initiated after the first logger call - I have adjusted my answer to cover your case – Alexander McFarlane Aug 15 '17 at 15:50