views:

1112

answers:

3

I have yet to find a way of setting up Python logging with Django that I'm happy with. My requirements are fairly simple:

  • Different log handlers for different events - that is, I want to be able to log to different files
  • Easy access to loggers in my modules. The module should be able to find its logger with little effort.
  • Should be easily applicable to command-line modules. Parts of the system are stand-alone command line or daemon processes. Logging should be easily usable with these modules.

My current setup is to use a logging.conf file and setup logging in each module I log from. It doesn't feel right.

Do you have a logging setup that you like? Please detail it: how do you setup the configuration (do you use logging.conf or set it up in code), where/when do you initiate the loggers, and how do you get access to them in your modules, etc.

+2  A: 

I am currently using logging system, which I created by my self. For loging it use csv format.

django-csvlog

This project still doesn't have a full documentation, but I working on it.

Oduvan
+13  A: 

The best way I've found so far is to initialize logging setup in settings.py - nowhere else. You can either use a configuration file or do it programmatically step-by-step - it just depends on your requirements. The key thing is that I usually add the handlers I want to the root logger, using levels and sometimes logging.Filters to get the events I want to the appropriate files, console, syslogs etc. You can of course add handlers to any other loggers too, but there isn't commonly a need for this in my experience.

In each module, I define a logger using

logger = logging.getLogger(__name__)

and use that for logging events in the module (and, if I want to differentiate further) use a logger which is a child of the logger created above.

If my app is going to be potentially used in a site which doesn't configure logging in settings.py, I define a NullHandler somewhere as follows:

#someutils.py

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

null_handler = NullHandler()

and ensure that an instance of it is added to all loggers created in the modules in my apps which use logging. (Note: NullHandler is already in the logging package for Python 3.1, and will be in Python 2.7.) So:

logger = logging.getLogger(__name__)
logger.addHandler(someutils.null_handler)

This is done to ensure that your modules play nicely in a site which doesn't configure logging in settings.py, and that you don't get any annoying "No handlers could be found for logger X.Y.Z" messages (which are warnings about potentially misconfigured logging).

Doing it this way meets your stated requirements:

  • You can set up different log handlers for different events, as you currently do.
  • Easy access to loggers in your modules - use getLogger(__name__).
  • Easily applicable to command-line modules - they also import settings.py.
Vinay Sajip
Won't this require that every module have a handler defined in the config (you cannot use a handler for foo to handle foo.bar)? See the conversation we had years ago at http://groups.google.com/group/comp.lang.python/browse_thread/thread/6a199393bcee6c1b/2ddf482a44bc4bb1
andrew cooke
@andrew cooke: You *can* use a handler for `foo` to handle events logged to `foo.bar`. Re. that thread - both fileConfig and dictConfig now have options to prevent disabling old loggers. See this issue: http://bugs.python.org/issue3136, which came in a couple of months after your issue http://bugs.python.org/issue2697 - anyway, it's been sorted out since June 2008.
Vinay Sajip
+3  A: 

We initialize logging in the top-level urls.py by using a logging.ini file.

The location of the logging.ini is provided in settings.py, but that's all.

Each module then does

logger = logging.getLogger(__name__)

To distinguish testing, development and production instances, we have different logging.ini files. For the most part, we have a "console log" that goes to stderr with Errors only. We have an "application log" that uses a regular rolling log file that goes to a logs directory.

S.Lott
I ended up using this, except initializing in settings.py instead of urls.py
Parand
How do you use settings from settings.py in your logging.ini file? For example, I need the BASE_DIR setting, so I can tell it where to store my log files.
slypete
@slypete: We don't use settings in the logging.ini. Since the logging is largely independent, we don't use any of the Django settings. Yes, there's a possibility of repeating something. No, it doesn't make much practical difference.
S.Lott
In that case, I would a separate logging.ini file in every installation of my app.
slypete
@slypete: You have a settings.py for each installation. You also have a logging.ini for each installation. Plus, you probably have an Apache conf file for each installation, also. Plus a wsgi interface file. I'm not sure what your point is.
S.Lott