J'essaie d'ajouter la journalisation à une application Web qui utilise Flask.
Lorsqu'il est hébergé à l'aide du serveur intégré (c'est-à-dire python3 server.py
), la journalisation fonctionne. Lorsqu'il est hébergé à l'aide de Gunicorn, le fichier journal n'est pas créé.
Le code le plus simple qui reproduit le problème est celui-ci:
#!/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 __== "__main__":
logHandler = logging.FileHandler('/var/log/demo/app.log')
logHandler.setLevel(logging.INFO)
flaskApp.logger.addHandler(logHandler)
flaskApp.logger.setLevel(logging.INFO)
flaskApp.run()
L'application est appelée à l'aide de:
gunicorn server:flaskApp -b :80 -w 4
--access-gfile /var/log/demo/access.log
--error-logfile /var/log/demo/error.log
Lorsque vous effectuez une demande sur la page d'accueil du site, les événements suivants se produisent:
Je reçois le HTTP 200 "Hello World\n" attendu en réponse.
Il y a une trace de la demande dans /var/log/demo/access.log
.
/var/log/demo/error.log
reste le même (il n'y a que les événements de démarrage).
Il y a la ligne "Sortie directe" dans le terminal.
Il n'y a pas de '/var/log/demo/app.log'. Si je crée le fichier avant de lancer l'application, le fichier n'est pas modifié.
Notez que:
Le répertoire /var/log/demo
est accessible à tous (lecture, écriture, exécution), ce n'est donc pas le problème des autorisations.
Si j'ajoute StreamHandler
comme deuxième gestionnaire, il n'y a toujours aucune trace du message "Log message" ni dans le terminal, ni dans les fichiers journaux de Gunicorn.
Gunicorn est installé à l'aide de pip3 install gunicorn
, donc il ne devrait pas y avoir de discordance avec les versions Python.
Que ce passe-t-il?
Lorsque vous utilisez python3 server.py
, Vous exécutez le script server3.py.
Lorsque vous utilisez gunicorn server:flaskApp ...
, Vous exécutez le script de démarrage de gunicorn qui importe le module server
et recherche la variable flaskApp
dans ce module.
Étant donné que server.py
Est importé, la variable __name__
Contiendra "server"
, Pas "__main__"
Et par conséquent, le code d'installation du gestionnaire de journaux n'est pas exécuté.
Vous pouvez simplement déplacer le code de configuration du gestionnaire de journaux en dehors de la strophe if __== "__main__":
. Mais assurez-vous que vous gardez flaskApp.run()
dedans puisque vous voulez pas vouloir que cela soit exécuté lorsque gunicorn importe server
.
En savoir plus sur que fait if __== “__main__”:
?
Cette approche fonctionne pour moi: importez le module de journalisation Python et ajoutez-y des gestionnaires d'erreur de gunicorn. Ensuite, votre enregistreur se connectera au fichier journal des erreurs de 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')
Mon script de démarrage Gunicorn est configuré pour générer des entrées de journal dans un fichier comme ceci:
gunicorn main:app \
--workers 4 \
--bind 0.0.0.0:9000 \
--log-file /app/logs/gunicorn.log \
--log-level DEBUG \
--reload