Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-python-json-logger for openSUSE:Factory checked in at 2022-10-08 01:25:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-python-json-logger (Old) and /work/SRC/openSUSE:Factory/.python-python-json-logger.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-python-json-logger" Sat Oct 8 01:25:28 2022 rev:7 rq:1008710 version:2.0.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-python-json-logger/python-python-json-logger.changes 2021-11-07 00:19:32.860553236 +0100 +++ /work/SRC/openSUSE:Factory/.python-python-json-logger.new.2275/python-python-json-logger.changes 2022-10-08 01:25:49.066311229 +0200 @@ -1,0 +2,17 @@ +Thu Oct 6 22:41:33 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com> + +- Update to 2.0.4 - 2022-07-11 + Changed + Fix too strict regex for percentage style logging - @aberres + +- Update to 2.0.3 - 2022-07-08 + 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 + +------------------------------------------------------------------- Old: ---- python-json-logger-2.0.2.tar.gz New: ---- python-json-logger-2.0.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-python-json-logger.spec ++++++ --- /var/tmp/diff_new_pack.0NIsYO/_old 2022-10-08 01:25:50.334314137 +0200 +++ /var/tmp/diff_new_pack.0NIsYO/_new 2022-10-08 01:25:50.338314146 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-python-json-logger # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-python-json-logger -Version: 2.0.2 +Version: 2.0.4 Release: 0 Summary: A python library adding a json log formatter License: BSD-2-Clause ++++++ python-json-logger-2.0.2.tar.gz -> python-json-logger-2.0.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-json-logger-2.0.2/PKG-INFO new/python-json-logger-2.0.4/PKG-INFO --- old/python-json-logger-2.0.2/PKG-INFO 2021-07-28 01:09:32.142751200 +0200 +++ new/python-json-logger-2.0.4/PKG-INFO 2022-07-11 16:08:03.423041600 +0200 @@ -1,186 +1,13 @@ Metadata-Version: 2.1 Name: python-json-logger -Version: 2.0.2 +Version: 2.0.4 Summary: A python library adding a json log formatter Home-page: http://github.com/madzak/python-json-logger Author: Zakaria Zajac Author-email: z...@madzak.com License: BSD -Description:  - [](https://pypi.python.org/pypi/python-json-logger/) - [](https://pypi.python.org/pypi/python-json-logger/) - - 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** - - ```python - 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: - - ```python - 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](http://www.structlog.org/) you could do something like this: - - ```python - 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 - - ```python - 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](https://docs.python.org/3/library/logging.config.html#logging.config.fileConfig), use the class `pythonjsonlogger.jsonlogger.JsonFormatter`. Here is a sample config file. - - ```ini - [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. - - ```json - { - "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 - ================= - - - [Wesley Tanaka - Structured log files in Python using python-json-logger](https://wtanaka.com/node/8201) - Platform: UNKNOWN -Classifier: Development Status :: 3 - Alpha +Classifier: Development Status :: 6 - Mature Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent @@ -195,3 +22,181 @@ Classifier: Topic :: System :: Logging Requires-Python: >=3.5 Description-Content-Type: text/markdown +License-File: LICENSE + + +[](https://pypi.python.org/pypi/python-json-logger/) +[](https://pypi.python.org/pypi/python-json-logger/) + +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** + +```python + 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: + +```python +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](http://www.structlog.org/) you could do something like this: + +```python +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 + +```python +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](https://docs.python.org/3/library/logging.config.html#logging.config.fileConfig), use the class `pythonjsonlogger.jsonlogger.JsonFormatter`. Here is a sample config file. + +```ini +[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. + +```json +{ + "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 +================= + +- [Wesley Tanaka - Structured log files in Python using python-json-logger](https://wtanaka.com/node/8201) + +- [Archive](https://web.archive.org/web/20201130054012/https://wtanaka.com/node/8201) + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-json-logger-2.0.2/README.md new/python-json-logger-2.0.4/README.md --- old/python-json-logger-2.0.2/README.md 2021-07-28 01:09:19.000000000 +0200 +++ new/python-json-logger-2.0.4/README.md 2022-07-11 16:07:55.000000000 +0200 @@ -170,3 +170,5 @@ ================= - [Wesley Tanaka - Structured log files in Python using python-json-logger](https://wtanaka.com/node/8201) + +- [Archive](https://web.archive.org/web/20201130054012/https://wtanaka.com/node/8201) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-json-logger-2.0.2/setup.cfg new/python-json-logger-2.0.4/setup.cfg --- old/python-json-logger-2.0.2/setup.cfg 2021-07-28 01:09:32.142751200 +0200 +++ new/python-json-logger-2.0.4/setup.cfg 2022-07-11 16:08:03.423041600 +0200 @@ -1,6 +1,36 @@ [bdist_wheel] python-tag = py3 +[mypy] +mypy_path = src +namespace_packages = true +disallow_any_unimported = true +disallow_any_expr = false +disallow_any_decorated = true +disallow_any_explicit = false +disallow_any_generics = false +disallow_subclassing_any = true +disallow_untyped_calls = false +disallow_untyped_defs = false +disallow_incomplete_defs = true +check_untyped_defs = true +disallow_untyped_decorators = true +no_implicit_optional = true +warn_redundant_casts = true +warn_unused_ignores = true +warn_no_return = true +warn_return_any = true +warn_unreachable = true +implicit_reexport = true +strict_equality = true +show_error_context = true +show_column_numbers = true +show_error_codes = true +pretty = true +show_absolute_path = true +warn_unused_configs = true +verbosity = 0 + [egg_info] tag_build = tag_date = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-json-logger-2.0.2/setup.py new/python-json-logger-2.0.4/setup.py --- old/python-json-logger-2.0.2/setup.py 2021-07-28 01:09:19.000000000 +0200 +++ new/python-json-logger-2.0.4/setup.py 2022-07-11 16:07:55.000000000 +0200 @@ -8,7 +8,7 @@ setup( name="python-json-logger", - version="2.0.2", + version="2.0.4", url="http://github.com/madzak/python-json-logger", license="BSD", include_package_data=True, @@ -23,7 +23,7 @@ python_requires='>=3.5', test_suite="tests.tests", classifiers=[ - 'Development Status :: 3 - Alpha', + 'Development Status :: 6 - Mature', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-json-logger-2.0.2/src/python_json_logger.egg-info/PKG-INFO new/python-json-logger-2.0.4/src/python_json_logger.egg-info/PKG-INFO --- old/python-json-logger-2.0.2/src/python_json_logger.egg-info/PKG-INFO 2021-07-28 01:09:31.000000000 +0200 +++ new/python-json-logger-2.0.4/src/python_json_logger.egg-info/PKG-INFO 2022-07-11 16:08:03.000000000 +0200 @@ -1,186 +1,13 @@ Metadata-Version: 2.1 Name: python-json-logger -Version: 2.0.2 +Version: 2.0.4 Summary: A python library adding a json log formatter Home-page: http://github.com/madzak/python-json-logger Author: Zakaria Zajac Author-email: z...@madzak.com License: BSD -Description:  - [](https://pypi.python.org/pypi/python-json-logger/) - [](https://pypi.python.org/pypi/python-json-logger/) - - 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** - - ```python - 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: - - ```python - 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](http://www.structlog.org/) you could do something like this: - - ```python - 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 - - ```python - 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](https://docs.python.org/3/library/logging.config.html#logging.config.fileConfig), use the class `pythonjsonlogger.jsonlogger.JsonFormatter`. Here is a sample config file. - - ```ini - [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. - - ```json - { - "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 - ================= - - - [Wesley Tanaka - Structured log files in Python using python-json-logger](https://wtanaka.com/node/8201) - Platform: UNKNOWN -Classifier: Development Status :: 3 - Alpha +Classifier: Development Status :: 6 - Mature Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent @@ -195,3 +22,181 @@ Classifier: Topic :: System :: Logging Requires-Python: >=3.5 Description-Content-Type: text/markdown +License-File: LICENSE + + +[](https://pypi.python.org/pypi/python-json-logger/) +[](https://pypi.python.org/pypi/python-json-logger/) + +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** + +```python + 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: + +```python +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](http://www.structlog.org/) you could do something like this: + +```python +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 + +```python +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](https://docs.python.org/3/library/logging.config.html#logging.config.fileConfig), use the class `pythonjsonlogger.jsonlogger.JsonFormatter`. Here is a sample config file. + +```ini +[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. + +```json +{ + "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 +================= + +- [Wesley Tanaka - Structured log files in Python using python-json-logger](https://wtanaka.com/node/8201) + +- [Archive](https://web.archive.org/web/20201130054012/https://wtanaka.com/node/8201) + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-json-logger-2.0.2/src/pythonjsonlogger/jsonlogger.py new/python-json-logger-2.0.4/src/pythonjsonlogger/jsonlogger.py --- old/python-json-logger-2.0.2/src/pythonjsonlogger/jsonlogger.py 2021-07-28 01:09:19.000000000 +0200 +++ new/python-json-logger-2.0.4/src/pythonjsonlogger/jsonlogger.py 2022-07-11 16:07:55.000000000 +0200 @@ -9,20 +9,22 @@ import traceback import importlib +from typing import Any, Dict, Union, List, Tuple + from inspect import istraceback from collections import OrderedDict # skip natural LogRecord attributes # http://docs.python.org/library/logging.html#logrecord-attributes -RESERVED_ATTRS = ( +RESERVED_ATTRS: Tuple[str, ...] = ( 'args', 'asctime', 'created', 'exc_info', 'exc_text', 'filename', 'funcName', 'levelname', 'levelno', 'lineno', 'module', 'msecs', 'message', 'msg', 'name', 'pathname', 'process', 'processName', 'relativeCreated', 'stack_info', 'thread', 'threadName') -def merge_record_extra(record, target, reserved): +def merge_record_extra(record: logging.LogRecord, target: Dict, reserved: Union[Dict, List]) -> Dict: """ Merges extra attributes from LogRecord object into target dictionary @@ -80,7 +82,7 @@ def __init__(self, *args, **kwargs): """ :param json_default: a function for encoding non-standard objects - as outlined in http://docs.python.org/2/library/json.html + as outlined in https://docs.python.org/3/library/json.html :param json_encoder: optional custom encoder :param json_serializer: a :meth:`json.dumps`-compatible callable that will be used to serialize the log record. @@ -138,17 +140,30 @@ module = importlib.import_module(path) return getattr(module, function) - def parse(self): + def parse(self) -> List[str]: """ Parses format string looking for substitutions This method is responsible for returning a list of fields (as strings) to include in all log messages. """ - standard_formatters = re.compile(r'\((.+?)\)', re.IGNORECASE) - return standard_formatters.findall(self._fmt) + if isinstance(self._style, logging.StringTemplateStyle): + formatter_style_pattern = re.compile(r'\$\{(.+?)\}', re.IGNORECASE) + elif isinstance(self._style, logging.StrFormatStyle): + formatter_style_pattern = re.compile(r'\{(.+?)\}', re.IGNORECASE) + # PercentStyle is parent class of StringTemplateStyle and StrFormatStyle so + # it needs to be checked last. + elif isinstance(self._style, logging.PercentStyle): + formatter_style_pattern = re.compile(r'%\((.+?)\)', re.IGNORECASE) + else: + raise ValueError('Invalid format: %s' % self._fmt) + + if self._fmt: + return formatter_style_pattern.findall(self._fmt) + else: + return [] - def add_fields(self, log_record, record, message_dict): + def add_fields(self, log_record: Dict[str, Any], record: logging.LogRecord, message_dict: Dict[str, Any]) -> None: """ Override this method to implement custom logic for adding fields. """ @@ -180,15 +195,17 @@ indent=self.json_indent, ensure_ascii=self.json_ensure_ascii) - def serialize_log_record(self, log_record): + def serialize_log_record(self, log_record: Dict[str, Any]) -> str: """Returns the final representation of the log record.""" return "%s%s" % (self.prefix, self.jsonify_log_record(log_record)) - def format(self, record): + def format(self, record: logging.LogRecord) -> str: """Formats a log record and serializes to json""" - message_dict = {} - if isinstance(record.msg, dict): - message_dict = record.msg + message_dict: Dict[str, Any] = {} + # FIXME: logging.LogRecord.msg and logging.LogRecord.message in typeshed + # are always type of str. We shouldn't need to override that. + if isinstance(record.msg, dict): # type: ignore + message_dict = record.msg # type: ignore record.message = None else: record.message = record.getMessage() @@ -211,11 +228,8 @@ # Python2.7 doesn't have stack_info. pass - try: - log_record = OrderedDict() - except NameError: - log_record = {} - + log_record: Dict[str, Any] + log_record = OrderedDict() self.add_fields(log_record, record, message_dict) log_record = self.process_log_record(log_record) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-json-logger-2.0.2/tests/tests.py new/python-json-logger-2.0.4/tests/tests.py --- old/python-json-logger-2.0.2/tests/tests.py 2021-07-28 01:09:19.000000000 +0200 +++ new/python-json-logger-2.0.4/tests/tests.py 2022-07-11 16:07:55.000000000 +0200 @@ -42,6 +42,20 @@ self.assertEqual(logJson["message"], msg) + def testPercentageFormat(self): + fr = jsonlogger.JsonFormatter( + # All kind of different styles to check the regex + '[%(levelname)8s] %(message)s %(filename)s:%(lineno)d %(asctime)' + ) + self.logHandler.setFormatter(fr) + + msg = "testing logging format" + self.logger.info(msg) + logJson = json.loads(self.buffer.getvalue()) + + self.assertEqual(logJson["message"], msg) + self.assertEqual(logJson.keys(), {'levelname', 'message', 'filename', 'lineno', 'asctime'}) + def testRenameBaseField(self): fr = jsonlogger.JsonFormatter(rename_fields={'message': '@message'}) self.logHandler.setFormatter(fr)