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
Metadata
Release files for JSON-log-formatter 1.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| json_log_formatter-1.2.1.tar.gz | 5.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| json_log_formatter-1.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.5 kB
Release files / json_log_formatter-1.2.1.tar.gz
| Download URL | json_log_formatter-1.2.1.tar.gz |
|---|---|
| Size | 5.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1d4fd14495ad7e694aa576259ba81acaa69e6945d9d780f32ed25373d7d5ae93
|
|
BLAKE2b-256 checksum How to use checksums |
dfebcaf193a5c77e3d9c1604dfa86fe87d9096e014303497134f23f6196a7685
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.3
|
Release files / json_log_formatter-1.2.1-py3-none-any.whl
| Download URL | json_log_formatter-1.2.1-py3-none-any.whl |
|---|---|
| Size | 6.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1e40432466c911ba2d106a302314b1c3b0019de44c762bef94e8f23138a415a7
|
|
BLAKE2b-256 checksum How to use checksums |
c5a1b11bca303b81d07d5a686254ecbee35771d6fd050bdf0524a0003aeca306
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.3
|