Skip to main content

JSON log formatter

Project description

The library helps you to store logs in JSON format. Why is it important? Well, it facilitates integration with Logstash.

Usage example:

import logging

import json_log_formatter

formatter = json_log_formatter.JSONFormatter()

json_handler = logging.FileHandler(filename='/var/log/my-log.json')
json_handler.setFormatter(formatter)

logger = logging.getLogger('my_json')
logger.addHandler(json_handler)
logger.setLevel(logging.INFO)

logger.info('Sign up', extra={'referral_code': '52d6ce'})

try:
    raise ValueError('something wrong')
except ValueError:
    logger.error('Request failed', exc_info=True)

The log file will contain the following log record (inline).

{
    "message": "Sign up",
    "time": "2015-09-01T06:06:26.524448+00:00",
    "referral_code": "52d6ce"
}
{
    "message": "Request failed",
    "time": "2015-09-01T06:06:26.524449+00:00",
    "exc_info": "Traceback (most recent call last): ..."
}

If you use a log collection and analysis system, you might need to include the built-in log record attributes with VerboseJSONFormatter.

json_handler.setFormatter(json_log_formatter.VerboseJSONFormatter())
logger.error('An error has occured')
{
    "filename": "tests.py",
    "funcName": "test_file_name_is_testspy",
    "levelname": "ERROR",
    "lineno": 276,
    "module": "tests",
    "name": "my_json",
    "pathname": "/Users/bob/json-log-formatter/tests.py",
    "process": 3081,
    "processName": "MainProcess",
    "stack_info": null,
    "thread": 4664270272,
    "threadName": "MainThread",
    "message": "An error has occured",
    "time": "2021-07-04T21:05:42.767726+00:00"
}

If you need to flatten complex objects as strings, use FlatJSONFormatter.

json_handler.setFormatter(json_log_formatter.FlatJSONFormatter())
logger.error('An error has occured')

logger.info('Sign up', extra={'request': WSGIRequest({
    'PATH_INFO': 'bogus',
    'REQUEST_METHOD': 'bogus',
    'CONTENT_TYPE': 'text/html; charset=utf8',
    'wsgi.input': BytesIO(b''),
})})
{
    "message": "Sign up",
    "time": "2024-10-01T00:59:29.332888+00:00",
    "request": "<WSGIRequest: BOGUS '/bogus'>"
}

JSON libraries

You can use ujson or simplejson instead of built-in json library.

import json_log_formatter
import ujson

formatter = json_log_formatter.JSONFormatter()
formatter.json_lib = ujson

Django integration

Here is an example of how the JSON formatter can be used with Django.

LOGGING['formatters']['json'] = {
    '()': 'json_log_formatter.JSONFormatter',
}
LOGGING['handlers']['json_file'] = {
    'level': 'INFO',
    'class': 'logging.FileHandler',
    'filename': '/var/log/my-log.json',
    'formatter': 'json',
}
LOGGING['loggers']['my_json'] = {
    'handlers': ['json_file'],
    'level': 'INFO',
}

Let’s try to log something.

import logging

logger = logging.getLogger('my_json')

logger.info('Sign up', extra={'referral_code': '52d6ce'})

Custom formatter

You will likely need a custom log formatter. For instance, you want to log a user ID, an IP address and time as django.utils.timezone.now(). To do so you should override JSONFormatter.json_record().

class CustomisedJSONFormatter(json_log_formatter.JSONFormatter):
    def json_record(self, message: str, extra: dict, record: logging.LogRecord) -> dict:
        extra['message'] = message
        extra['user_id'] = current_user_id()
        extra['ip'] = current_ip()

        # Include builtins
        extra['level'] = record.levelname
        extra['name'] = record.name

        if 'time' not in extra:
            extra['time'] = django.utils.timezone.now()

        if record.exc_info:
            extra['exc_info'] = self.formatException(record.exc_info)

        return extra

Let’s say you want datetime to be serialized as a timestamp. Override mutate_json_record to convert it.

class CustomisedJSONFormatter(json_log_formatter.JSONFormatter):
    def mutate_json_record(self, json_record):
        for attr_name, attr in json_record.items():
            if isinstance(attr, datetime):
                json_record[attr_name] = attr.timestamp()

        return json_record

Tests

$ pip install -r requirements.txt
$ tox

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

json_log_formatter-1.2.1.tar.gz (5.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

json_log_formatter-1.2.1-py3-none-any.whl (6.6 kB view details)

Uploaded Python 3

File details

Details for the file json_log_formatter-1.2.1.tar.gz.

File metadata

  • Download URL: json_log_formatter-1.2.1.tar.gz
  • Upload date:
  • Size: 5.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for json_log_formatter-1.2.1.tar.gz
Algorithm Hash digest
SHA256 1d4fd14495ad7e694aa576259ba81acaa69e6945d9d780f32ed25373d7d5ae93
MD5 40a71b04f652d0c7ac500f9ddc97bc6b
BLAKE2b-256 dfebcaf193a5c77e3d9c1604dfa86fe87d9096e014303497134f23f6196a7685

See more details on using hashes here.

File details

Details for the file json_log_formatter-1.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for json_log_formatter-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1e40432466c911ba2d106a302314b1c3b0019de44c762bef94e8f23138a415a7
MD5 32135fc1330fe93a81b5fc8ebfb375b4
BLAKE2b-256 c5a1b11bca303b81d07d5a686254ecbee35771d6fd050bdf0524a0003aeca306

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page