Gunicorn: Flask์˜ app.logger์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2012๋…„ 07์›” 19์ผ  ยท  11์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: benoitc/gunicorn

app.logger.info("This is a message")์™€ ๊ฐ™์€ Flask ๋กœ๊ฑฐ์˜ ๋ฉ”์‹œ์ง€๋Š” gunicorn ๋กœ๊ทธ ํŒŒ์ผ์— ์ €์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

Flask๋Š” ํ™˜๊ฒฝ(http://flask.pocoo.org/docs/errorhandling/)์— ๋Œ€ํ•œ ๊ฐ€์ •์„ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ณธ์ ์œผ๋กœ ํ”„๋กœ๋•์…˜ ๋ชจ๋“œ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๊ธฐ๋กํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Flask์˜ app.logger๊ฐ€ gunicorn์„ ํ†ตํ•ด ๋ฉ”์‹œ์ง€๋ฅผ ๊ธฐ๋กํ•˜๋„๋ก ํ•˜๋ ค๋ฉด ๋กœ๊น… ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ์€ gunicorn์˜ stderr์— ๋Œ€ํ•œ ๋กœ๊ฑฐ์ž…๋‹ˆ๋‹ค.

import logging
import flask

app = flask.Flask(__name__)

@app.before_first_request
def setup_logging():
    if not app.debug:
        # In production mode, add log handler to sys.stderr.
        app.logger.addHandler(logging.StreamHandler())
        app.logger.setLevel(logging.INFO)

์ด๊ฒƒ์€ gunicorn์˜ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ฉฐ ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  11 ๋Œ“๊ธ€

Flask๋Š” ํ™˜๊ฒฝ(http://flask.pocoo.org/docs/errorhandling/)์— ๋Œ€ํ•œ ๊ฐ€์ •์„ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ณธ์ ์œผ๋กœ ํ”„๋กœ๋•์…˜ ๋ชจ๋“œ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๊ธฐ๋กํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Flask์˜ app.logger๊ฐ€ gunicorn์„ ํ†ตํ•ด ๋ฉ”์‹œ์ง€๋ฅผ ๊ธฐ๋กํ•˜๋„๋ก ํ•˜๋ ค๋ฉด ๋กœ๊น… ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ์€ gunicorn์˜ stderr์— ๋Œ€ํ•œ ๋กœ๊ฑฐ์ž…๋‹ˆ๋‹ค.

import logging
import flask

app = flask.Flask(__name__)

@app.before_first_request
def setup_logging():
    if not app.debug:
        # In production mode, add log handler to sys.stderr.
        app.logger.addHandler(logging.StreamHandler())
        app.logger.setLevel(logging.INFO)

์ด๊ฒƒ์€ gunicorn์˜ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ฉฐ ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์š”์ฒญ์— ๋”ฐ๋ผ ๋‹ซํž™๋‹ˆ๋‹ค. ๊ฐ์‚ฌ ํ•ด์š”!

gunicorn์€ STDERR์—์„œ ์ž๋™์œผ๋กœ ๋กœ๊ทธ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๊นŒ?

@benoitc
gunicorn์ด STDERR์—์„œ ๋กœ๊ทธ๋ฅผ ์„ ํƒํ•˜๋„๋ก ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

-R ํ”Œ๋ž˜๊ทธ๊ฐ€ ์ฐพ๊ณ  ์žˆ๋Š” ๊ฒƒ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

http://gunicorn-docs.readthedocs.org/en/latest/settings.html#enable -stdio-inheritance

-R์€ ๋‚˜๋ฅผ ์œ„ํ•ด ๊ทธ๊ฒƒ์„ํ•˜์ง€ ์•Š์•˜๋‹ค.

์•„๋ž˜๋Š” ๋‚ด ์„ค์ •์ž…๋‹ˆ๋‹ค

@app.route('/')
def index():
    console = logging.StreamHandler()
    log = logging.getLogger("asdasd")
    log.addHandler(console)
    log.setLevel(logging.DEBUG)
    log.error("Something")
    print >> sys.stderr, "Another thing"
    return 'ok'

๋‹ค์Œ์€ ๋‚ด๊ฐ€ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

gunicorn --access-logfile - --log-file /mnt/log/test.log --bind 0.0.0.0:8080 --workers 2 --worker-class gevent --log-level -D debug server:app

/mnt/log/test.log์— gunicorn ๋กœ๊ทธ๊ฐ€ ํ‘œ์‹œ๋˜์ง€๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ์—๋Š” ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ดœ์ฐฎ์•„. ๊ฐ„๋‹จํ•œ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ž‘๋™ ๋ฐฉ์‹์„ ์˜คํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
stderr์„ ์ˆ˜๋™์œผ๋กœ ํ”Œ๋Ÿฌ์‹œํ•ด์•ผ ํ•จ(IIRC๋Š” ๋ฒ„ํผ๋ง๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
gunicorn์ด ํฌํฌํ•  ๋•Œ, ์•„๋งˆ๋„?)

๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๊ฐ€ ์–ด๋””๋กœ ๊ฐ€๋Š”์ง€ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹๊ฒƒ์ด ํ›จ์”ฌ ์‰ฝ์Šต๋‹ˆ๋‹ค.
stdio ๋Œ€์‹  ํŒŒ์ด์ฌ ๋กœ๊ฑฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
2014๋…„ 6์›” 26์ผ ์˜คํ›„ 1์‹œ 39๋ถ„์— "Yousuf Fauzan" [email protected] ์ด ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

-R์€ ๋‚˜๋ฅผ ์œ„ํ•ด ๊ทธ๊ฒƒ์„ํ•˜์ง€ ์•Š์•˜๋‹ค.

์•„๋ž˜๋Š” ๋‚ด ์„ค์ •์ž…๋‹ˆ๋‹ค

@app.route('/')
def ์ธ๋ฑ์Šค():
์ฝ˜์†” = logging.StreamHandler()
๋กœ๊ทธ = logging.getLogger("asdasd")
log.addHandler(์ฝ˜์†”)
log.setLevel(logging.DEBUG)
log.error("๋ญ”๊ฐ€")
์ธ์‡„ >> sys.stderr, "๋˜ ๋‹ค๋ฅธ ๊ฒƒ"
'ํ™•์ธ'์„ ๋ฐ˜ํ™˜

๋‹ค์Œ์€ ๋‚ด๊ฐ€ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

gunicorn --access-logfile --log-file /mnt/log/test.log --bind 0.0.0.0:8080 --workers 2 --worker-class gevent --log-level ๋””๋ฒ„๊ทธ ์„œ๋ฒ„:app

/mnt/log/test.log์— gunicorn ๋กœ๊ทธ๊ฐ€ ์žˆ์ง€๋งŒ ๋‚ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—๋Š” ์—†์Šต๋‹ˆ๋‹ค.
๋กœ๊ทธ.

โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/benoitc/gunicorn/issues/379#issuecomment -47276949.

๋ฌธ์ œ๋ฅผ ์ฐพ์€ ๊ฒƒ ๊ฐ™์•„์š”. ๋‹ค์Œ์€ 19.00์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ ๋กœ๊ทธ์˜ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค.

fix logging: donโ€™t try to redirect stdout/stderr to the logfile.

๋ฐฉ๊ธˆ v18๋กœ ์‹œ๋„ํ–ˆ๋Š”๋ฐ StreamHandler์˜ ๋กœ๊ทธ๊ฐ€ gunicorn ๋กœ๊ทธ๋กœ ๋ผ์šฐํŒ…๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?
@benoitc @tilgovi

@spicavigo gunicorn์€ stderr์„ ๋กœ๊ทธ ํŒŒ์ผ๋กœ ์ž๋™ ๋ฆฌ๋””๋ ‰์…˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ˆ˜์ • ์‚ฌํ•ญ์€ #591์—์„œ ๋…ผ์˜๋œ ๊ฒƒ์ฒ˜๋Ÿผ ํ•ดํ‚น์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ฝ˜์†”์— ๋กœ๊ทธ๋ฅผ ํ‘œ์‹œํ•˜๋Š” --error-logfile=- ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์…จ์Šต๋‹ˆ๊นŒ?

์˜ค๋ฅ˜ ํŒŒ์ผ์— ์ง์ ‘ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ ค๋ฉด ๊ฒฐ๊ตญ Environ['wsgi.errors']์— ์ธ์‡„ํ•˜๊ฑฐ๋‚˜ ee08ac86441e36c3433849b79b3839d1425647fd๋ฅผ ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@benoitc ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

์ด์ œ stderr ๋Œ€์‹  ํŒŒ์ผ์— ๋กœ๊น…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ๊ฐœ๋ฐœ์ž ์‚ฌ์ด์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋ฐœ์ƒํ•˜์—ฌ ์™„์ „ํžˆ ๋„˜์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” pip install gunicorn์ด์—ˆ๊ณ  ๊ฐ‘์ž๊ธฐ stderr ๋ฆฌ๋””๋ ‰์…˜์ด ์ž‘๋™์„ ๋ฉˆ์ท„๊ณ  ๊ทธ๊ฒƒ์ด ๋‚ด ์ฝ”๋“œ์˜ ๋ฒ„๊ทธ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฒ„์ „ ๋ณ€๊ฒฝ ๋•Œ๋ฌธ์ด๋ผ๋Š” ๊ฒƒ์„ ๊นจ๋‹ซ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. :)

@benoitc ์–ด๋–ป๊ฒŒ ๋“  stderr์„ ๋กœ๊ทธ ํŒŒ์ผ์— ๊ธฐ๋กํ•˜๋Š” ๊ฒƒ์ด ์—ฌ์ „ํžˆ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๊นŒ?

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰