1
  • I want to configure a json logger, and use the logging config file.
  • I can achieve the equivalent programmatically (without a config file)
  • When I use a config file, I have problems with imported package jsonlogger
  • Note that this is not a duplicate of this
import logging
import logging.config
from pythonjsonlogger import jsonlogger # <----- where should I put this import ?

logging.config.fileConfig("logging.cfg")

logging.info("where is my stuff ?")

And here is my config file:

[loggers]
keys=root

[handlers]
keys=simple

[formatters]
keys=simple

[logger_root]
level=INFO
handlers=simple

[handler_simple]
class=StreamHandler
formatter=simple

[formatter_simple]
format="[ %(asctime)s %(levelname)s ] %(message)s"
datefmt="%d/%m/%y ( %H:%M:%S )"
class=jsonlogger.JsonFormatter # <----- how to let module know this class ?

When I run my program this is the error I get:

Traceback (most recent call last):
  File "main.py", line 5, in <module>
    logging.config.fileConfig("logging.cfg")
  File "/usr/lib/python3.10/logging/config.py", line 72, in fileConfig
    formatters = _create_formatters(cp)
  File "/usr/lib/python3.10/logging/config.py", line 119, in _create_formatters
    c = _resolve(class_name)
  File "/usr/lib/python3.10/logging/config.py", line 90, in _resolve
    found = __import__(used)
ModuleNotFoundError: No module named 'jsonlogger'
1
  • 1
    I didn't quite understand your comment on my answer. If you do a Web search, you'll see it's quite common to load a dict from e.g. YAML or JSON and use that in a dictConfig() call. Commented Jul 20, 2022 at 15:35

2 Answers 2

1

If you use dictConfig() rather than the older fileConfig(), you should be able to access jsonlogger if it's in the import path (e.g. installed in a venv for your application). You'd just declare a class of e.g. pythonjsonlogger.jsonlogger.JsonFormatter for your formatter.

Sign up to request clarification or add additional context in comments.

1 Comment

Is it common to load a configuration file to a dict and use dictConfig() ? should I avoid using configuration files in the logging context ?
0

Here is a complete working example that demonstrates the following:

  • loading configuration from a json file
  • default (root) logger + customized (analyzer) logger
  • uses pythonjsonlogger.jsonlogger.JsonFormatter
  • passes parameters to pythonjsonlogger.jsonlogger.JsonFormatter

This answer is based on:

Here is how I use the logging mechanism:

import json
import logging
import logging.config

with open("logging.json") as fl:
    logging.config.dictConfig(
        json.load(fl)
    )

# default (root) logger
logging.info("where is my stuff ?")

# customized (analyzer) logger
logging.getLogger("analyzer").info(
    "it is right there"
)

And here is the complete configuration file (a bit long)

{
    "version": 1,
    "formatters": {
        "formatter_default": {
            "format": "[ %(asctime)s ] [%(levelname)s] %(message)s",
            "datefmt": "%d/%m/%y ( %H:%M:%S )"
        },
        "formatter_analyzer": {
            "()": "pythonjsonlogger.jsonlogger.JsonFormatter",
            "format": "[ %(asctime)s ] %(levelname)s %(message)s",
            "datefmt": "%d/%m/%y ( %H:%M:%S )",
            "rename_fields": {
                "asctime": "time",
                "levelname": "level"
            },
            "json_indent": 4
        }

    },
    "handlers": { 
        "handler_default": { 
            "formatter": "formatter_default",
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stdout"
        },
        "handler_analyzer": { 
            "formatter": "formatter_analyzer",
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stdout"
        }

    },
    "loggers": { 
        "root": {
            "handlers": ["handler_default"],
            "level": "INFO"
        },
        "analyzer": { 
            "handlers": ["handler_analyzer"],
            "propagate": false, # <----- needed !
            "level": "INFO"
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.