2

This is for Python 2.7 ....

I have a Django project, and I use logging.config.dictConfig(CONFIG) to get the logging that I want when running the Django app as a server. I have my own module in mycore.logging, and it creates a logger object at import-time. This is all great.

However, Django has independent 'management commands' and I want to log each management command to its own separate file. The logfile name would be the name of the management command + ".log".

I've searched and googled and not found any examples of this. Is it really so unusual? Or have I just not found the prior art?

I think I know how to remove the existing FileHandler, instantiate a new one with my desired output file, and add it as a handler on the logger object.

But it seems like a clunky thing to do. Any advice will be welcome.

import logging
import logging.config
from logutils.colorize import ColorizingStreamHandler
from django.conf import settings

class ColorHandler(ColorizingStreamHandler):
    def __init__(self, *args, **kwargs):
        super(ColorHandler, self).__init__(*args, **kwargs)
        self.level_map = {
                # Provide your custom coloring information here
                logging.DEBUG: (None, 'blue', False),
                logging.INFO: (None, 'green', False),
                logging.WARNING: (None, 'yellow', False),
                logging.ERROR: (None, 'red', False),
                logging.CRITICAL: ('red', 'white', True),

        }

try:
    CONSOLE_LOG_LEVEL = settings.CONSOLE_LOG_LEVEL
except AttributeError as ae:
    CONSOLE_LOG_LEVEL =  logging.INFO
try:
    FILE_LOG_LEVEL = settings.FILE_LOG_LEVEL
except AttributeError as ae:
    FILE_LOG_LEVEL =  logging.DEBUG

CONFIG = {
    'version':1,
    'disable_existing_loggers': True,
    'handlers':{
        'console': {
            '()':ColorHandler,
            'level': CONSOLE_LOG_LEVEL,
            'formatter': 'simplest',
            'stream': 'ext://sys.stdout',
        },
        'file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'level': FILE_LOG_LEVEL,
            'formatter': 'simplest',
            'filename': './log-oxfam.txt',
            'mode': 'a',
            'maxBytes': 10485760,
            'backupCount': 5,
        },
    },
    'formatters': {
        'simplest': {
            'format': '%(levelname)-8s %(message)s',
        },
        'time_level_message': {
            'format': '%(asctime)s %(levelname)-8s %(message)s',
        },
        'detailed': {
            'format': '%(asctime)s %(module)s line:%(lineno)-4d %(levelname)-8s %(message)s',
        },
    },
    'loggers': {
        'myDjangoApp': {
            'level':'DEBUG',
            'handlers':['console', 'file'],
            ###'handlers':['console'],
        },
    },
}

logging.config.dictConfig(CONFIG)
logger = logging.getLogger("myDjangoApp")

1 Answer 1

1

I would base the solution around logging.handlers.QueueHandler. It's pretty much the only one that isn't tied to a storage facility. Your listeners can decide at runtime where to put things.

Sign up to request clarification or add additional context in comments.

4 Comments

My bad. I need a solution in python 2.7. I clarified the description to say so.
Don't see an easy solution there. You'd pretty much have to somehow teach a MemoryView to go threaded with the old threading library that doesn't have a Queue (luckily there is collections.deque, but still). I now remember why I migrated to 3.x though :)
I think I haven't been clear about the thing that I want. Here is a summary: -- At import time, my utility code instantiates a log object. That does what I need. -- At __main__() time, in selected, independent commands, I want to replace (entirely) the FileHandler that exists within my logger object, with new FileHandler object with the same attributes as the original except that it writes to a different file.
@BillTorcaso You can use the logutils project to provide QueueHandler functionality under Python 2.7 - pip install logutils.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.