So I've read through the Python Logging 101 (really useful) and the
logging docs:

http://plumberjack.blogspot.com/2009/09/python-logging-101.html
http://docs.python.org/library/logging.html

Here's my understanding of what we need to do for Django.

1. Create a 'django' logger somewhere in the framework that will
always be executed if part of Django has been imported - would the
django/__init__.py file work? Configure that with a NullHandler, and
set it NOT to propagate events to the root logger. That way we can
start using 'django.*' loggers throughout the framework but none of
the messages will be sent anywhere without further configuration. The
code should look something like this:

import logging

class NullHandler(logging.Handler):
    def emit(self, record):
        pass

logger = logging.getLogger('django')
logger.addHandler(NullHandler())
logger.propagate = False

NullHandler is a generally useful class (I'm surprised it's not part
of the core logging library), so we should probably put that in
django.utils.log. The NullHandler is there purely to prevent the one-
off "you haven't configured a handler yet" error that gets sent to
sys.stderr.

2. Start using loggers within the Django framework itself. The most
obvious place to start is SQL queries - at the point where we execute
SQL, we should do this:

logging.getLogger('django.db.sql').debug(sql_to_execute)

That logs the SQL to a 'django.db.sql' logger - which is a child of
the 'django' logger and hence will be swallowed by the NullHandler.

Another place we could use logging is to record cache gets and misses:

logging.getLogger('django.core.cache').debug('Cache miss for key %s',
key)

And for sending e-mail:

logging.getLogger('django.core.mail').info('Mail sent to %s',
to_email)

The logger names reflect the structure of Django up to a point
(django.db) but I don't think there's anything wrong with straying
from that convention (django.db.sql for example) provided the prefixes
are sensible.

3. Add a bunch of syntactic sugar for making log messages visible at
various points within Django. For example:

./manage.py runserver --log-level=django:info

Would cause the runserver to first configure the 'django' logger to
print all messages of level 'info' and higher to stdout.

./manage.py runserver --log-level=django:info --log-
level=django.db:debug

Same as above, but also configures django.db messages of debug or
higher to display (I'm sure the command line syntax could be
improved).

By default, runserver would display no log messages at all.

The same arguments could also work for ./manage.py test:

./manage.py test --log-level=django.db.sql:debug

Hmm... maybe the --log-level argument could work for ALL management
commands.

My philosophy here is that log messages should be ignored unless
explicitly told otherwise. Django gets run in various different ways -
runserver, test and in deployment under mod_wsgi/FastCGI/etc - and
it's not at all obvious what the default log output behaviour should
be. As long as we make it extremely easy to see log messages if we
want them I think having them off by default makes sense. It also
ensures no surprises for people upgrading from 1.1 to 1.2.

4. Add a way to configure loggers in Django's settings.py file, in
particular for use in production. I'm not sure if these settings
should be ignored when running under other circumstances (./manage.py
test etc) in favour of the command line option, or if they should
still take effect. I quite liked Ivan's suggestion:

LOGGING = {
     'django.db.sql': {
         'handler': 'django.logging.FileLogger', # WatchedFileLogger
copy
         'filename': '/tmp/django-sql.log',
         'level': 'debug',
     },
     'django.core.cache': {
         'handler': 'logging.handlers.HTTPHandler',
         'host': '...',
         'url': '....',
         'format': '....'
     },
     'django.errors': {
         'handler': 'logging.handlers.SMTPHandler',
         ...
     }
}

django.errors is where we get to replace the current "e-mail 500
errors to an ADMIN" functionality.

There should also be an option for advanced users to ignore the
declarative syntax entirely and just provide a bunch of code that
configures logging in the traditional way:

import logging
django_logger = logging.getLogger('django')
django_logger.setLevel(...)
django_logger.addHandler(...) # etc

I'm not sure where that custom code should live - right there in
settings.py? At any rate, I think it's vital that people can use the
low level logging configuration API if they want to.

I'd rather not encourage people to use the logging module's support
for .ini style configuration, just because Django already has its own
configuration standards. That's not to say people can't call that from
their own code if they want to, but I don't think we should emphasise
that ability.

5. Document how users should go about implementing their own loggers.
I think we should tell people NOT to put them within the 'django'
logger namespace - that should be reserved for core code. Instead,
application developers should use logging.getLogger('their-app-name')
- my OpenID library might do getLogger('django_openid') for example.

We might need to tell developers doing this to set up the NullHandler
on their base logger to again suppress that warning message. If so, we
could provide a utility method in django.utils.log:

def getLogger(name):
    logger = logging.getLogger(name)
    if not logger.handlers:
        logger.addHandler(NullHandler())
    return logger

There may well be a better way of doing this, or I may be
misunderstanding the logging library.

Once they've got their logger, they can do whatever they like with it.
Log messages can be turned on using the same mechanisms I described
above.

The above suggestions are based on my limited experience doing simple
logging, plus information gleaned from the two above documents. I have
absolutely no idea if this is the right approach - Vinjay, does this
look about right?

Cheers,

Simon
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to