Logging stdout to gunicorn access log?

后端 未结 4 1066
萌比男神i
萌比男神i 2021-02-06 06:38

When I wrap my Flask application in gunicorn writing to stdout no longer seems to go anywhere (simple print statements don\'t appear). Is there someway to either ca

相关标签:
4条回答
  • 2021-02-06 06:45

    Two solutions to this problem. They are probably longer than others, but ultimately they tap into how logging is done under the hood in Python.

    1. set logging configuration in the Flask app

    The official Flask documentation on logging works for gunicorn. https://flask.palletsprojects.com/en/1.1.x/logging/#basic-configuration

    • some example code to try out:
    from logging.config import dictConfig
    
    from flask import Flask
    
    dictConfig(
        {
            "version": 1,
            "disable_existing_loggers": False,
            "formatters": {
                "default": {
                    "format": "[%(asctime)s] [%(process)d] [%(levelname)s] in %(module)s: %(message)s",
                    "datefmt": "%Y-%m-%d %H:%M:%S %z"
                }
            },
            "handlers": {
                "wsgi": {
                    "class": "logging.StreamHandler",
                    "stream": "ext://flask.logging.wsgi_errors_stream",
                    "formatter": "default",
                }
            },
            "root": {"level": "DEBUG", "handlers": ["wsgi"]},
        }
    )
    app = Flask(__name__)
    
    @app.route("/")
    def hello():
        app.logger.debug("this is a DEBUG message")
        app.logger.info("this is an INFO message")
        app.logger.warning("this is a WARNING message")
        app.logger.error("this is an ERROR message")
        app.logger.critical("this is a CRITICAL message")
        return "hello world"
    
    • run with gunicorn
    gunicorn -w 2 -b 127.0.0.1:5000 --access-logfile - app:app
    
    • request it using curl
    curl http://127.0.0.1:5000
    
    • this would generate the following logs
    [2020-09-04 11:24:43 +0200] [2724300] [INFO] Starting gunicorn 20.0.4
    [2020-09-04 11:24:43 +0200] [2724300] [INFO] Listening at: http://127.0.0.1:5000 (2724300)
    [2020-09-04 11:24:43 +0200] [2724300] [INFO] Using worker: sync
    [2020-09-04 11:24:43 +0200] [2724311] [INFO] Booting worker with pid: 2724311
    [2020-09-04 11:24:43 +0200] [2724322] [INFO] Booting worker with pid: 2724322
    [2020-09-04 11:24:45 +0200] [2724322] [DEBUG] in flog: this is a DEBUG message
    [2020-09-04 11:24:45 +0200] [2724322] [INFO] in flog: this is an INFO message
    [2020-09-04 11:24:45 +0200] [2724322] [WARNING] in flog: this is a WARNING message
    [2020-09-04 11:24:45 +0200] [2724322] [ERROR] in flog: this is an ERROR message
    [2020-09-04 11:24:45 +0200] [2724322] [CRITICAL] in flog: this is a CRITICAL message
    127.0.0.1 - - [04/Sep/2020:11:24:45 +0200] "GET / HTTP/1.1" 200 11 "-" "curl/7.68.0"
    

    2. set logging configuration in Gunicorn

    • same application code as above but without the dictConfig({...}) section

    • create a logging.ini file

    [loggers]
    keys=root
    
    [handlers]
    keys=consoleHandler
    
    [formatters]
    keys=simpleFormatter
    
    [logger_root]
    level=DEBUG
    handlers=consoleHandler
    
    [handler_consoleHandler]
    class=StreamHandler
    level=DEBUG
    formatter=simpleFormatter
    args=(sys.stdout,)
    
    [formatter_simpleFormatter]
    format=[%(asctime)s] [%(process)d] [%(levelname)s] - %(module)s - %(message)s
    datefmt=%Y-%m-%d %H:%M:%S %z
    
    • run gunicorn with --log-config logging.ini option, i.e gunicorn -w 2 -b 127.0.0.1:5000 --access-logfile - --log-config logging.ini app:app
    0 讨论(0)
  • 2021-02-06 06:55

    You can redirect standard output to a errorlog file, which is enough for me.

    Note that:

    capture_output

    --capture-output
    False
    Redirect stdout/stderr to specified file in errorlog


    My config file gunicorn.config.py setting

    accesslog = 'gunicorn.log'
    errorlog = 'gunicorn.error.log'
    capture_output = True
    

    Then run with gunicorn app_py:myapp -c gunicorn.config.py

    The equivaluent command line would be

    gunicorn app_py:myapp --error-logfile gunicorn.error.log --access-logfile gunicorn.log --capture-output

    0 讨论(0)
  • 2021-02-06 07:00

    Use the logging: set the stream to stdout

    import logging
    
    app.logger.addHandler(logging.StreamHandler(sys.stdout))
    app.logger.setLevel(logging.DEBUG)
    
    app.logger.debug("Hello World")
    
    0 讨论(0)
  • 2021-02-06 07:06

    The solution from John mee works, but it duplicates log entries in the stdout from gunicorn.

    I used this:

    import logging
    from flask import Flask
    
    app = Flask(__name__)
    
    if __name__ != '__main__':
        gunicorn_logger = logging.getLogger('gunicorn.error')
        app.logger.handlers = gunicorn_logger.handlers
        app.logger.setLevel(gunicorn_logger.level)
    

    and got I this from: https://medium.com/@trstringer/logging-flask-and-gunicorn-the-manageable-way-2e6f0b8beb2f

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