-
Notifications
You must be signed in to change notification settings - Fork 14.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use gunicorn to serve logs generated by worker #17591
Changes from 1 commit
e73c1d8
87efb97
1cce404
75b6148
f31fad6
f57b2b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,15 +19,16 @@ | |
import os | ||
import time | ||
|
||
import gunicorn.app.base | ||
from flask import Flask, abort, request, send_from_directory | ||
from itsdangerous import TimedJSONWebSignatureSerializer | ||
from setproctitle import setproctitle | ||
|
||
from airflow.configuration import conf | ||
|
||
|
||
def flask_app(): | ||
flask_app = Flask(__name__) | ||
def create_app(): | ||
flask_app = Flask(__name__, static_folder=None) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't support this feature, so we can safely turn it off. |
||
max_request_age = conf.getint('webserver', 'log_request_clock_grace', fallback=30) | ||
log_directory = os.path.expanduser(conf.get('logging', 'BASE_LOG_FOLDER')) | ||
|
||
|
@@ -73,10 +74,47 @@ def serve_logs_view(filename): | |
return flask_app | ||
|
||
|
||
class StandaloneGunicornApplication(gunicorn.app.base.BaseApplication): | ||
""" | ||
Standalone Gunicorn application/serve for usage with any WSGI-application. | ||
|
||
Code inspired by an example from the Gunicorn documentation. | ||
https://github.com/benoitc/gunicorn/blob/cf55d2cec277f220ebd605989ce78ad1bb553c46/examples/standalone_app.py | ||
|
||
For details, about standalone gunicorn application, see: | ||
https://docs.gunicorn.org/en/stable/custom.html | ||
""" | ||
|
||
def __init__(self, app, options=None): | ||
self.options = options or {} | ||
self.application = app | ||
super().__init__() | ||
|
||
def load_config(self): | ||
config = { | ||
key: value | ||
for key, value in self.options.items() | ||
if key in self.cfg.settings and value is not None | ||
} | ||
for key, value in config.items(): | ||
mik-laj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.cfg.set(key.lower(), value) | ||
|
||
def load(self): | ||
return self.application | ||
|
||
|
||
def serve_logs(): | ||
"""Serves logs generated by Worker""" | ||
setproctitle("airflow serve-logs") | ||
app = flask_app() | ||
wsgi_app = create_app() | ||
|
||
worker_log_server_port = conf.getint('celery', 'WORKER_LOG_SERVER_PORT') | ||
app.run(host='0.0.0.0', port=worker_log_server_port) | ||
options = { | ||
'bind': f"0.0.0.0:{worker_log_server_port}", | ||
'workers': 2, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need 2 workers or do away with just 1? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1 should work too, but I configured 2 to failover in case one worker had problems. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah 2 is better just in case of memory errors/crashes. Just one small nit (in case somene has problems with memory usage etc.) i think it would be great to mention in the docs of worker that we are using Gunicorm and that the configuration options can be overridden by GUNiCORN_CMD_ARGS env variable https://docs.gunicorn.org/en/latest/settings.html#settings It's not at all obvious from docs without looking at the code now that wlwe have separate Gunicorm processes forked and that you can configure their behaviour via ENV vars. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. Added docs. |
||
} | ||
StandaloneGunicornApplication(wsgi_app, options).run() | ||
|
||
|
||
if __name__ == '__main__': | ||
serve_logs() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow convention supported by flask. https://github.com/pallets/flask/blob/afc13b9390ae2e40f4731e815b49edc9ef52ed4b/src/flask/cli.py#L63