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 | Provenance | Actions |
|---|---|---|---|---|
| json_log_formatter-1.2.1.tar.gz | 5.9 kB | Without provenance | Details for json_log_formatter-1.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| json_log_formatter-1.2.1-py3-none-any.whl | Python 3 | none | any | Details for json_log_formatter-1.2.1-py3-none-any.whl |
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
|
Security for JSON-log-formatter 1.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.