0

I would like to understand if it's possible and how is it possible, to modify the message part of a log message, using the Python logging module.

So basically, you can format a complete log as:

format = '{"timestamp": "%(asctime)s", "logger_level": "%(levelname)s", "log_message": %(message)s}'

However, I would like to make sure the message part is always in json format. Is there any way I can modify the format of only the message part, maybe with a custom logging.Formatter?

Thank you.

8
  • 2
    That it gets converted to json with a json.dumps() I would expect Commented Oct 21, 2021 at 12:30
  • is this not sufficient? - github.com/madzak/python-json-logger Or I didnt understood your question correctly Commented Oct 21, 2021 at 12:32
  • The problem is that, if the message is a dictionary, it formats it as a whole string, while I would like the whole log to be a json item Commented Oct 21, 2021 at 12:43
  • Can you please provide a simple example with both actual and expected output? stackoverflow.com/help/minimal-reproducible-example Commented Oct 21, 2021 at 12:46
  • @daniel, are you saying that you would like log["log_message"] to be a dictionary, instead of a string? (After parsing the log string as json, of course.) Commented Oct 21, 2021 at 13:30

2 Answers 2

1

The format specification %(message)s tells Python you want to format a string. Try it with %(message)r and it should do the job:

>>> logging.error('{"log_message": %r}', {"a": 55})
ERROR:root:{"log_message": {'a': 55}}
Sign up to request clarification or add additional context in comments.

Comments

1

There's an example in the Logging Cookbook which shows one way of doing this.Basically:

import json
import logging

class StructuredMessage:
    def __init__(self, message, /, **kwargs):
        self.message = message
        self.kwargs = kwargs

    def __str__(self):
        return '%s >>> %s' % (self.message, json.dumps(self.kwargs))

_ = StructuredMessage   # optional, to improve readability

logging.basicConfig(level=logging.INFO, format='%(message)s')
logging.info(_('message 1', foo='bar', bar='baz', num=123, fnum=123.456))

Of course, you can adapt this basic idea to do something closer to what you want/need.

Update: The formatting only happens if the message is actually output. Also, it won't apply to logging from third-party libraries. You would need to subclass Logger before importing any other modules which import logging to achieve that, but it's a documented approach.

1 Comment

However, this requires you to implicitly format every message before it's passed to the logging module. Is it possible that this formatting is apply to all messages without having to say so specifically?

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.