¿Por qué la aplicación Flask no crea ningún registro cuando está alojado en Gunicorn?

Estoy intentando agregar el registro a una aplicación web que usa Flask.

Cuando se aloja utilizando el servidor incorporado (es decir, python3 server.py ), el registro funciona. Cuando se aloja con Gunicorn, el archivo de registro no se crea.

El código más simple que reproduce el problema es este:

 #!/usr/bin/env python import logging from flask import Flask flaskApp = Flask(__name__) @flaskApp.route('/') def index(): flaskApp.logger.info('Log message') print('Direct output') return 'Hello World\n' if __name__ == "__main__": logHandler = logging.FileHandler('/var/log/demo/app.log') logHandler.setLevel(logging.INFO) flaskApp.logger.addHandler(logHandler) flaskApp.logger.setLevel(logging.INFO) flaskApp.run() 

La aplicación se llama utilizando:

 gunicorn server:flaskApp -b :80 -w 4 --access-gfile /var/log/demo/access.log --error-logfile /var/log/demo/error.log 

Al realizar una solicitud a la página de inicio del sitio, ocurre lo siguiente:

  1. Recibo el HTTP 200 esperado “Hello World \ n” en respuesta.

  2. Hay un seguimiento de la solicitud en /var/log/demo/access.log .

  3. /var/log/demo/error.log permanece igual (solo hay eventos de arranque).

  4. Hay la línea de “salida directa” en el terminal.

  5. No hay ‘/var/log/demo/app.log’. Si creo el archivo antes de iniciar la aplicación, el archivo no se modifica.

Tenga en cuenta que:

  • El directorio /var/log/demo puede ser accedido (leer, escribir, ejecutar) por todos, por lo que este no es el problema de los permisos.

  • Si agrego StreamHandler como un segundo controlador, todavía no hay rastro del mensaje “Mensaje de registro” ni en el terminal, ni en los archivos de registro de Gunicorn.

  • Gunicorn se instala utilizando pip3 install gunicorn , por lo que no debería haber ninguna discrepancia con las versiones de Python.

¿Qué esta pasando?

Cuando usa python3 server.py está ejecutando el script server3.py.

Cuando usa el gunicorn server:flaskApp ... está ejecutando el script de inicio gunicorn que luego importa el server del módulo y busca la variable flaskApp en ese módulo.

Dado que se está importando server.py __name__ var contendrá "server" , no "__main__" y, por lo tanto, no se está ejecutando el código de configuración del controlador.

Simplemente puede mover el código de configuración del manejador de registros fuera de la stanza if __name__ == "__main__": . Pero asegúrese de mantener flaskApp.run() allí, ya que no desea que se ejecute cuando gunicorn importe el server .

Más sobre lo que hace if __name__ == “__main__”: hazlo?

Este enfoque funciona para mí: importar el módulo de registro de Python y agregarle los controladores de error de gunicorn. Luego, su registrador iniciará sesión en el archivo de registro de errores gunicorn:

 import logging app = Flask(__name__) gunicorn_error_logger = logging.getLogger('gunicorn.error') app.logger.handlers.extend(gunicorn_error_logger.handlers) app.logger.setLevel(logging.DEBUG) app.logger.debug('this will show in the log') 

Mi script de inicio de Gunicorn está configurado para generar entradas de registro en un archivo como este:

 gunicorn main:app \ --workers 4 \ --bind 0.0.0.0:9000 \ --log-file /app/logs/gunicorn.log \ --log-level DEBUG \ --reload