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',
},
}
}
Related
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'm using Sentry with Django like this:
sentry_integration = DjangoIntegration()
sentry_sdk.init(
dsn="https://xxx#sentry.io/xxx",
integrations=[sentry_integration]
)
and with these settings for logging:
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',
}
},
}
If I instiantiate and call a logger in my code, this gets sent to Sentry.
import logging
logger = logging.getLogger(__name__)
logger.error("error!")
However, now I'd like to also log .warning calls. The documentation says to do this:
sentry_logging = LoggingIntegration(event_level=logging.WARNING)
sentry_sdk.init(
dsn="https://xxx#sentry.io/xxx",
integrations=[sentry_logging]
)
But the LoggingIntegration is used rather than the DjangoIntegration. I've tried to use DjangoIntegration in the code above but I get this error:
TypeError: init() got an unexpected keyword argument 'event_level'
Is this possible?
The integrations argument is a list. You can pass in both integrations:
init(
integrations=[LoggingIntegration(...), DjangoIntegration(...)]
)
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',
},
}
...
I'm install both Dajaxice and Dajax with sucess (they both works)
But i get some warning in dev server log
The 'request' object must be accesible within the context. You must add 'django.contrib.messages.context_processors.request' to your TEMPLATE_CONTEXT_PROCESSORS and render your views using a RequestContext.
If i try to add to TEMPLATE_CONTEXT_PROCESSORS django.contrib.messages.context_processors.request
it will raise error about no context_processors.request in django.contrib.messages
Also i render my templates with context like
return render_to_response('root.html', {'news' : news, 'author' : author }, context_instance=RequestContext(request))
My log section in settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'dajaxice': {
'handlers': ['console'],
'level': 'INFO',
'propagate': True,
},
'dajaxice.DajaxiceRequest': {
'handlers': ['console'],
'level': 'INFO',
'propagate': True,
},
}
}
You have to change
django.contrib.messages.context_processors.request
to
django.contrib.messages.context_processors.messages
It's messages not request
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,
},
},
}