Search code examples
djangologginggunicorngoogle-cloud-stackdriver

Unable to log to google stackdriver logging django + gunicorn + nGINX?


I've tried the below code for logging in django settings

from google.cloud import logging as google_cloud_logging

log_client = google_cloud_logging.Client()
log_client.setup_logging()

LOGGING = {
    'version': 1,
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
        },
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler'
        },
        'stackdriver_logging': {
            'class': 'google.cloud.logging.handlers.CloudLoggingHandler',
            'client': log_client
        },
    },
    'loggers': {
        'django': {
            'handlers': ['stackdriver_logging'],
            'level': 'INFO',
            'propagate': True,
        },
        'django.request': {
            'handlers': [
                'stackdriver_logging',
                'mail_admins'
            ],
            'level': 'ERROR',
        }
    },
}

gunicorn.conf.py

bind = "127.0.0.1:8000"
workers = 3
loglevel = "debug"
proc_name = "hhh"
daemon = False

I was able write to stackdriver logging with django development server but logging not working when I use gunicorn. But django.request is working.

Problem: logger "django" not being called and showing no errors with gunicorn

Please help.


Solution

  • After trying many ways finally it worked with below configuration

    gcp_utils/stackdriver_logging.py

    import logging
    import traceback
    from django.views.debug import ExceptionReporter
    from google.cloud import error_reporting, logging as google_cloud_logging
    
    
    client = error_reporting.Client()
    log_client = google_cloud_logging.Client()
    log_client.setup_logging()
    
    
    class StackdriverErrorHandler(logging.Handler):
    
        def __init__(self):
            logging.Handler.__init__(self)
    
        def emit(self, record):
            try:
                request = record.request
                if request.user.is_authenticated():
                    user = request.user.email
                else:
                    user = 'Anonymous'
                status_code = getattr(record, 'status_code', None)
                http_context = error_reporting.HTTPContext(
                    method=request.method,
                    url=request.build_absolute_uri(),
                    user_agent=request.META.get('HTTP_USER_AGENT'),
                    referrer=request.META.get('HTTP_REFERER'),
                    response_status_code=status_code,
                    remote_ip=request.META.get('REMOTE_ADDR')
                )
            except Exception as e:
                print e
                http_context = None
    
            if record.exc_info:
                exc_info = record.exc_info
            else:
                exc_info = (None, record.getMessage(), None)
            reporter = ExceptionReporter(request, is_email=True, *exc_info)
            tb_frames = reporter.get_traceback_frames()
            if tb_frames:
                tb = tb_frames[-1]
            else:
                tb = {}
            report_location = {
                'filePath': tb.get('filename'),
                'lineNumber': tb.get('lineno'),
                'functionName': tb.get('function')
            }
            client._send_error_report(
                message=traceback.format_exc(),
                http_context=http_context,
                user=user,
                report_location=report_location
            )
    

    settings.py

    import sys
    from google.cloud import logging as google_cloud_logging
    
    
    log_client = google_cloud_logging.Client()
    
    if not DEBUG:
      LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console': {
                'level': 'INFO',
                'class': 'logging.StreamHandler',
                'stream': sys.stdout,
            },
            'mail_admins': {
                'level': 'ERROR',
                'class': 'django.utils.log.AdminEmailHandler'
            },
            'stackdriver_logging': {
                'class': 'google.cloud.logging.handlers.CloudLoggingHandler',
                'client': log_client
            },
            'stackdriver_error_reporting': {
                'level': 'ERROR',
                'class': 'gcp_utils.stackdriver_logging.StackdriverErrorHandler',
            }
        },
        'loggers': {
            'django': {
                'handlers': ['console', 'stackdriver_logging'],
                'level': 'DEBUG',
                'propagate': True,
            },
            'django.request': {
                'handlers': [
                    'stackdriver_logging',
                    'mail_admins'
                ],
                'level': 'ERROR',
            }
        },
    }
    

    gunicorn.conf.py

    from google.cloud import logging as google_cloud_logging
    
    log_client = google_cloud_logging.Client()
    log_client.setup_logging()
    
    bind = "127.0.0.1:8000"
    workers = 3
    loglevel = "debug"
    proc_name = "django_app"
    daemon = False
    pythonpath = "/path/to/python/"
    timeout = 90
    accesslog = '/home/user/logs/debug.log'
    logconfig_dict = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'mail_admins': {
                'level': 'ERROR',
                'class': 'django.utils.log.AdminEmailHandler'
            },
            'stackdriver_logging': {
                'class': 'google.cloud.logging.handlers.CloudLoggingHandler',
                'client': log_client
            },
        },
        'loggers': {
            'gunicorn.access': {
                'handlers': ['stackdriver_logging'],
                'level': 'INFO',
                'propagate': True,
            },
            'django.request': {
                'handlers': [
                    'stackdriver_logging',
                    'mail_admins'
                ],
                'level': 'ERROR',
            }
        },
    }
    

    running gunicorn process

    $ gunicorn -c gunicorn.conf.py wsgi:application
    

    We must define the logconfig_dict in-order to make it work with google stackdriver logging.