Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging in Django on Heroku not appearing

I have created an app on Heroku and I push my Django app to it.

I monitor the logs using heroku logs --tail to see them in real time.

Then, in my settings.py, I have the following:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': ('%(asctime)s [%(process)d] [%(levelname)s] ' +
                       'pathname=%(pathname)s lineno=%(lineno)s ' +
                       'funcname=%(funcName)s %(message)s'),
            'datefmt': '%Y-%m-%d %H:%M:%S'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        }
    },
    'handlers': {
        'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
        },
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
            'stream': sys.stdout,
        }
    },
    'loggers': {
        'MYAPP': {
            'handlers': ['console'],
            'level': 'INFO',
        }
    }
}

Then, when I want to log something, I use the following:

import logging
import sys 

logger = logging.getLogger('MYAPP')
logger.info('My message here...')
sys.stdout.flush()

but it isn't reflected in my logs.

My Procfile:

web: gunicorn myapp.wsgi --log-file=-

EDIT: Curiously, I can actually change "myapp" to "django" when I define my logging config and also logging.getLogger('django') and that allows me to see anything using print in my logs, but nothing from the formatted logger I've defined.

I even have PYTHONUNBUFFERED=true and DEBUG=1 set for my staging environment, but I don't see any of the logs that I see when using my local version with foreman start web.

What is causing this and how do I see my logs live in Heroku?

like image 928
lollercoaster Avatar asked Aug 26 '15 18:08

lollercoaster


2 Answers

Your Procfile is probably at fault here:

If you want to have gunicorn log to stdout you have to use the --logfile=- command line option (you are missing the = !) according to this answer.

So your entire Procfile should look like this:

web: gunicorn myapp.wsgi --log-file=-

EDIT:

Since print statements are working for you, but logging is not, your logging setup is probably at fault. Make sure that you set up logging during the startup of your app (where are you calling dictConfig in your code?):

import logging
logging.config.dictConfig(LOGGING)
logger = logging.getLogger('MYAPP')
logger.info("Just testing")
like image 115
rkrzr Avatar answered Oct 18 '22 14:10

rkrzr


Your Procfile and LOGGING configuration looks fine. Django configures the logger just before the apps are imported, so if you try to log even before than (for. e.g. from settings.py file), it will not work.

EDIT:

LOGGING config:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': ('%(asctime)s [%(process)d] [%(levelname)s] '
                       'pathname=%(pathname)s lineno=%(lineno)s '
                       'funcname=%(funcName)s %(message)s'),
            'datefmt': '%Y-%m-%d %H:%M:%S'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        }
    },
    'handlers': {
    'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
    },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose'
        }
    },
    'loggers': {
    'ex_logger': {
            'handlers': ['console', ],
            'level': 'INFO',
        }
    }
}

adding following to settings.py won't log:

import logging
logger = logging.getLogger('ex_logger')
logger.info("core.settings logger")  # won't work 

adding to views.py should log:

from django.http import HttpResponse
import logging

logger = logging.getLogger('ex_logger')
logger.info("core.views logger")  # should work                                                                                                         

def url_please(request):
    logger.info("path: %s" % request.path)  # should work                                                                                               
    return HttpResponse(request.path)
like image 42
Aman Avatar answered Oct 18 '22 15:10

Aman