add an option to change access_log using gunicorn

This commit is contained in:
Sergey Fedoruk 2018-12-29 23:56:01 +01:00 committed by Sergey Fedoruk
parent cea1547e08
commit d76d5e2c5f
3 changed files with 97 additions and 0 deletions

View File

@ -15,6 +15,7 @@ keyword arguments:
- `protocol` *(default `HttpProtocol`)*: Subclass - `protocol` *(default `HttpProtocol`)*: Subclass
of of
[asyncio.protocol](https://docs.python.org/3/library/asyncio-protocol.html#protocol-classes). [asyncio.protocol](https://docs.python.org/3/library/asyncio-protocol.html#protocol-classes).
- `access_log` *(default `True`)*: Enables log on handling requests (significantly slows server).
## Workers ## Workers
@ -63,6 +64,20 @@ of the memory leak.
See the [Gunicorn Docs](http://docs.gunicorn.org/en/latest/settings.html#max-requests) for more information. See the [Gunicorn Docs](http://docs.gunicorn.org/en/latest/settings.html#max-requests) for more information.
## Disable debug logging
To improve the performance add `debug=False` and `access_log=False` in the `run` arguments.
```python
app.run(host='0.0.0.0', port=1337, workers=4, debug=False, access_log=False)
```
Running via Gunicorn you can set `--log-level` higher than `info` to not get any access logs anymore.
```
gunicorn myapp:app --bind 0.0.0.0:1337 --worker-class sanic.worker.GunicornWorker --log-level warning
```
## Asynchronous support ## Asynchronous support
This is suitable if you *need* to share the sanic process with other applications, in particular the `loop`. This is suitable if you *need* to share the sanic process with other applications, in particular the `loop`.
However be advised that this method does not support using multiple processes, and is not the preferred way However be advised that this method does not support using multiple processes, and is not the preferred way

View File

@ -57,6 +57,10 @@ class GunicornWorker(base.Worker):
if self.app.callable.websocket_enabled if self.app.callable.websocket_enabled
else self.http_protocol else self.http_protocol
) )
# set ACCESS_LOG on base of logging level
self.app.callable.config.ACCESS_LOG = self.log.loglevel <= logging.INFO
self._server_settings = self.app.callable._helper( self._server_settings = self.app.callable._helper(
loop=self.loop, loop=self.loop,
debug=is_debug, debug=is_debug,

View File

@ -4,6 +4,7 @@ import shlex
import subprocess import subprocess
import urllib.request import urllib.request
from unittest import mock from unittest import mock
from urllib.error import HTTPError
from sanic.worker import GunicornWorker from sanic.worker import GunicornWorker
from sanic.app import Sanic from sanic.app import Sanic
import asyncio import asyncio
@ -24,12 +25,89 @@ def gunicorn_worker():
worker.kill() worker.kill()
@pytest.fixture(scope='module')
def gunicorn_worker_log_level_info():
command = (
'gunicorn '
'--bind 127.0.0.1:1338 '
'--worker-class sanic.worker.GunicornWorker '
'--log-level info '
'examples.simple_server:app'
)
worker = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
time.sleep(2)
return worker
@pytest.fixture(scope='module')
def gunicorn_worker_log_level_warning():
command = (
'gunicorn '
'--bind 127.0.0.1:1339 '
'--worker-class sanic.worker.GunicornWorker '
'--log-level warning '
'examples.simple_server:app'
)
worker = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
time.sleep(2)
return worker
@pytest.fixture(scope='module')
def gunicorn_worker_log_level_warning2():
command = (
'gunicorn '
'--bind 127.0.0.1:1340 '
'--worker-class sanic.worker.GunicornWorker '
'--log-level warning '
'examples.exception_monitoring:app'
)
worker = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
time.sleep(2)
return worker
def test_gunicorn_worker(gunicorn_worker): def test_gunicorn_worker(gunicorn_worker):
with urllib.request.urlopen("http://localhost:1337/") as f: with urllib.request.urlopen("http://localhost:1337/") as f:
res = json.loads(f.read(100).decode()) res = json.loads(f.read(100).decode())
assert res["test"] assert res["test"]
def test_gunicorn_worker_logs_info(gunicorn_worker_log_level_info):
"""
on base of our log-level we get an access message
"""
with urllib.request.urlopen('http://localhost:1338/') as _:
gunicorn_worker_log_level_info.kill()
assert b"(sanic.access)[INFO][127.0.0.1" in gunicorn_worker_log_level_info.stdout.read()
def test_gunicorn_worker_logs_warning(gunicorn_worker_log_level_warning):
"""
with log-level warning we are not getting an access messages anymore
"""
with urllib.request.urlopen('http://localhost:1339/') as _:
gunicorn_worker_log_level_warning.kill()
assert not gunicorn_worker_log_level_warning.stdout.read()
def test_gunicorn_worker_logs_warning_on_error(gunicorn_worker_log_level_warning2):
"""
with log-level warning we get an error log but don't get an access log
"""
try:
url = urllib.request.urlopen('http://localhost:1340/')
except HTTPError:
pass
else:
url.close()
gunicorn_worker_log_level_warning2.kill()
log_message = gunicorn_worker_log_level_warning2.stdout.read()
assert b"(sanic.access)[INFO][127.0.0.1" not in log_message
assert b"[ERROR] Exception occurred while handling uri" in log_message
class GunicornTestWorker(GunicornWorker): class GunicornTestWorker(GunicornWorker):
def __init__(self): def __init__(self):
self.app = mock.Mock() self.app = mock.Mock()