Lazy Logger Formatting
ID |
python.logging_no_format |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Efficiency |
Language |
Python |
Tags |
best-practice, efficiency |
Description
Reports logger calls whose first argument is a pre-formatted string — logger.info("got %s" % name), logger.info(f"got {name}"), logger.info("got " + str(name)), logger.info("got {}".format(name)). The logging module supports lazy interpolation: pass the format string and the arguments separately, and the interpolation runs only if the level is actually enabled.
logger.info("got %s" % name) # FLAW
logger.info(f"got {name}") # FLAW
logger.info("got " + str(name)) # FLAW
logger.info("got {}".format(name)) # FLAW
logger.info("got %s", name) # OK
Rationale
In a production service the bulk of the log calls are at DEBUG level and are not enabled. The eager forms still build the formatted string for every one of those calls, dominating the work the logging package is doing. The lazy form delegates the format step to the logger, which only runs it when the message is actually emitted.
The lazy form also integrates with structured-log handlers that want the args as fields rather than embedded in the message text.