Flask app logger not working when running within gunicorn

后端 未结 5 1132
臣服心动
臣服心动 2021-01-31 17:53

I\'m trying to save application log messages from a very simple flask app in a log file. While this works flawlessly when I\'m running the app with the embedded Flask server, it

相关标签:
5条回答
  • 2021-01-31 18:11

    Someone can search: how to see errors with Python error stack when using Flask with Gunicorn.

    Just set up the flag --error-logfile to the file path where you want to see error stacks. Particularly (when using in Docker) you can set it up in GUNICORN_CMD_ARGS environment variable to the next value (an example):

    --bind=0.0.0.0:8000 --access-logfile=/logs/rest.app/access.log --error-logfile=/logs/rest.app/error.log --capture-output --enable-stdio-inheritance

    0 讨论(0)
  • 2021-01-31 18:13

    You answered your question yourself here. Though I'll add my answer in hope that it would help someone else having similar issue.

    Since your question has 2 parts, of which the first part is solved, ill mark my response for each part:

    PART 1: No logging happening if instead of directly running the app via python, you run it under gunicorn This was because, when directly running, the name == 'main' is True, and your code initialized both a FileHandler and a StreamHandler, and logging worked. But when run through gunicorn, name == 'main' would fail, as name would then contain the name of your module. This means no effective handlers will be initialized. And hence no logging is seen.

    PART 2: Why doesn't Flask logger work by default under gunicorn/uWSGI The latest flask versions initialize app.logger from scratch and attach a few handlers like DebugHandler, StreamHandler by default depending on if app.debug==True. Still the logger is not enough and will only log to STDERR. There have been multiple changes in gunicorn over last few versions. Version 19.4.1 doesn't capture STDOUT and STDERR to the gunicorn error.log. But it does make available loggers with names 'gunicorn' , 'gunicorn.access' and 'gunicorn.error'. The last one has a FileHandler writing to the configured error.log. In case you want logs from your flask app to go to error.log use one of the following approaches: Approach1:

    #only use gunicorn.error logger for all logging
    LOGGER = logging.getLogger('gunicorn.error')
    LOGGER.info('my info')
    LOGGER.debug('debug message')
    # this would write the log messages to error.log
    

    Approach2:

    # Only use the FileHandler from gunicorn.error logger
    gunicorn_error_handlers = logging.getLogger('gunicorn.error').handlers
    app.logger.handlers.extend(gunicorn_error_handlers )
    app.logger.addHandler(myhandler1)
    app.logger.addHandler(myhandler2)
    app.logger.info('my info')
    app.logger.debug('debug message')
    

    Will recommend approach 2, as you can keep whatever handlers you wish in addition to gunicorn.error. Also, you can choose to not add gunicorn.error handlers based on a condition.

    thanks

    0 讨论(0)
  • 2021-01-31 18:20

    Flask uses Werkzeug for WSGI. The "Flask logs" you see are actually from Werkzeug's builtin development server and not from Flask itself.

    When you replace that development server with something like Gunicorn or uWSGI, you don't see its logs.

    The same goes for the Debugger. You can see the familiar "Flask debug page" even if you only use Werkzeug's Debugger.

    Now you know. :)

    0 讨论(0)
  • 2021-01-31 18:25

    @Auguiwan's answer does explain the origin question, but not talked about how to solve it.@indrajeet 's answer is quite comprehensive and provides a kind of solution. However, they don't solve my related problem.

    My answer mainly tries to help people who get here by searched similar keywords "flask gunicorn log" like me. I find this link is very helpful among related search result https://medium.com/@yoanis_gil/logging-with-docker-part-1-1-965cb5e17165

    The part Gunicorn configuration

    exec gunicorn ${WSGI_MODULE}:${WSGI_APP} \
      --name $NAME \
      --workers $NUM_WORKERS \
      --user=$USER --group=$GROUP \
      --bind=unix:$SOCKFILE \
      --log-level=info \
      --log-file=/dev/stdout
    

    really helps me out. The core configuration is --log-level and --log-file part.
    If you are using supervisored with gunicorn.conf like me, just change related gunicorn.conf file.

    0 讨论(0)
  • 2021-01-31 18:30

    With gunicorn 19.6, --capture-output --enable-stdio-inheritance seems to work.

    0 讨论(0)
提交回复
热议问题