I have a class named "Photo" in my Django application which is not writing messages to my log file when an error occurs.
My project hierarchy looks like this:
- myproj
- apps
- classes
- classes/__init__.py
- classes/photo.py
Here is my LOGGING configuration setting:
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'standard': {
'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
'datefmt' : "%d/%b/%Y %H:%M:%S"
},
},
'handlers': {
'null': {
'level':'DEBUG',
'class':'django.utils.log.NullHandler',
},
'logfile': {
'level':LOG_LEVEL,
'class':'logging.handlers.RotatingFileHandler',
'filename': '/var/log/myproj/apps.log',
'maxBytes': 50000,
'backupCount': 2,
'formatter': 'standard',
},
'database_logfile': {
'level':LOG_LEVEL,
'class':'logging.handlers.RotatingFileHandler',
'filename': '/var/log/myproj/database.log',
'maxBytes': 50000,
'backupCount': 2,
'formatter': 'standard',
},
'console':{
'level':LOG_LEVEL,
'class':'logging.StreamHandler',
'formatter': 'standard'
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler'
# Only send emails when DEBUG = False
#'filters': ['require_debug_false'],
},
},
'loggers': {
'django': {
'handlers':['console'],
'propagate': True,
'level':'WARN',
},
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'django.db.backends': {
'handlers': ['database_logfile'],
'level': 'DEBUG',
'propagate': False,
},
'apps': {
'handlers': ['console', 'logfile', 'mail_admins'],
'level': 'DEBUG',
},
'classes.photo': {
'handlers': ['console', 'logfile', 'mail_admins'],
'level': 'DEBUG',
},
}
}
Here's part of my class:
# photo.py
import logging
logger = logging.getLogger(__name__)
class Photo:
def create_gallery_photo(self):
...
photo_size = os.path.getsize()
if photo_size > PHOTO_SIZE_LIMIT:
logger.error("Photo too big")
At first I only had an 'apps' handler and I realized that the error
wouldn't get logged since photo.py was outside the 'apps' application. But when I added a 'classes' logger I started getting a "No classes could be found for logger" error. Not sure of what to do, I changed the logger to 'classes.photo' and the 'no classes' error went away but the error message still isn't getting logged. I checked 'logger.name' and it's set to 'classes.photo'. Is there something else I need to do because this error is being logged from a class? All the logging in my 'apps' project is working just fine.
Try adding a root logger with a console handler, and see what %(name)s gets logged there. All messages should reach that, unless they first get handled by a logger with propagate=False.
...
'loggers': {
...,
'': {
'handlers': ['console'],
'level': 'DEBUG',
},
}
...
Related
What I want to achieve is that warning and errors that happen in production (i.e. DEBUG=False) are logged into to a rotating log file.
I tried this
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'handlers': {
'file': {
'level': 'WARNING',
'class': 'logging.FileHandler',
'filename': 'staging.log',
},
},
'loggers': {
'': {
'handlers': ['file'],
'level': 'WARNING',
'propagate': True,
},
'django': {
'handlers': ['file'],
'level': 'WARNING',
'propagate': True,
},
'django.request': {
'handlers': ['file'],
'level': 'WARNING',
'propagate': True,
},
},
}
However, the above logs everything, not just messages of log level WARNING and above.
You can follow the django logger here.
In your views.py:
import logging
logger = logging.getLogger(__name__)
then you can record using logger.error() or logger.warning() or logger.info().
It will create a logger file in your main project directory and it will list out all the logging details.
See this:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
'simple': {
'format': '{levelname} {message}',
'style': '{',
},
},
'handlers': {
'logfile': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'filename': "yourproject_name.log",
'maxBytes': 100000,
'backupCount': 2,
'formatter': 'verbose',
},
},
'loggers': {
'django': {
'handlers': ['logfile'],
'level': 'INFO',
'propagate': True,
},
'apps': {
'handlers': ['logfile'],
'level': 'DEBUG',
'propagate': True,
},
},
}
I'm trying to integrate logging with loki in my django app like this:
handler = logging_loki.LokiHandler(
url="http://localhost:3100/loki/api/v1/push",
tags={"app": "django", "env": ENV},
version="1",
)
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '[%(asctime)s] {%(module)s} [%(levelname)s] - %(message)s',
'datefmt': '%d-%m-%Y %H:%M:%S'
},
},
'handlers': {
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'standard',
}
},
'loggers': {
'': {
'handlers': ['console', handler], # this doesnt work
'level': 'DEBUG',
'propagate': True,
# 'name': ENV
}
}
}
What do I need to change so that django uses this custom handler? I tried just referencing the handler object in the logging dict but that didn't need to be the right approach.
I also tried this:
LOGGING_CONFIG = None
logging.config.dictConfig(LOGGING)
logging.getLogger(__name__).addHandler(handler)
but that's not sending any logs to loki
Try this:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '[%(asctime)s] {%(module)s} [%(levelname)s] - %(message)s',
'datefmt': '%d-%m-%Y %H:%M:%S'
},
},
'handlers': {
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'standard',
},
'loki': {
'level': 'INFO',
'class': 'logging_loki.LokiHandler',
'url': "http://localhost:3100/loki/api/v1/push",
'tags' {"app": "django", "env": ENV},
'version': "1",
},
},
'loggers': {
'': {
'handlers': ['console', 'loki'],
'level': 'DEBUG',
'propagate': True,
}
}
}
Specifically, you have to:
Define you handler in the handlers dictionary in the LOGGING setting. The configuration here is used to specify the initialisation arguments for the handler.
Then assign this handler using its key (loki in the example I've given above) to the logger(s) you want it to handle.
I have a test in django (v2.2) that generates an error on purpose to check that errors are logged in the proper log files.
But I get also a print in the console which is kind of annoying, I was looking for a way to hide the message.
If I disable logging with logging.disable(logging.CRITICAL), it will not log the error in the files.
I also tried to use with self.settings(LOGGING=logging) after removing the console handler from the loggers (see settings below) but it does not seem to be taken into account.
Also, setting disable_existing_logger to True does not help.
Do you have some ideas how to do that?
my settings:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'msg_filter': {
'()': MessageFilter,
'strings_to_be_ignored': [
'Not Found: /favicon.ico'
],
}
},
'formatters': {
'verbose': {
'format': '_____________________________________________________________'
'\n%(asctime)s - [%(levelname)s|%(name)s] %(message)s\n'
},
'simple': {
'format': '%(asctime)s - [%(levelname)s|%(name)s] %(message).50s'
},
},
'handlers': {
'warning': {
'level': 'WARNING',
'class': 'logging.FileHandler',
'filename': '/some_folder/warning.log',
'formatter': 'verbose',
'filters': ['msg_filter']
},
'warning_simple': {
'level': 'WARNING',
'class': 'logging.FileHandler',
'filename': '/some_folder/warning.log',
'formatter': 'simple',
'filters': ['msg_filter']
},
'info': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/some_folder/info.log',
'maxBytes': 1024 * 1024 * 2,
'backupCount': 9,
'formatter': 'simple',
'filters': ['msg_filter']
},
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
'filters': ['msg_filter']
},
'console_simple': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'simple',
'filters': ['msg_filter']
}
},
'loggers': {
'': {
'handlers': ['console', 'info', 'warning'],
'level': 'DEBUG',
'propagate': False,
},
'django': {
'handlers': ['console_simple', 'info', 'warning_simple'],
'level': 'DEBUG',
'propagate': False,
}
}
}
You should set disable_existing_loggers variable True. This variable being true means the loggers is disabled.
Read this:
https://docs.djangoproject.com/en/3.0/topics/logging/#configuring-logging
you can add the --logging-clear-handlers option.
python manage.py test --logging-clear-handlers
I'm trying to figure out logging in Django (checking out Python logging itself for the first time too for that matter).
I have the following in my settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/home/afzalsh/logs/debug.log',
},
},
'loggers': {
'django.request': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
This is the exact code as what Django documentation has as the first example.
Then I have a log message in a class based view.
import logging
.
.
.
class StationHome(View):
.
.
.
def post(self,request, pk):
station = Station.objects.get(pk=pk)
form = StationForm(request.POST, instance=station)
if form.is_valid():
logger = logging.getLogger(__name__)
logger.error("Yep!")
form.save()
return HttpResponseRedirect(reverse("home_station",
kwargs={'pk':pk},
)
)
else:
return HttpResponse("Form Invalid")
.
.
.
The debug.log file has got created but it doesn't get populated with any message on going through the particular code. The expected process do happen.
You've requested the logger associated with __name__, so you get one named the same as the current Python module. However, the only one you've actually configured is "django.request". You should use that in your call to getLogger instead.
In your settings your handler dict contains level 'debug' for file where as in your code you are using 'error' level to log.
logger.error("Yep!")
Try using 'debug' level in your code. Something like this:
logger.debug("Yep!")
also posting my settings here so that you can use that as a reference.
{
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'standard' : {
'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
'datefmt' : "%d/%b/%Y %H:%M:%S"
},
},
'handlers': {
'console':{
'level': 'DEBUG',
'class': 'logging.StreamHandler'
},
'null' : {
'level':'DEBUG',
'class':'django.utils.log.NullHandler',
},
'file' : {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': 'debug.log',
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'django': {
'handlers': ['file'],
'propogate': True,
'level': 'DEBUG',
},
'matchroom_app':{
'handlers' : ['file'],
'level': 'DEBUG',
},
'matchroom_post':{
'handlers' : ['file'],
'level' : 'DEBUG',
},
'matchroom_social':{
'handlers': ['file'],
'level' : 'DEBUG',
},
}
}
My Django 1.3 logging setup causes all log messages to be output twice. I've read that importing settings.py two or more times has caused this problem in the past, but Django 1.3 has new logging features, and I don't think I'm importing settings.py twice anywhere.
settings.py config:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {
'format': '%(levelname)s: %(message)s'
},
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple',
},
},
'loggers': {
'custom': {
'handlers': ['console'],
'level': 'DEBUG',
},
}
}
Code:
import logging
log = logging.getLogger('custom')
log.debug('message1')
log.debug('message2')
Output:
DEBUG: message1
DEBUG:custom:message1
Thanks for your help.
Have you tried setting propagate = False? Along with disable_existing_loggers = True?
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'simple': {
'format': '%(levelname)s: %(message)s'
},
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple',
},
},
'loggers': {
'custom': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': False,
},
}
}
You might want to try 'disable_existing_loggers': True?
I've been suffered by the same issue. And I fixed it by redirecting the root logs to a file, and project logs to both the file and the console.
I grep my code, and could not find anywhere basicConfig() exists, also tried to set disable_existing_loggers to True, It doesn't help, finally solved the problem by set a file logger. I guess it maybe a problem by design in some cases.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {
# exact format is not important, this is the minimum information
'format': '%(asctime)s %(name)-12s %(lineno)d %(levelname)-8s %(message)s',
},
},
'handlers': {
'console': {
#'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'simple',
},
# Add Handler for mail_admins for `warning` and above
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
},
'file': {
#'level': 'INFO',
'class': 'logging.FileHandler',
'formatter': 'simple',
'filename': os.path.join(os.path.dirname(PROJECT_ROOT), 'crawler.admin.log'),
},
},
'loggers': {
# root logger
'': {
'level': 'INFO',
'handlers': ['file', 'mail_admins'],
},
'scrapy': {
'level': 'WARNING',
'handlers': ['console', 'mail_admins'],
'propagate': False,
},
'crawleradmin': {
'level': 'INFO',
'handlers': ['console', 'file', 'mail_admins'],
# required to avoid double logging with root logger
'propagate': False,
},
},
}