2

I have this LOGGING settings for my Django app. What I was expecting is that the views logs would go into their own separate folder when I have three different loggers in my views file.

Logger in my settings file:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'views_error_file': {
            'class': 'logging.FileHandler',
            'filename': 'logs/errors/views.debug.log',
        },
        'views_info_file': {
            'class': 'logging.FileHandler',
            'filename': 'logs/infos/views.debug.log',
        },
        'views_debug_file': {
            'class': 'logging.FileHandler',
            'filename': 'logs/debugs/views.debug.log',
        }
    },
    'loggers': {
        'py_folder.views': {
            'handlers': ['views_error_file'],
            'level': 'ERROR',
        },

        'py_folder.views': {
            'handlers': ['views_info_file'],
            'level': 'INFO',
        },

        'py_folder.views': {
            'handlers': ['views_debug_file'],
            'level': 'DEBUG',
        }
    }
}

The views.py file:

import logging
# Get an instance of a logger
logger = logging.getLogger(__name__)

def sample_function(request):
    params_choices = ['param_1', 'param_2']

    sample_param = request.POST.get('sample_param')
    # logger.debug should be logged at logs/debugs/views.debug.log
    logger.debug(sample_param)
    if sample_param in params_choices:
        if sample_param == 'param_1':
            # logger.info should be logged at logs/infos/views.debug.log
            logger.info("param_1 okay")
            return redirect("/param_1-req")
        else:
            # logger.error should be logged at logs/error/views.debug.log
            logger.error("param_2 okay")
            return redirect("/param_2-req")
    else:
        logger.error("param does not exist")
            return redirect("/param-invalid")

But its only going in to the logs/debugs/views.debug.log.

The logs/debugs/views.debug.log file:

param_3
param does not exist

As you can see, both logger.debug and logger.error logged to the logs/debugs/views.debug.log. I tried changing the logs/info/views.debug.log file to logs/infos/views.info.log and logs/error/views.error.log to logs/error/views.error.log but nothing changed.

I don't know why this is the behavior. I am new to Django. Please help.

Prosy Arceno
  • 2,616
  • 1
  • 8
  • 32

1 Answers1

2

Well, I've come up with something.

Inside your app (in this example it's the polls app from tutorial), create a directory logs, and inside it a file named handlers.py, with this content:

from logging import FileHandler, INFO, ERROR, DEBUG

class AppFileHandler(FileHandler):
    def __init__(self, filename, loglevel, mode, encoding, delay):
        super().__init__(filename, mode, encoding, delay)
        self.loglevel = loglevel
    
    def emit(self, record):
        if not record.levelno == self.loglevel:
            return
        super().emit(record)

class AppDebugFileHandler(AppFileHandler):
    def __init__(self, filename, mode='a', encoding=None, delay=False):
        super().__init__(filename, DEBUG, mode, encoding, delay)

class AppErrorFileHandler(AppFileHandler):
    def __init__(self, filename, mode='a', encoding=None, delay=False):
        super().__init__(filename, ERROR, mode, encoding, delay)

class AppInfoFileHandler(AppFileHandler):
    def __init__(self, filename, mode='a', encoding=None, delay=False):
        super().__init__(filename, INFO, mode, encoding, delay)

Then change LOGGING as this:

import os # you can move this import to beginning of settings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'views_info_file': {
            'class': 'polls.logs.handlers.AppInfoFileHandler',
            'filename': os.path.join(BASE_DIR, 'views.info.log'),
        },
        'views_error_file': {
            'class': 'polls.logs.handlers.AppErrorFileHandler',
            'filename': os.path.join(BASE_DIR, 'views.error.log'),
        },
        'views_debug_file': {
            'class': 'polls.logs.handlers.AppDebugFileHandler',
            'filename': os.path.join(BASE_DIR, 'views.debug.log'),
        },
    },
    'loggers': {
        'polls.views': {
            'handlers': ['views_info_file', 'views_error_file', 'views_debug_file'],
            'level': 'DEBUG'
        },
    }
}

This will create 3 log files on root of your project (not app, you can customize the filename directory).

This works, but perhaps it's not the best way, may be reinventing the wheel here. Also the level: 'DEBUG' setting no longer indicates the error level logging, this should be stressed in a comment on settings.

Niloct
  • 9,491
  • 3
  • 44
  • 57
  • 1
    This worked!!! only its putting the file on the root directory, not on the logs folder I created. – Prosy Arceno May 10 '21 at 02:01
  • Is it because of the BASE_DIR? should I add something more here? – Prosy Arceno May 10 '21 at 02:03
  • 1
    nevermind. I added this `PY_ROOT = 'py_folder'` `LOGGING_ROOT = os.path.join(PY_ROOT , 'logs')` and used it istead of `BASE_DIR`. Thanks so much – Prosy Arceno May 10 '21 at 02:11
  • Yes you can put something like `os.path.join(BASE_DIR, '/polls/logs/views.error.log')`, then in my example it would put the logfile inside the same dir as the `handlers.py`. – Niloct May 10 '21 at 02:13