Django logging does not write debug.log file issue - django

I just set up new server and while I'm checking it, I got 500 error. I expect that debug.log file has error message, However, when I check the file the file was empty. Nothing was written. So I changed the loggers settings may times, but still the file is empty and I can't fix the error because what is wrong with it...
This is my views.py
logger = logging.getLogger(__name__)
put this line to do logging.
settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'formatters': {
'simple': {
'format': '%(asctime)s %(filename)s:%(lineno)d %(message)s',
}
},
'handlers': {
'file': {
'level': 'DEBUG',
'filters': ['require_debug_false'],
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/service/debug.log',
'formatter': 'simple',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'ERROR',
'propagate': True,
},
}
}
if DEBUG:
del LOGGING['loggers']['django']
del LOGGING['handlers']['file']
if not os.path.exists('log'):
os.makedirs('log')
I attached my wsgi.py
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
application = get_wsgi_application()
This is settings.py where import local settings.
try:
from local_settings import *
except ImportError:
raise ImportError('You must create local_settings.py on project root')
This is local_settings.py
DEBUG=False

You don't have logger named views in your settings. It's only logger named django there. So try to use it in views.py:
logger = logging.getLogger('django')

what is the setting of DEBUG on your server?
because:
if DEBUG:
del LOGGING['loggers']['django']
del LOGGING['handlers']['file']
if DEBUG is True you are deleting the logger and handler...

Related

Log SQL queries even if DEBUG=False

This is my logging config in settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
'file': {
'class': 'logging.FileHandler',
'filename': os.path.join(BASE_DIR, 'logs', 'django.log'),
},
},
'loggers': {
'django': {
'handlers': ['file', 'console'],
'level': 'DEBUG',
},
'django.template': {
'handlers': ['file', 'console'],
'level': 'INFO',
},
'App': {
'handlers': ['file', 'console'],
'level': 'DEBUG',
},
},
}
There's a behavior that I can't explain: if I run with debug=True I can see all SQL queries being logged to the console, but when debug=False that doesn't happen, even if I don't change the configuration above.
Why is this? How can I determine in my logging config whether or not SQL queries are logged to the console?
Query logging goes way deeper as Django wraps the database cursor based on the truthiness of a computed property.
From Line 226, django.db.backends.base.base v2.2.6 sources
def _prepare_cursor(self, cursor):
"""
Validate the connection is usable and perform database cursor wrapping.
"""
self.validate_thread_sharing()
if self.queries_logged:
wrapped_cursor = self.make_debug_cursor(cursor)
else:
wrapped_cursor = self.make_cursor(cursor)
return wrapped_cursor
This computed property gets to be decided on where debugging is forced or debugging is enabled in project settings
From Line 149, django.db.backends.base.base v2.2.6 sources
#property
def queries_logged(self):
return self.force_debug_cursor or settings.DEBUG
You should be able to get a proxy to the default connection and force the debug cursor to be used.
from django.db import connection
connection.force_debug_cursor = True
I however advise against this approach and favor query audits in the database.
That's because existing loggers already filtered your logs. In this case is Django's logger.
DEFAULT_LOGGING = {
'filters': {
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
},
...
}
and django.utils.log.RequireDebugTrue
class RequireDebugTrue(logging.Filter):
def filter(self, record):
return settings.DEBUG
To solve this issue, you could disable existing loggers by set disable_existing_loggers: True or you can override the filter like so:
LOGGING = {
...
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'filters': [],
},
...
}
Step 1: Write patch_django function in patchers.py
# Created by BaiJiFeiLong#gmail.com at 2022/6/6
import importlib
import importlib.util
import sys
# noinspection DuplicatedCode
def patch_module(module_name, modification_func):
spec = importlib.util.find_spec(module_name)
source = spec.loader.get_source(module_name)
source = modification_func(source)
module = importlib.util.module_from_spec(spec)
code = compile(source, module.__spec__.origin, 'exec')
exec(code, module.__dict__)
sys.modules[module_name] = module
return module
def patch_django():
patch_module("django.db.backends.base.base", lambda x: x.replace(
"self.force_debug_cursor = False",
"self.force_debug_cursor = True"))
Step2: Call patch_django before django imported.
manage.py
__import__("importlib").import_module("patchers").patch_django() # noqa
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
wsgi.py
__import__("importlib").import_module("patchers").patch_django() # noqa
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
application = get_wsgi_application()
asgi.py
__import__("importlib").import_module("patchers").patch_django() # noqa
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
application = get_asgi_application()
Step 3: Make sure django.db.backends is in debug level
'django.db.backends': {
'level': 'DEBUG',
},

How configure Django logging to file for app

I am struggling with Django logging configuration. I have one app called "api" and I want to save to file all logs from this app. When I set up a logger to django everything works fine but when I change it to my app_name it doesn't.
Here is my configuration:
File structure:
email_api
api
tasks.py
email_api
celery.py
settings
logs
email.log
My logging configuration:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': 'logs/email.log',
},
},
'loggers': {
'api': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
tasks.py file where I logging:
import logging
logger = logging.getLogger(__name__)
#app.task(bind=True, default_retry_delay=3, max_retries=3,)
def send_email(self, data, email_id):
message = create_message(data, email)
try:
logger.debug("Log Message Here")
message.send()
Keys in the LOGGING['loggers'][...] dict are names of loggers. You have configured logging with api as a name of the logger.
In order to write to this logger, you should request it by that name:
logger = logging.getLogger('api')
...
logger.debug("Log Message Here")

Celery periodic tasks not running when root logger is configured to use raven

I'm using Django with Celery in order to execute periodic tasks and Raven as a sentry client.
So far I've managed to run several apps with celery beat and all worked fine.
For some reason, In a recent app I'm working on, when I'm settings the root logger to use a 'sentry' hander, the periodic tasks are not running.
When settings the root logger to only use 'console' handler, it does work.
I can't wrap my head around what causing this issue.
This is my logging dict:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'root': {
'level': os.environ.get('LOG_LEVEL','INFO'),
'handlers': ['console'],
},
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
},
'sentry': {
'level': 'WARNING',
'class': 'raven.contrib.django.raven_compat.handlers.SentryHandler',
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'raven': {
'level': 'WARNING',
'handlers': ['console','sentry'],
'propagate': True,
},
'celery': {
'handlers': ['console'],
'level': 'DEBUG',
},
}
}
And the env var controlling the root logger handlers:
ENABLE_SENTRY = os.environ.get('ENABLE_SENTRY', 'FALSE') == 'TRUE'
if (ENABLE_SENTRY):
LOGGING['root']['handlers'] = ['console','sentry']
Note: Seems like the root logger doesn't log to console after that change
This is how I run the celery beat and worker:
python manage.py celery worker -E -B --maxtasksperchild=1000
--concurrency=10 --loglevel=DEBUG -Ofair
This is part of the packages I'm using:
celery==3.1.17 django-celery==3.1.16 raven==5.0.0 Django==1.8.7
This is my celery.py file:
"""
This module will hold celery configuration
"""
from __future__ import absolute_import
from django.conf import settings
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ltg_backend_app.settings')
# init the celery app
app = Celery('ltg_backend_app')
# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
Any help would be greatly appreciated!
did you configure raven to trap the necessary signals needed in order to work with Celery? here's how i configure my Celery app:
import celery
from django.conf import settings
import raven
from raven.contrib.celery import register_signal, register_logger_signal
class Celery(celery.Celery):
def on_configure(self):
#
# https://docs.sentry.io/clients/python/integrations/celery/
#
if 'dsn' in settings.RAVEN_CONFIG and settings.RAVEN_CONFIG['dsn']:
client = raven.Client(settings.RAVEN_CONFIG['dsn'])
else:
client = raven.Client() # should do nothing
# register a custom filter to filter out duplicate logs
register_logger_signal(client)
# hook into the Celery error handler
register_signal(client)
app = Celery('foobar')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
see here for more config options and details: https://docs.sentry.io/clients/python/integrations/celery/

django logger can't output the response content

I'm use django 1.4.6, I want to use the logger module integrated with django to output the response content, however, I cannot see it in the log file.
Source sample shown here:
import logging
logger = logging.getLogger('__file__')
...
response = redirect(url)
logger.debug(response.content)
return response
Once you have configured your loggers, handlers, filters and formatters,
You need to call it as follows:
import logging
# Standard instance of a logger with __name__
stdlogger = logging.getLogger(__name__)
logger.debug(response.content)
response = redirect(url)
return response
The call to logging.getLogger() obtains (creating, if necessary) an instance of a logger. The logger instance is identified by a name. This name is used to identify the logger for configuration purposes.
By convention, the logger name is usually name .
The Python name syntax used for getLogger automatically assigns the package name as the logger name.
Please show peple configuration of logging in static file
I have little change for your code
logger = logging.getLogger(__name__)
Log configuation on settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': "[%(asctime)s] %(levelname)s %(message)s",
'datefmt': "%d/%b/%Y %H:%M:%S"
}
},
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/var/log/django_practices.log',
'formatter': 'verbose'
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'stream': sys.stdout,
'formatter': 'verbose'
},
},
'loggers': {
'name_your_app_django': {
'handlers': ['file', 'console'],
'level': ode'DEBUG',
}
}
}
In my configuration log will be print in console and file name.
Note : name_your_app_django change to fix with your code.

How to use sentry/raven in django views

I managed to install sentry successfully and I can see the sentry interface webservice at localhost and doing a
raven test http://jsifslkdjfklsdfjklsdjfklMYCODE
works, the tests shows up in the interface.
The problem is I can't find any examples or documentation on what exactly should I put on my views and my settings.
I know I have to add to my INSTALLED_APPS
'sentry',
'raven.contrib.django',
And I also added
SENTRY_DNS = 'http://jsifslkdjfklsdfjklsdjfklMYCODE'
This next two lines appear in the docs but it doesnt say where do they go
from raven.contrib.django.models import client
client.captureException()
I tried in settings.py but still I can't get my views to log anything.
I also added this
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'root': {
'level': 'WARNING',
'handlers': ['sentry'],
},
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
},
'handlers': {
'sentry': {
'level': 'ERROR',
'class': 'raven.contrib.django.handlers.SentryHandler',
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose'
}
},
'loggers': {
'django.db.backends': {
'level': 'ERROR',
'handlers': ['console'],
'propagate': False,
},
'raven': {
'level': 'DEBUG',
'handlers': ['console'],
'propagate': False,
},
'sentry.errors': {
'level': 'DEBUG',
'handlers': ['console'],
'propagate': False,
},
},
}
And in my views I added this:
import logging
logger = logging.getLogger()
def home(request,template_name):
logger.error('There was some crazy error lol', exc_info=True, extra={'request': request, })
return render_to_response(template_name,context, context_instance=RequestContext(request))
I have no other code related to logging apart from what you see here, What am I missing?
Your 'raven' logger is not actually using the sentry handler, but only writing to 'console'. Had the same problem. The documentation for raven/sentry lacks a good writer.
change your raven logger to:
'raven': {
'level': 'DEBUG',
'handlers': ['console', 'sentry'],
'propagate': False,
},
and make sure you use it as logger:
logger = logging.getLogger('raven')
I had to use this monstruosity on my settings.py:
import logging
# from raven.contrib.django.handlers import SentryHandler
from raven.handlers.logging import SentryHandler
logging.getLogger().setLevel(logging.INFO)
logger = logging.getLogger()# ensure we havent already registered the handler
handler = SentryHandler('http://13d06dad246d4fe6a180ef9b15151a13:eb46a6d724df4327a8cc04d9d3cfad37#sentry.bandtastic.pagekite.me/1')
logger.addHandler(handler)
# Add StreamHandler to sentry's default so you can catch missed exceptions
logger = logging.getLogger('sentry.errors')
logger.propagate = False
logger.addHandler(logging.StreamHandler())
from raven.conf import setup_logging
setup_logging(handler)
And in my views i can use a simple
import logging
logger = logging.getLogger(__name__)
def home(request,context={},template_name=None):
logger.info(str(request), exc_info=True)
return render_to_response(template_name,context, context_instance=RequestContext(request))
I tried many settings.