Last active
February 11, 2023 06:05
-
-
Save bukowa/f54a7be4c3186275262bf6080fee2d50 to your computer and use it in GitHub Desktop.
django + gunicorn proper logging setup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from .logging import GunicornLogger, gunicorn_logconfig_dict, gunicorn_access_log_format | |
wsgi_app = "conf.wsgi" | |
bind = "0.0.0.0:8000" | |
workers = 2 | |
proxy_protocol = True | |
proxy_allow_ips = "*" | |
forwarded_allow_ips = "*" | |
logger_class = GunicornLogger | |
logconfig_dict = gunicorn_logconfig_dict | |
access_log_format = gunicorn_access_log_format |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2023-02-11 07:01:16:763941: 102023 INFO gunicorn.error info 139980609957952 Starting gunicorn 20.1.0 | |
2023-02-11 07:01:16:764141: 102023 INFO gunicorn.error info 139980609957952 Listening at: http://0.0.0.0:8000 (102023) | |
2023-02-11 07:01:16:764170: 102023 INFO gunicorn.error info 139980609957952 Using worker: sync | |
2023-02-11 07:01:16:765599: 102024 INFO gunicorn.error info 139980609957952 Booting worker with pid: 102024 | |
2023-02-11 07:01:16:818548: 102025 INFO gunicorn.error info 139980609957952 Booting worker with pid: 102025 | |
2023-02-11 07:01:21:466149: 102025 WARNING django.request log_response 139980609957952 Not Found: /is_alive | |
2023-02-11 07:01:21:466396: 102025 INFO gunicorn.access access 139980609957952 127.0.0.1 - -"GET /is_alive HTTP/1.1" 404 179 "-" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# | |
# https://i.stack.imgur.com/dtg8O.png | |
# | |
# | |
import logging | |
import os | |
from datetime import datetime | |
from logging import Formatter as _Formatter | |
from gunicorn.glogging import Logger as _GunicornLogger | |
django_level = os.environ.get("DJANGO_LOGGING_LEVEL", "INFO").upper() | |
gunicorn_level = os.environ.get("GUNICORN_LOGGING_LEVEL", "INFO").upper() | |
gunicorn_access_level = os.environ.get("GUNICORN_ACCESS_LOGGING_LEVEL", "WARNING").upper() | |
log_datefmt = "%Y-%m-%d %H:%M:%S:%f:%z" | |
log_format = "%(asctime)s %(process)d %(levelname)s %(name)s %(funcName)s %(thread)d %(message)s" | |
gunicorn_access_log_format = '%(h)s %(l)s %(u)s"%(r)s" %(s)s %(b)s "%(f)s"' | |
class Formatter(_Formatter): | |
def formatTime(self, record, *args, **kwargs) -> str: | |
""" | |
Python default does not support microseconds in `asctime`. | |
""" | |
return datetime.fromtimestamp(record.created).strftime(log_datefmt) | |
class GunicornLogger(_GunicornLogger): | |
def now(self): | |
""" | |
Gunicorn uses this method to log the current time in the access log. | |
""" | |
return datetime.now().strftime(log_datefmt) | |
base_logconfig_dict = { | |
"version": 1, | |
"formatters": { | |
"custom": { | |
'()': Formatter, | |
"format": log_format, | |
"datefmt": log_datefmt, | |
}, | |
}, | |
"handlers": { | |
"stdout": { | |
"level": 0, | |
"class": "logging.StreamHandler", | |
"formatter": "custom", | |
"stream": "ext://sys.stdout", | |
}, | |
"stderr": { | |
"level": 0, | |
"class": "logging.StreamHandler", | |
"formatter": "custom", | |
"stream": "ext://sys.stderr", | |
}, | |
}, | |
} | |
gunicorn_logconfig_dict = { | |
**base_logconfig_dict, | |
# required to avoid error in gunicorn 20.1.0: | |
# `Error: Unable to configure root logger` | |
"root": {}, | |
"loggers": { | |
# gunicorn access logger logs in one place and on `INFO` level by default; | |
# note: things that comes to my mind | |
# when it should be enabled, is when; | |
# a) something is bypassing proxy and should be logged | |
# b) we are debugging | |
"gunicorn.access": { | |
"handlers": ["stderr"], | |
"level": gunicorn_access_level, | |
"propagate": False, | |
}, | |
"gunicorn.error": { | |
"handlers": ["stderr"], | |
"level": gunicorn_level, | |
"propagate": False, | |
}, | |
}, | |
"disable_existing_loggers": True, | |
} | |
django_logconfig_dict = { | |
**base_logconfig_dict, | |
# all loggers not specified in `loggers` | |
# will use the settings from `root` logger | |
"root": { | |
"handlers": ["stderr"], | |
"level": django_level, | |
}, | |
# override loggers that django uses | |
# in DEFAULT_LOGGING config dict | |
"loggers": { | |
# do not propagate to `root` logger | |
"django": { | |
"handlers": ["stderr"], | |
"level": django_level, | |
"propagate": False, | |
}, | |
# propagate to `django` logger | |
"django.server": { | |
"handlers": [], | |
"level": django_level, | |
"propagate": True, | |
}, | |
"faker": { | |
"level": logging.INFO, | |
"propagate": False, | |
}, | |
}, | |
"disable_existing_loggers": False, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from .logging import django_logconfig_dict | |
LOGGING = django_logconfig_dict |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment