Search code examples
pythondjangologgingpathpython-logging

How to set a dirname and file instead of filepath or filename in Django logging?


We are looking to log the path of the file being logged.

For example I have the file views.py - this file name is repeated in the many applications of a Django project thus we need the file name to include the app name - polls\views.py On the other hand we don't want the full absolute path..

This is the format line:

format": "{levelname}: {message} at {asctime} in {filename} {funcName} {lineno} (process={process: d}, thread={thread:d})"

According to this thread we only have the following related options: filename, module, and pathname which do not suffice.

Have not found help from Django logging docs

Also tried string manipulating with {os.path.dirname(pathname)} but it doesn't appear to parse right

We get

    raise ValueError('Unable to configure '
ValueError: Unable to configure formatter 'verbose'

This is the LOGGING snippet from our settings.py:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            "format": "{levelname}: {message} at {asctime} in {filename} {funcName} {lineno} (process={process: d}, thread={thread:d})",
            "style": "{",
        },
        'default': {
            'format': '%(asctime)s - %(levelname)s - %(module)s - %(lineno)d => %(message)s',
            'datefmt': '%Y-%m-%d %H:%M:%S'
        },
    },
    'handlers': {
        'error_file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'level': 'DEBUG',
            'formatter': 'verbose',
            'filename': f'logs/error_{datetime.datetime.today().strftime("%Y-%m-%d")}.log',
        },
        'info_file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'level': 'INFO',
            'formatter': 'verbose',
            'filename': f'logs/info_{datetime.datetime.today().strftime("%Y-%m-%d")}.log',
        },
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'default',
        },
    },
    'loggers': {
        'error_logger': {
            'handlers': ['error_file', 'console'],
            'level': 'DEBUG',
            'propagate': False,
        },
        'info_logger': {
            'handlers': ['info_file', 'console'],
            'level': 'INFO',
            'propagate': False,
        },
    },
}

Solution

  • You can try to use extra context as describe in this post.

    In your views, add your app as extra context:

    import logging
    
    logger = logging.getLogger(__name__)
    
    def my_function():
        app_name = 'my_app'  # Replace with your app name
        logger.info('This is a log message', extra={'app_name': app_name})
    

    In your settings.py, add '{app_name}' in your formatter, for example:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'verbose': {
                "**format": "{levelname}: {message} at {asctime} in {filename} {funcName} {lineno} (process={process: d}, thread={thread:d})"**,
                "style": "{",
            },
            'default': {
                'format': '%(asctime)s - %(levelname)s - %(module)s - %(lineno)d => %(message)s',
                'datefmt': '%Y-%m-%d %H:%M:%S'
            },
            # Add a new formatter for including the app_name with your desired format
            'app_formatter': {
                'format': '{levelname}: {message} {asctime} {module} {app_name} {filename} {funcName} {lineno} {process:d} {thread:d} {message}',
                'style': '{',
            },
        },
        'handlers': {
            'error_file': {
                'class': 'logging.handlers.RotatingFileHandler',
                'level': 'DEBUG',
                'formatter': 'verbose',
                'filename': f'logs/error_{datetime.datetime.today().strftime("%Y-%m-%d")}.log',
            },
            'info_file': {
                'class': 'logging.handlers.RotatingFileHandler',
                'level': 'INFO',
                'formatter': 'verbose',
                'filename': f'logs/info_{datetime.datetime.today().strftime("%Y-%m-%d")}.log',
            },
            'console': {
                'class': 'logging.StreamHandler',
                'formatter': 'app_formatter',  # Use the new app_formatter
            },
        },
        'loggers': {
            'error_logger': {
                'handlers': ['error_file', 'console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'info_logger': {
                'handlers': ['info_file', 'console'],
                'level': 'INFO',
                'propagate': False,
            },
        },
    }