Json Formatter for the standard python logger

Related tags

Loggingpythonlogging
Overview

Build Status License Version

Overview

This library is provided to allow standard python logging to output log data as json objects. With JSON we can make our logs more readable by machines and we can stop writing custom parsers for syslog type records.

News

Hi, I see this package is quiet alive and I am sorry for ignoring it so long. I will be stepping up my maintenance of this package so please allow me a week to get things back in order (and most likely a new minor version) and i'll post and update here once I am caught up.

Installing

Pip:

pip install python-json-logger

Pypi:

https://pypi.python.org/pypi/python-json-logger

Manual:

python setup.py install

Usage

Integrating with Python's logging framework

Json outputs are provided by the JsonFormatter logging formatter. You can add the custom formatter like below:

Please note: version 0.1.0 has changed the import structure, please update to the following example for proper importing

    import logging
    from pythonjsonlogger import jsonlogger

    logger = logging.getLogger()

    logHandler = logging.StreamHandler()
    formatter = jsonlogger.JsonFormatter()
    logHandler.setFormatter(formatter)
    logger.addHandler(logHandler)

Customizing fields

The fmt parser can also be overidden if you want to have required fields that differ from the default of just message.

These two invocations are equivalent:

class CustomJsonFormatter(jsonlogger.JsonFormatter):
    def parse(self):
        return self._fmt.split(';')

formatter = CustomJsonFormatter('one;two')

# is equivalent to:

formatter = jsonlogger.JsonFormatter('%(one)s %(two)s')

You can also add extra fields to your json output by specifying a dict in place of message, as well as by specifying an extra={} argument.

Contents of these dictionaries will be added at the root level of the entry and may override basic fields.

You can also use the add_fields method to add to or generally normalize the set of default set of fields, it is called for every log event. For example, to unify default fields with those provided by structlog you could do something like this:

class CustomJsonFormatter(jsonlogger.JsonFormatter):
    def add_fields(self, log_record, record, message_dict):
        super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
        if not log_record.get('timestamp'):
            # this doesn't use record.created, so it is slightly off
            now = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')
            log_record['timestamp'] = now
        if log_record.get('level'):
            log_record['level'] = log_record['level'].upper()
        else:
            log_record['level'] = record.levelname

formatter = CustomJsonFormatter('%(timestamp)s %(level)s %(name)s %(message)s')

Items added to the log record will be included in every log message, no matter what the format requires.

Adding custom object serialization

For custom handling of object serialization you can specify default json object translator or provide a custom encoder

def json_translate(obj):
    if isinstance(obj, MyClass):
        return {"special": obj.special}

formatter = jsonlogger.JsonFormatter(json_default=json_translate,
                                     json_encoder=json.JSONEncoder)
logHandler.setFormatter(formatter)

logger.info({"special": "value", "run": 12})
logger.info("classic message", extra={"special": "value", "run": 12})

Using a Config File

To use the module with a config file using the fileConfig function, use the class pythonjsonlogger.jsonlogger.JsonFormatter. Here is a sample config file.

[loggers]
keys = root,custom

[logger_root]
handlers =

[logger_custom]
level = INFO
handlers = custom
qualname = custom

[handlers]
keys = custom

[handler_custom]
class = StreamHandler
level = INFO
formatter = json
args = (sys.stdout,)

[formatters]
keys = json

[formatter_json]
format = %(message)s
class = pythonjsonlogger.jsonlogger.JsonFormatter

Example Output

Sample JSON with a full formatter (basically the log message from the unit test). Every log message will appear on 1 line like a typical logger.

{
    "threadName": "MainThread",
    "name": "root",
    "thread": 140735202359648,
    "created": 1336281068.506248,
    "process": 41937,
    "processName": "MainProcess",
    "relativeCreated": 9.100914001464844,
    "module": "tests",
    "funcName": "testFormatKeys",
    "levelno": 20,
    "msecs": 506.24799728393555,
    "pathname": "tests/tests.py",
    "lineno": 60,
    "asctime": ["12-05-05 22:11:08,506248"],
    "message": "testing logging format",
    "filename": "tests.py",
    "levelname": "INFO",
    "special": "value",
    "run": 12
}

External Examples

Comments
  • Add PEP 561 marker

    Add PEP 561 marker

    • Add a PEP 561 marker
    • Add basic mypy configuration
    • Run mypy from tox
    • Minor code modifications to make mypy happy

    This is intended to be a relatively minimal change just to enable basic type checking. Future changes should fill out the type annotations more and enable stricter mypy configuration (set all mypy options to 'true').

    This change is a small step towards https://github.com/madzak/python-json-logger/issues/118

    Note that the marker is intentionally not shipped via setup.py -- the annotations need more cleanup first (turn on a few key mypy config options, e.g. no-untyped-defs).

    opened by bringhurst 11
  • Jsonformatter formats the newline character

    Jsonformatter formats the newline character

    Jsonformatter will not format the newline character that is inside the message fields too.

    Ex: without this commit { "rid": "6c0320a4-ed87-4d0a-a668-b7ceef94eecf", "asctime": "2021-03-23 14:13:50,151", "filename": "", "module": "", "funcName": "", "lineno": 16, "levelname": "INFO", "message": "log line 1\nlog line 2" }

    After this commit { "rid": "6c0320a4-ed87-4d0a-a668-b7ceef94eecf", "asctime": "2021-03-23 14:13:50,151", "filename": "", "module": "", "funcName": "", "lineno": 16, "levelname": "INFO", "message": "log line 1 log line 2" }

    opened by anandtripathi5 7
  • Python 2.6 test fix and travis ci

    Python 2.6 test fix and travis ci

    This encompasses #39 and #40 with the "addition" of removing Python 2.6 from the list of allowed failures. Merging this in will close those too.

    opened by nelsonjchen 7
  • No StackTrace info on the log

    No StackTrace info on the log

    Hello.

    I'm trying to use this module to format django's log. The problem I'm having is that the full message of the stack trace when there's an exception, including the actual Exception name and message, is not showing up in my log files.

    Any idea for how I might fix this?

    opened by hitokiri82 5
  • Drop Python 3.5 support and pypy 3.6 support

    Drop Python 3.5 support and pypy 3.6 support

    To allow for typing annotations and enforcement of typing annotations, we need to:

    • Drop Python 3.5 support since it doesn't support the syntax
    • Drop pypy 3.6 support since it doesn't support mypy

    See https://github.com/madzak/python-json-logger/pull/129#issuecomment-1030708627 for additional background.

    opened by bringhurst 4
  • Update examples and tests for Python 3.8 compatibility

    Update examples and tests for Python 3.8 compatibility

    See #86 See #74

    This PR fixes up a couple of small issues encountered when upgrading to Python 3.8:

    • updates examples in README.md to be compatible with Python 3.8
    • updates test code to match the formatting example provided in the readme
    • adds Python 3.8 testing to Travis and tox
    • marks the package as Python 3.8 compatible in setup.py
    opened by tommilligan 4
  • Invalid format '(levelname) (name) (message)' for '%' style

    Invalid format '(levelname) (name) (message)' for '%' style

    It seems like with Python 3.8 the format string needs to be specified differently.

    I have this small test setup:

    This is test.py:

    import os
    import logging
    from pythonjsonlogger import jsonlogger
    
    logger = logging.getLogger()
    logHandler = logging.StreamHandler()
    formatter = jsonlogger.JsonFormatter("(levelname) (name) (message)")
    logHandler.setFormatter(formatter)
    logger.handlers = [logHandler]
    logger.setLevel(logging.INFO)
    
    logger.info("Hello world")
    

    and this Dockerfile:

    FROM python:3.7
    RUN pip install python-json-logger
    COPY test.py .
    CMD ["python", "test.py"]
    

    If I run docker build -t test . && docker run -it test it works as expected, the output is {"levelname": "INFO", "name": "root", "message": "Hello world"}.

    Under Python 3.8 this results in ValueError: Invalid format '(levelname) (name) (message)' for '%' style. I have to change the format line to read formatter = jsonlogger.JsonFormatter("%(levelname) %(name) %(message)"). I'm not sure if this is expected, but it might (at least) warrant an update of the documentation.

    opened by stchris 4
  • How to append logs in the current dict ?

    How to append logs in the current dict ?

    Thanks for the nice library ! I tried your example which is given in the readme section. It's working fine.

    My problem is I am using logging.FileHandler('reuben.json') to write the dump in a file. What happening is every time a log message is entering as a separate entry instead of an item of a list or dictionary.

    Is it possible to create the json in the given below format :

    log.error({"host": "host1", "message": "Failed to install"})
    log.info({"host": "host2", "message": "successfully installed"})
    

    json :

    [{"host": "host1", "message": "Failed to install"}, {"host": "host2", "message": "successfully installed"}]
    
    opened by reubenur-rahman 4
  • Allow editing of log_record in two possible ways

    Allow editing of log_record in two possible ways

    One more thing related to https://github.com/madzak/python-json-logger/issues/16: I just noticed that while process_log_record returns the log_record, that returned value isn't actually stored in a variable. By making the change in this commit, the user can use two approaches in process_log_record in a subclass to modify the log_record:

    • modify the given log_record in process_log_record (in-place) and return that,
    • or, use the given log_record to compute an entirely new dictionary instance and return that instead.
    opened by svisser 4
  • Release 2.0

    Release 2.0

    Hello @madzak.

    The readme says:

    NOTICE: Python2.7 is only supported up to v0.1.11. The next release, v2.0, will support Python3 only

    Python 2 is unsupported since 1st Jan 2020. Is there any roadmap for 2.0 or could you just make a new release supporting only Python3?

    Thanks!

    opened by PabloCastellano 3
  • Fix/setuptools

    Fix/setuptools

    opened by orsinium 3
  • 2.0.4: pytest is not able to find units

    2.0.4: pytest is not able to find units

    + /usr/bin/pytest -ra
    =========================================================================== test session starts ============================================================================
    platform linux -- Python 3.8.15, pytest-7.2.0, pluggy-1.0.0
    rootdir: /home/tkloczko/rpmbuild/BUILD/python-json-logger-2.0.4
    collected 0 items
    
    ========================================================================== no tests ran in 0.01s ===========================================================================
    

    However

    + /usr/bin/pytest -ra tests/tests.py
    =========================================================================== test session starts ============================================================================
    platform linux -- Python 3.8.15, pytest-7.2.0, pluggy-1.0.0
    rootdir: /home/tkloczko/rpmbuild/BUILD/python-json-logger-2.0.4
    collected 16 items
    
    tests/tests.py ................                                                                                                                                      [100%]
    
    ============================================================================ 16 passed in 0.03s ============================================================================
    

    pytest automacically scans tests_*.py files so tests/tests.py should be renamed to fix this.

    opened by kloczek 0
  • Change format of message to Message

    Change format of message to Message

    Hello, this isn't an issue, but wanted to know if there was an easier way to call Message instead of message or do we have to go the CustomJsonFormatter class route? For example, how to change the message here

    formatter = jsonlogger.JsonFormatter("%(asctime)s %(filename)s %(module)s %(funcName)s %(lineno)s %(message)s")
    

    to Message, because changing it directly in this line of code wouldn't work?

    Thank you.

    opened by sharathsridhar 0
  • dict as object of message

    dict as object of message

    With this patch we can do something like this:

        formatter = jsonlogger.JsonFormatter(dict_as_object=True)
        # ...
        my_dict = {
            "result": 0,
            "text": "some text",
        }
        logger.info("Just text")
        logger.info(my_dict)
    

    Output:

    {
      "message": "Just text"
    }
    {
      "message": {
        "result": 0,
        "text": "some text",
      }
    }
    
    opened by DmitruMoth 0
  • Drop support of old python versions

    Drop support of old python versions

    While browsing the code, I realized that some code is written with python2 in mind (especially the test). python2 is not supported since January 2020 (https://www.python.org/doc/sunset-python-2/).

    I'd also suggest changing the packaging of this library to drop the support of python3.5 (EOL 2020-09-13) and python3.6 (EOL 2021-12-23) (source: https://endoflife.date/python)

    Some guidance can be found here: https://packaging.python.org/en/latest/guides/dropping-older-python-versions/

    opened by lopagela 1
  • How to include all available fields in a log record + some custom fields?

    How to include all available fields in a log record + some custom fields?

    Currently, I am writing a custom formatter to include all fields with the intention of adding some of my own later.

    I have two sets of questions

    Q1 : Is this the correct way? i.e. subclass the formatter and than copying field by field over ? or am I going about it the wrong way ?

    Ultimately, I will want to include most of the default fields plus I am going to add some custom in-house fields.

    class CustomJsonFormatter(jsonlogger.JsonFormatter):
        
        def add_fields(self, log_record, record, message_dict):
            import datetime
            super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
    
            log_record['args'] = record.args
            # log_record['asctime'] = record.asctime
            log_record['created'] = record.created
            log_record['exc_info'] = record.exc_info
            log_record['exc_text'] = record.exc_text
            log_record['filename'] = record.filename
            log_record['funcName'] = record.funcName
            log_record['levelname'] = record.levelname
            log_record['levelno'] = record.levelno
            log_record['lineno'] = record.lineno
            log_record['module'] = record.module
            log_record['msecs'] = record.msecs
            log_record['message'] = record.message
            log_record['msg'] = record.msg
            log_record['name'] = record.name
            log_record['pathname'] = record.pathname
            log_record['process'] = record.process
            log_record['processName'] = record.processName
            log_record['relativeCreated'] = record.relativeCreated
            log_record['stack_info'] = record.stack_info
            log_record['thread'] = record.thread
            log_record['threadName'] = record.threadName
    

    Q2 : What if I want most but not all the default fields, is there some pythonic way to do that ?

    opened by nyue 0
Releases(v2.0.4)
  • v2.0.4(Jul 11, 2022)

  • v2.0.3(Jul 8, 2022)

    Added

    • Add PEP 561 marker/basic mypy configuration. - @bringhurst
    • Workaround logging.LogRecord.msg type of string. - @bringhurst

    Changed

    • Changed a link archive of the reference page in case it's down. - @ahonnecke
    • Removed unnecessary try-except around OrderedDict usage - @sozofaan
    • Update documentation link to json module + use https - @deronnax
    • Dropped 3.5 support. - @bringhurst
    Source code(tar.gz)
    Source code(zip)
  • v2.0.2(Jul 27, 2021)

    Added

    • Officially supporting 3.9 - @felixonmars.
    • You can now add static fields to log objects - @cosimomeli.

    Changed

    • Dropped 3.4 support.
    • Dropped Travis CI for Github Actions.
    • Wheel should build for python 3 instead of just 3.4 now.
    Source code(tar.gz)
    Source code(zip)
  • v2.0.1(Oct 12, 2020)

  • v0.1.5(Jun 12, 2016)

Owner
Zakaria Zajac
Zakaria Zajac
Pretty-print tabular data in Python, a library and a command-line utility. Repository migrated from bitbucket.org/astanin/python-tabulate.

python-tabulate Pretty-print tabular data in Python, a library and a command-line utility. The main use cases of the library are: printing small table

Sergey Astanin 1.5k Jan 06, 2023
🐑 Syslog Simulator hazır veya kullanıcıların eklediği logları belirtilen adreslere ve port'a seçilen döngüde syslog ile gönderilmesini sağlayan araçtır. | 🇹🇷

syslogsimulator hazır ürün loglarını SIEM veya log toplayıcısına istediğiniz portta belirli sürelerde göndermeyi sağlayan küçük bir araçtır.

Enes Aydın 3 Sep 28, 2021
👻 - Simple Keylloger with Socket

Keyllogs 👻 - Simple Keylloger with Socket Keyllogs 🎲 - Run Keyllogs

Bidouffe 3 Mar 28, 2022
dash-manufacture-spc-dashboard is a dashboard for monitoring read-time process quality along manufacture production line

In our solution based on plotly, dash and influxdb, the user will firstly generate the specifications for different robots, and then a wide range of interactive visualizations for different machines

Dequn Teng 1 Feb 13, 2022
Log4j alternative for Python

Log4p Log4p is the most secure logging library ever created in this and all other universes. Usage: import log4p log4p.log('"Wow, this library is sec

Isaak Uchakaev 15 Dec 16, 2022
Lazy Profiler is a simple utility to collect CPU, GPU, RAM and GPU Memory stats while the program is running.

lazyprofiler Lazy Profiler is a simple utility to collect CPU, GPU, RAM and GPU Memory stats while the program is running. Installation Use the packag

Shankar Rao Pandala 28 Dec 09, 2022
Yaml - Loggers are like print() statements

Upgrade your print statements Loggers are like print() statements except they also include loads of other metadata: timestamp msg (same as print!) arg

isaac peterson 38 Jul 20, 2022
A very basic esp32-based logic analyzer capable of sampling digital signals at up to ~3.2MHz.

A very basic esp32-based logic analyzer capable of sampling digital signals at up to ~3.2MHz.

Davide Della Giustina 43 Dec 27, 2022
Soda SQL Data testing, monitoring and profiling for SQL accessible data.

Soda SQL Data testing, monitoring and profiling for SQL accessible data. What does Soda SQL do? Soda SQL allows you to Stop your pipeline when bad dat

Soda Data Monitoring 51 Jan 01, 2023
Logging system for the TPC software.

tpc_logger Logging system for the TPC software. The TPC Logger class provides a singleton for logging information within C++ code or in the python API

UC Davis Machine Learning 1 Jan 10, 2022
Monitoring plugin to check disk io with Icinga, Nagios and other compatible monitoring solutions

check_disk_io - Monitor disk io This is a monitoring plugin for Icinga, Nagios and other compatible monitoring solutions to check the disk io. It uses

DinoTools 3 Nov 15, 2022
A simple package that allows you to save inputs & outputs as .log files

wolf_dot_log A simple package that allows you to save inputs & outputs as .log files pip install wolf_dot_log pip3 install wolf_dot_log |Instructions|

Alpwuf 1 Nov 16, 2021
This is a DemoCode for parsing through large log files and triggering an email whenever there's an error.

LogFileParserDemoCode This is a DemoCode for parsing through large log files and triggering an email whenever there's an error. There are a total of f

2 Jan 06, 2022
Greppin' Logs: Leveling Up Log Analysis

This repo contains sample code and example datasets from Jon Stewart and Noah Rubin's presentation at the 2021 SANS DFIR Summit titled Greppin' Logs. The talk was centered around the idea that Forens

Stroz Friedberg 20 Sep 14, 2022
A simple, transparent, open-source key logger, written in Python, for tracking your own key-usage statistics.

A simple, transparent, open-source key logger, written in Python, for tracking your own key-usage statistics, originally intended for keyboard layout optimization.

Ga68 56 Jan 03, 2023
Key Logger - Key Logger using Python

Key_Logger Key Logger using Python This is the basic Keylogger that i have made

Mudit Sinha 2 Jan 15, 2022
changedetection.io - The best and simplest self-hosted website change detection monitoring service

changedetection.io - The best and simplest self-hosted website change detection monitoring service. An alternative to Visualping, Watchtower etc. Designed for simplicity - the main goal is to simply

7.3k Jan 01, 2023
Robust and effective logging for Python 2 and 3.

Robust and effective logging for Python 2 and 3.

Chris Hager 1k Jan 04, 2023
A new kind of Progress Bar, with real time throughput, eta and very cool animations!

alive-progress :) A new kind of Progress Bar, with real-time throughput, eta and very cool animations! Ever found yourself in a remote ssh session, do

Rogério Sampaio de Almeida 4k Dec 30, 2022
Display tabular data in a visually appealing ASCII table format

PrettyTable Installation Install via pip: python -m pip install -U prettytable Install latest development version: python -m pip install -U git+https

Jazzband 924 Jan 05, 2023