Issue 34844: logging.Formatter enhancement - Checking on style and fmt fields (original) (raw)

Issue: Currently logging.Formatter does not check if the format passed in is valid style or if the field is valid when creating the logging.Formatter object. It would be nice to have such check in the constructor of the logging.Formatter.

Here are 2 scenarios:

Scenario 1: Passing in invalid fmt when creating the logging.Formatter. Example: import logging logger = logging.getLogger('my_logger') handler = logging.StreamHandler()

fmt = logging.Formatter("blah-blah", style="{")
handler.setFormatter(fmt)

logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

logger.info('This is my logging message.')

The above example would output the fmt string("blah-blah") whenever a logging operation is performed, such as logging.info, logging.warning. And this goes the same for mismatching style and fmt, like so: fmt = logging.Formatter("{asctime}-{message}", style="%")

Scenario 2: Passing in invalid fields to logging.Formatter

import logging
logger = logging.getLogger('my_logger')
handler = logging.StreamHandler()

fmt = logging.Formatter("%(FuncName)s-%(message)s")
handler.setFormatter(fmt)

logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

logger.info('This is my logging message.'

) As you can see from the above example, the "%(FuncName)s" field is misspelled with a capital "F", which should have been a lowercase "f". In this scenario, we would get an interesting stacktrace:

--- Logging error --- Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/init.py", line 992, in emit msg = self.format(record) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/init.py", line 838, in format return fmt.format(record) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/init.py", line 578, in format s = self.formatMessage(record) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/init.py", line 547, in formatMessage return self._style.format(record) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/init.py", line 391, in format return self._fmt % record.dict KeyError: 'FuncName' Call stack: File "", line 1, in Message: 'This is my logging message.' Arguments: ()

Personally, I think the "KeyError" here can be misleading and confusing to some.

Proposal:

I would like to make a PR with the following changes:

Draw Backs:

Please let me know your thoughts, and I thought it would be nice to get some new ideas and areas I haven't thought about before I make this PR.

Best regards, Luna Chen (BNMetrics)

Checking fmt to match the style in the constructor of logging.Formatter

This seems a reasonable change to want to make. You would need to parse the format string for fields using the appropriate style. This should probably be via a validate() method in each of the XXXStyle classes, which is passed the format string and raises an exception if invalid.

I would like to have custom fields passed in as an additional (optional) argument into the constructor for logging.Formatter

If this is just a list of custom field names, it could be inferred from the passed format string, which will now be being parsed for fields for the checking described above. So there should be no need to pass an additional argument.

With this, we can remove the "extra" argument in Logger.makeRecord()

We can't do this, because of the need to maintain backwards compatibility. Note also that custom fields can be introduced into a LogRecord in other ways, e.g. using Filters.

the "KeyError" here can be misleading and confusing

It seems reasonable to make a change to re-raise such a KeyError using a more informative error message, perhaps as a ValueError.