zerosleeps

Since 2010

Time zone abbreviations suck

Yesterday morning a huge chunk of the east coast of Australia changed from AEDT (Australian Eastern Daylight Time) to AEST (Australian Eastern Standard Time) thanks to DST (Daylight Saving Time) ending.

We went from %DT when %ST was in effect, to %ST where %ST is not in effect.

These names and acronyms are crap. The whole concept of daylight saving time is crap. We, like every other household in the country, have a few things with clocks that need to be manually changed. It takes me 5 minutes.

5 minutes × twice a year × 10 million Australian households = 100,000,000 minutes = 69,444 human days. Every year.

What exactly does it save?

Log database queries in Django

While I’m on the topic of logging in Django, it makes me sad and a little bit grumpy that when you take Django out of the box, it doesn’t default to showing you what it’s doing with your database.

Here’s a LOGGING configuration that takes care of that, and sends everything from django.db.backends to a file in the project’s root directory during development:

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "handlers": {
        "db_backends_file": {
            "class": "logging.FileHandler",
            "filename": BASE_DIR / "db_backends.log"
        }
    },
    "loggers": {
        "django.db.backends": {
            "level": "DEBUG",
            "handlers": ["db_backends_file"]
        }
    }
}

It’s important to note that django.db.backends only generates output when the DEBUG setting is True.

Log HTTP 5xx responses in Django

By default, in a production environment where setting DEBUG is false, Django sends log messages with ERROR or CRITICAL levels to AdminEmailHandler. This includes HTTP 5xx responses, which are handled by the django.request logger.

If you don’t have outbound email configured you lose these errors.

Python’s logging.StreamHandler defaults to sending output to stderr, and most of the time my Django applications are managed by systemd service units which default to passing stdout and stderr to systemd’s journal.

Put all of that knowledge together and here’s the delightfully simple LOGGING configuration I usually add to my production settings:

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "handlers": {
        "stderr": {
            "class": "logging.StreamHandler"
        }
    },
    "loggers": {
        "django.request": {
            "level": "ERROR",
            "handlers": ["stderr"]
        }
    }
}

I can then fumble about with journald as required.