Django logger refuse to show full traceback in file message

Question:

Currently, i’m setting up logging in Django following the document https://docs.djangoproject.com/en/2.2/topics/logging/ (I’m using Django 2.2 with python3.7) and Django rest framework.
Here is my settings.py:

# LOGGING 
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'simple': {
            'format': '{levelname} {asctime} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'file': {
            'level': 'ERROR',
            'class': 'logging.FileHandler',
            'filename': '/var/log/django_errors.log',
            'formatter': 'simple'
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'ERROR',
        },
    },
}

Here is my view using django-rest-framework:

import logging

logger = logging.getLogger(__name__)

class Countries(APIView):
    permission_classes = ()
    authentication_classes = []

    def get(self, request):
        try:
           ... some API process
        except Exception as e:
            import traceback
            print(traceback.format_exc())
            logger.error(traceback.format_exc())
            return JsonResponse({'code': 500, 'message': str(e)}, status=500)

From the console I can see the print() show the correct full stack traceback. But in the logging file, it doesn’t show any traceback.

django_errors.log:

ERROR 2022-12-22 11:35:21,051 "GET /api/countries HTTP/1.1" 500 72
ERROR 2022-12-22 11:35:21,065 "GET /api/countries HTTP/1.1" 500 72

I also tried logger.exception() the same thing happens, file doesn’t log full stack traceback

I tried looking online for solutions and tried them but to no prevail, hope someone can help me figure out why

expected log to show correct traceback for example like console print():

    Traceback (most recent call last):
       File "/app/api/views/countries.py", line 40, in get
       country["currency"] = 
 get_currency_code_from_country_code(country["data"])
       File "/app/utils/django_utils.py", line 470, in 
 get_currency_code_from_country_code
       return currency.alpha_3
       AttributeError: 'NoneType' object has no attribute 'alpha_3

I even tried adding {stack_info} to my formatter, but it just returns None:

ERROR 2022-12-22 11:58:18,921 "GET /api/countries HTTP/1.1" 500 72 None
Asked By: Linh Nguyen

||

Answers:

I misunderstood how Django uses its own named hierarchy. I thought by using django it would apply to all loggers, but it’s not the case because Django default only logs info without stack trace.

For it to work I take a look again at the docs, I need to specify the logger parent name for it to actually get recorded by the logging system.

so I need to have the logger like so to capture the loggers specify in each file:

 'loggers': {
    'app1': { # need to specify app parent folder in loggers
        'handlers': ['file', 'mail_admins'],
        'level': 'ERROR',
    },
    'app2': {
        'handlers': ['file', 'mail_admins'],
        'level': 'ERROR',
    },
    'base.celery': {
        'handlers': ['file', 'mail_admins'],
        'level': 'ERROR',
    },
 },

and for the logger to show stack trace I need to use logger.exception("") it will trigger ERROR level with stack trace

Now my log files and email contain all stack trace infos

Answered By: Linh Nguyen