Proper logging configuration to disable django error emails

Viewed 1107

I just got sentry working in my environment and I tried tweaking my logging to make it stop sending error emails, but it still is and I don't understand why. My logging config is:

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "verbose": {
            "format": '%(levelname)s %(asctime)s (%(pathname)s %(funcName)s): "%(message)s"'
        },
        "simple": {"format": "%(levelname)s %(message)s"},
        "django.server": {
            "()": "django.utils.log.ServerFormatter",
            "format": "[%(server_time)s] %(message)s",
        },
    },
    "handlers": {
        "null": {"level": "DEBUG", "class": "logging.NullHandler",},
        "console": {
            "level": "DEBUG",
            "class": "logging.StreamHandler",
            "formatter": "simple",
        },
        "log_file": {
            "level": "DEBUG",
            "class": "logging.handlers.RotatingFileHandler",
            "filename": "/var/log/courtlistener/django.log",
            "maxBytes": "16777216",  # 16 megabytes
            "formatter": "verbose",
        },
        "django.server": {
            "level": "INFO",
            "class": "logging.StreamHandler",
            "formatter": "django.server",
        },
    },
    "loggers": {
        # Disable SuspiciousOperation.DisallowedHost exception ("Invalid
        # HTTP_HOST" header messages.) This appears to be caused by clients that
        # don't support SNI, and which are browsing to other domains on the
        # server. The most relevant bad client is the googlebot.
        "django.security.DisallowedHost": {
            "handlers": ["null"],
            "propagate": False,
        },
        "django.server": {
            "handlers": ["django.server"],
            "level": "INFO",
            "propagate": False,
        },
        # This is the one that's used practically everywhere in the code.
        "cl": {"handlers": ["log_file"], "level": "INFO", "propagate": True,},
    },
}

Is there a missing piece here? I don't know how that'd possibly send emails. Is there another config variable I should be thinking about?

UPDATE: One thing I've noticed is that I get plaintext error emails now instead of the HTML ones I used to get. This changed when I tweaked the logging config, but I have no idea why and Googling it doesn't seem to reveal anything.

2 Answers

Django setups a default mail_admins handler, which you can't simply replace in the handlers section, so if you want to get rid of it you need to overwrite the handlers in the root logger:

All loggers except django.server propagate logging to their parents, up to the root django logger. The console and mail_admins handlers are attached to the root logger to provide the behavior described above.

LOGGING = {
    'loggers': {
        'django': {
            'handlers': [],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
            'propagate': False,
        },
    },

}

[edit] fixed wrong statement about overwriting the handler class, sadly it doesn't work as expected, seems to be hard-coded in some way (too busy to look it up in the django code base).

Your LOGGING config looks (almost, see the end) fine to me. There are a few other things I can think of.

Perhaps you made the changes but not everywhere, you may have other apps, celery processes, staging deploys etc. running somewhere that you've forgotten about.

Perhaps something else (I'm not sure what...) is configuring this logging handler. If this is the case, you can disable the existing loggers:

LOGGING = {
    "disable_existing_loggers": True,
    ...
}

This isn't a very good idea though, disabling other people's loggers, so as an alternative you can disable it in another way.

The ADMINS setting defines the email addresses to send the errors to, so you can disable it by just setting this to an empty list:

ADMINS = []

This should be relatively safe as sending error emails is the only thing this setting is used for - unless you or a third party app are using it.

You can also be sent emails not of server errors, but of 404 errors. Make sure your MIDDLEWARE does not contain BrokenLinkEmailsMiddleware. There is also a similar setting to ADMINS for this, but it's called MANAGERS:

MANAGERS = []

You should also check the default logging config, to make sure you haven't missed something when creating your own LOGGING dict.

One more thing I've noticed, when plugging your LOGGING config into a project is that the configuration doesn't parse correctly for me, because the value of maxBytes should be an int, not a string. So you could also try changing:

"log_file": {
    "level": "DEBUG",
    "class": "logging.handlers.RotatingFileHandler",
    "filename": "/var/log/courtlistener/django.log",
    "maxBytes": "16777216",  # 16 megabytes
    "formatter": "verbose",
}

to:

"log_file": {
    "level": "DEBUG",
    "class": "logging.handlers.RotatingFileHandler",
    "filename": "/var/log/courtlistener/django.log",
    "maxBytes": 16777216,  # 16 megabytes
    "formatter": "verbose",
}
Related