I'm implementing Django logging in a project. I've got it working such that log entries are inserted into a file in our dev environment, and into a database in our production environment.
The problem I'm having is that Django needs to create the log file, even though it will be empty, in non-dev environments.
Is there a better way to implement this so that the empty log file isn't created in non-dev environments?
My code:
settings.py
logging configuration:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
},
'is_not_dev_environment': {
'()': 'lib.log.log.IsNotDevEnvironment'
},
'is_dev_environment': {
'()': 'lib.log.log.IsDevEnvironment'
}
},
'formatters': {
'standard': {
'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
'datefmt': "%d/%b/%Y %H:%M:%S"
},
'custom': {
'format': CUSTOM_LOGGING_FORMAT,
'datefmt': "%d/%b/%Y %H:%M:%S"
},
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
},
'db': {
'level': LOGGING_LEVEL,
'filters': ['is_not_dev_environment'],
'class': 'lib.log.log.DBLogHandler',
'formatter': 'custom'
},
'file': {
'level': LOGGING_LEVEL,
'filters': ['is_dev_environment'],
'filename': /var/log/django.log,
'class': 'lib.log.log.FileLogHandler',
'formatter': 'custom',
},
},
'loggers': {
'django': {
'handlers': ['mail_admins'],
'level': LOGGING_LEVEL,
'propagate': True,
}
}
}
LOGGING['loggers'].update({app: copy.deepcopy(LOCAL_APP_LOGGER) for app in LOCAL_APPS})
lib/log/log.py
which holds the filtering classes:
class IsNotDevEnvironment(logging.Filter):
def filter(self, record):
return settings.ENVIRONMENT != 'DEV'
class IsDevEnvironment(logging.Filter):
def filter(self, record):
return settings.ENVIRONMENT == 'DEV'
I settled on a different option that met my requirements. The main issue I was having was that in our test environment we couldn't create the log file (can't manipulate files with sudo on our CI provider's system). I resolved that by adding logic to disable logging based on an environment variable in the test environment.
tests/config.py
:
from logging.config import dictConfigClass
from django.conf import settings
def logging_config(config):
disable_logging = getattr(settings, 'DISABLE_LOGGING', False)
if not disable_logging:
dictConfigClass(config).configure()
An alternative would be to set the handler based on some logic:
if ENVIRONMENT == 'DEV':
LOGGING['handlers'].update({
""" Dict specifying dev handler """
})
else:
LOGGING['handlers'].update({
""" Dict specifying production handler """
})