Background
I have a Django site served by Apache, set up in its own virtualhost and using mod_wsgi.
I want all of the errors associated with this virtualhost to be logged to a single file.
Currently, some errors are being sent to Apache's default error log and others are being sent to the one I defined in the virtualhost.
I'm pretty sure I have Django set up to stream WARN
, ERROR
and CRITICAL
errors to sys.stderr
via an instance of logging.StreamHandler
configured in my Django settings. I think mod_wsgi passes that along to Apache, which then logs it according to whichever ErrorLog
, ErrorLogFormat
and LogLevel
directives apply.
Questions
- What settings/situations cause errors to go to one log over another?
- Is it possible to unify the kinds of errors I give examples of?
- Are there any limitations on which errors can be logged where?
Error log examples
/var/log/apache2/mysite_error.log :
(Caused by purposefully setting an invalid log level "foo" for the default Django logger in the Django settings files.)
[Wed Aug 09 19:48:31.049028 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] mod_wsgi (pid=30894): Target WSGI script '/home/myuser/mysite/mysite/mysite.wsgi' cannot be loaded as Python module.
[Wed Aug 09 19:48:31.049050 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] mod_wsgi (pid=30894): Exception occurred processing WSGI script '/home/myuser/mysite/mysite/mysite.wsgi'.
[Wed Aug 09 19:48:31.049063 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] Traceback (most recent call last):
[Wed Aug 09 19:48:31.049075 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] File "/home/myuser/mysite/mysite/mysite.wsgi", line 18, in <module>
[Wed Aug 09 19:48:31.049112 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] application = get_wsgi_application()
[Wed Aug 09 19:48:31.049119 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] File "/home/myuser/mysite/venv/lib/python2.7/site-packages/django/core/wsgi.py", line 14, in get_wsgi_application
[Wed Aug 09 19:48:31.049140 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] django.setup()
[Wed Aug 09 19:48:31.049153 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] File "/home/myuser/mysite/venv/lib/python2.7/site-packages/django/__init__.py", line 17, in setup
[Wed Aug 09 19:48:31.049172 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
[Wed Aug 09 19:48:31.049177 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] File "/home/myuser/mysite/venv/lib/python2.7/site-packages/django/utils/log.py", line 86, in configure_logging
[Wed Aug 09 19:48:31.049212 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] logging_config_func(logging_settings)
[Wed Aug 09 19:48:31.049217 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] File "/usr/lib/python2.7/logging/config.py", line 794, in dictConfig
[Wed Aug 09 19:48:31.049339 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] dictConfigClass(config).configure()
[Wed Aug 09 19:48:31.049344 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] File "/usr/lib/python2.7/logging/config.py", line 627, in configure
[Wed Aug 09 19:48:31.049392 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] '%r: %s' % (name, e))
[Wed Aug 09 19:48:31.049416 2017] [:error] [pid 30894:tid 140490808121088] [client 129.112.115.40:32828] ValueError: Unable to configure logger 'django': Unknown level: 'foo'
/var/log/apache2/error.log :
(Caused by making an GET request that queries for a record that does not exist in the database.)
[Wed Aug 09 19:45:56.500731 2017] [:error] [pid 30718:tid 140490808121088] ERROR 2017-08-09 19:45:56,500 base:256 handle_uncaught_exception 30718 140490808121088 Internal Server Error: /fooview
[Wed Aug 09 19:45:56.500744 2017] [:error] [pid 30718:tid 140490808121088] Traceback (most recent call last):
[Wed Aug 09 19:45:56.500746 2017] [:error] [pid 30718:tid 140490808121088] File "/home/myuser/mysite/venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
[Wed Aug 09 19:45:56.500748 2017] [:error] [pid 30718:tid 140490808121088] response = wrapped_callback(request, *callback_args, **callback_kwargs)
[Wed Aug 09 19:45:56.500749 2017] [:error] [pid 30718:tid 140490808121088] File "/home/myuser/mysite/rtls/views.py", line 55, in fooview
[Wed Aug 09 19:45:56.500751 2017] [:error] [pid 30718:tid 140490808121088] Node.objects.get(pk=-1)
[Wed Aug 09 19:45:56.500752 2017] [:error] [pid 30718:tid 140490808121088] File "/home/myuser/mysite/venv/lib/python2.7/site-packages/django/db/models/manager.py", line 127, in manager_method
[Wed Aug 09 19:45:56.500754 2017] [:error] [pid 30718:tid 140490808121088] return getattr(self.get_queryset(), name)(*args, **kwargs)
[Wed Aug 09 19:45:56.500755 2017] [:error] [pid 30718:tid 140490808121088] File "/home/myuser/mysite/venv/lib/python2.7/site-packages/django/db/models/query.py", line 334, in get
[Wed Aug 09 19:45:56.500756 2017] [:error] [pid 30718:tid 140490808121088] self.model._meta.object_name
[Wed Aug 09 19:45:56.500758 2017] [:error] [pid 30718:tid 140490808121088] DoesNotExist: Node matching query does not exist.
Also, if I manually make a logging call using logger.error('some error message')
, it shows up here as well - not in the virtualhost's error log like I would expect.
Program version info
- Apache/2.4.7 (Ubuntu) using mpm_worker (
apache2ctl -V
) - Django/1.8.14 (
pip freeze
) - mod_wsgi/3.4 (the last method of this)
- Python/2.7.6 (from startup logs in main Apache
error.log
)
Related sections of configs and code
Apache
/etc/apache2/apache2.conf :
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel error
# ... stuff ...
WSGIRestrictStdout On
/etc/apache2/sites-available/mysite.conf :
<VirtualHost *:80>
# ... stuff ...
ErrorLog ${APACHE_LOG_DIR}/mysite_error.log
LogLevel warn
#serving wsgi script
WSGIScriptAlias / /home/myuser/mysite/mysite/mysite.wsgi
<Directory /home/myuser/mysite/mysite>
<Files mysite.wsgi>
Require all granted
</Files>
</Directory>
# ... stuff ...
</VirtualHost>
Django
/home/myuser/mysite/mysite/initial_settings.py :
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s:%(lineno)s %(funcName)s %(process)d %(thread)d %(message)s'
},
# ... other formatters ...
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
# ... other handlers ...
}
}
/home/myuser/mysite/mysite/deployment.py :
from initial_settings import LOGGING
LOGGING['loggers']['django'] = {
'handlers': ['console'],
'level': 'WARN',
'propagate': True,
}
/home/myuser/mysite/mysite/settings.py :
from deployment import LOGGING
/home/myuser/mysite/mysite/mysite.wsgi :
(mod_wsgi daemon mode and python-home directives are just around the corner but not merged yet, sorry to trigger Graham)
import os
import sys
activate_this_file = "/home/myuser/mysite/venv/bin/activate_this.py"
execfile(activate_this_file, dict(__file__=activate_this_file))
path = '/home/myuser/mysite'
if path not in sys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
# needed for upgrade django >=1.7
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()