2015-03-11 5 views
14

Sto provando a salvare i messaggi del registro dell'applicazione da un'app molto semplice in un file di registro. Sebbene funzioni perfettamente mentre sto eseguendo l'app con il server Flask incorporato, non funziona affatto quando è in esecuzione all'interno di gUnicorn, in pratica, nessun output dell'applicazione viene reindirizzato né al file di registro (quello specificato nell'app Flask) né a lo STDOUT quando esegui gunicorn.Il logger di app Flask non funziona durante l'esecuzione all'interno di gunicorn

Ciò detto, questo è il mio Flask app:

@app.route('/') 
def index(): 
    app.logger.debug('Into /!!!!') 
    print 'Will this print?' 
    return 'Flask is running!' 


if __name__ == '__main__': 
    #Setup the logger 
    file_handler = FileHandler('test.log') 
    handler = logging.StreamHandler() 
    file_handler.setLevel(logging.DEBUG) 
    handler.setLevel(logging.DEBUG) 
    file_handler.setFormatter(Formatter(
    '%(asctime)s %(levelname)s: %(message)s ' 
    '[in %(pathname)s:%(lineno)d]')) 
    handler.setFormatter(Formatter(
    '%(asctime)s %(levelname)s: %(message)s ' 
    '[in %(pathname)s:%(lineno)d]')) 
    app.logger.addHandler(handler) 
    app.logger.addHandler(file_handler) 
    app.run(debug=True) 

Ora, se mi metto l'applicazione come:

python app.py 

ottengo i risultati attesi:

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) 
* Restarting with stat 

-------------------------------------------------------------------------------- 
DEBUG in app [app.py:23]: 
Into /!!!! 
-------------------------------------------------------------------------------- 
2015-03-11 09:36:18,375 DEBUG: Into /!!!! [in app.py:23] 
Will this print? 
127.0.0.1 - - [11/Mar/2015 09:36:18] "GET/HTTP/1.1" 200 - 

Tailing prova .log, vedo:

2015-03-11 09:36:18,375 DEBUG: Into /!!!! [in app.py:23] 

Tutto sembra grande finora, poi quando provo a fare funzionare l'applicazione con nginx + gunicorn, prima ho cercato di correre gunicorn in questo modo:

gunicorn app:app -b localhost:8000 --debug --log-level debug 

App sta funzionando, se vado a http://localhost :

curl http://localhost 
Flask is running! 

Ma guardando il file di registro, è vuoto, non viene scritto nulla. Ho aggiunto 777 autorizzazioni solo per verificare se si trattava di un problema di autorizzazione senza successo. Poi guardando gunicorn stdout, nulla è stato scritto oltre l'istruzione print:

2015-03-11 09:42:06 [25641] [DEBUG] GET/
Will this print? 

Looking around, ho cercato di reindirizzare tutto l'output a gunicorn tronchi, poi a partire gunicorn come questo:

gunicorn app:app -b localhost:8000 --debug --log-file /tmp/test.log --log-level debug --error-logfile /tmp/error.log 

Ma ora non ho neanche capito dichiarazioni di stampa nei file gunicorn, questo è l'uscita da entrambi test.log e error.log (sono identiche):

2015-03-11 09:46:17 [26257] [DEBUG] tmp_upload_dir: None 
2015-03-11 09:46:17 [26257] [DEBUG] keyfile: None 
2015-03-11 09:46:17 [26257] [DEBUG] backlog: 2048 
2015-03-11 09:46:17 [26257] [DEBUG] logger_class: simple 
2015-03-11 09:46:17 [26257] [INFO] Starting gunicorn 17.5 
2015-03-11 09:46:17 [26257] [DEBUG] Arbiter booted 
2015-03-11 09:46:17 [26257] [INFO] Listening at: http://127.0.0.1:8000 (26257) 
2015-03-11 09:46:17 [26257] [INFO] Using worker: sync 
2015-03-11 09:46:17 [26262] [INFO] Booting worker with pid: 26262 
2015-03-11 09:48:15 [26262] [DEBUG] GET/

C'è molto domanda simile here, una delle risposte sembra suggerire che nessun logger dell'applicazione è disponibile quando si esegue runnning all'interno di gunicorn ??? Questo suona, almeno, abbastanza strano ... come posso registrare allora?

Un'altra proposed solution sembra suggerire che non utilizzano Flask logger, ma non è in relazione con gunicorn (credo) ...

Cosa mi manca? Dovrei rinunciare a gunicorn e andare per Apache-mod wsgi? Nginx-uWSGI? FastCGI? Qualche idea?

Grazie! Alejandro

EDIT:

Ho provato questa stessa configurazione con uWGSI anziché gunicorn e stesso comportamento, alcuna registrazione applicazione si ottiene sorta.

Ora sulla base di this response e questo other one, mi si avvicinò con questo (su gUnicorn e uWSGI, in entrambi funziona)

from flask import Flask 
import logging 
from logging import Formatter, FileHandler 

app = Flask(__name__) 

LOGGER = logging.getLogger('whatever') 
file_handler = FileHandler('test.log') 
handler = logging.StreamHandler() 
file_handler.setFormatter(Formatter(
    '%(asctime)s %(levelname)s: %(message)s ' 
    '[in %(pathname)s:%(lineno)d]' 
)) 
handler.setFormatter(Formatter(
    '%(asctime)s %(levelname)s: %(message)s ' 
    '[in %(pathname)s:%(lineno)d]' 
)) 
LOGGER.addHandler(file_handler) 
LOGGER.addHandler(handler) 
LOGGER.setLevel(logging.INFO) 

@app.route('/') 
def hello(): 
    LOGGER.info('info log') 
    LOGGER.debug('debug log') 
    return 'Hello!' 

if __name__ == '__main__': 
    app.run() 

uscita da gunicorn:

2015-03-11 12:25:01 [11540] [INFO] Starting gunicorn 17.5 
2015-03-11 12:25:01 [11540] [INFO] Listening at: http://127.0.0.1:8000 (11540) 
2015-03-11 12:25:01 [11540] [INFO] Using worker: sync 
2015-03-11 12:25:01 [11545] [INFO] Booting worker with pid: 11545 
2015-03-11 12:26:20,765 INFO: info log [in /home/mosquito/www/flask-project/flask-project/app.py:24] 

E guardando il mio File test.log:

2015-03-11 12:26:20,765 INFO: info log [in /home/mosquito/www/flask-project/flask-project/app.py:24] 

Quindi sì, funziona un pò, ma originale la domanda rimane ancora ... perché diamine, il logger Flask non sembra funzionare quando si esegue all'interno di contenitori wsgi - gunicorn, uWSGI?

+0

Questo ha funzionato anche per me. – cocobear

risposta

8

Il pallone utilizza Werkzeug per WSGI. I "Flask logs" che vedi sono in realtà dal server Werkzeug's builtin development e non dalla stessa Flask.

Quando si sostituisce il server di sviluppo con qualcosa come Gunicorn o uWSGI, non si vedono i suoi registri.

Lo stesso vale per il debugger. Puoi vedere la familiare "pagina di debug di Flask" anche se usi solo Werkzeug's Debugger.

Ora lo sai. :)

15

Hai risposto alla tua domanda da solo. Anche se aggiungerò la mia risposta nella speranza che possa aiutare qualcun altro ad avere problemi simili.

Dal momento che la tua domanda ha 2 parti, di cui la prima parte è risolto, mal segno la mia risposta per ogni parte:

PARTE 1: No logging succede se invece di eseguire direttamente l'applicazione tramite pitone, lo si esegue under gunicorn Questo perché, quando è in esecuzione, il nome == 'principale' è True e il codice ha inizializzato sia FileHandler che StreamHandler e la registrazione ha funzionato. Ma quando eseguito attraverso gunicorn, nome == 'principale' fallirebbe, come nome sarebbe poi contenere il nome del modulo. Ciò significa che i gestori effettivi saranno inizializzati. E quindi nessuna registrazione è vista.

PARTE 2: Perché non Boccetta lavoro logger di default sotto gunicorn/uWSGI Le ultime versioni boccetta inizializzare app.logger da zero e allegare un paio di gestori come DebugHandler, StreamHandler per difetto a seconda se app.debug == Vero. Tuttavia il logger non è sufficiente e si collegherà solo a STDERR. Ci sono stati molti cambiamenti in gunicorn nelle ultime versioni. La versione 19.4.1 non acquisisce STDOUT e STDERR nel file error.log di gunicorn. Ma rende disponibili i logger con i nomi 'gunicorn', 'gunicorn.access' e 'gunicorn.error'. L'ultimo ha una scrittura FileHandler sul error.log configurato. Nel caso in cui si desideri che i registri della propria app per dispositivi mobili passino all'errore.log utilizzare uno dei seguenti approcci: 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') 

raccomanderà approccio 2, come si può mantenere tutto ciò i gestori che si desidera, oltre a gunicorn.error. Inoltre, puoi scegliere di non aggiungere gestori gunicorn.error in base a una condizione.

grazie

+0

Mi piace l'approccio, lo metto alla prova, grazie @indrajeet – AlejandroVK

3

Con gunicorn 19,6, --capture-output --enable-stdio-inheritance sembra funzionare.

+0

non ho controllato, lo proverò, grazie @Mssi – AlejandroVK

+2

No, non c'è fortuna con questo – palfrey