diff --git a/CHANGELOG.md b/CHANGELOG.md index 366aab86..e697c3d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added rule GCI1066: For logging format, prefer using `%s` with kwargs instead of builtin formatter `"".format()` or `f""`, that way message formatting will be deferred until it cannot be avoided. + ### Changed - Correction of various typos in rules documentations diff --git a/RULES.md b/RULES.md index 5bf43932..f1988ba1 100644 --- a/RULES.md +++ b/RULES.md @@ -83,6 +83,8 @@ Some are applicable for different technologies. | | Resize images browser-side | Do not resize images using the HEIGHT and WIDTH attributes of the HTML code. This approach requires transferring these images to their original size, wasting bandwidth and CPU cycles. | [cnumr best practices (3rd edition) BP_034](https://github.com/cnumr/best-practices/blob/main/chapters/BP_034_fr.md) | 🚫 | 🚫 | 🚧 | 🚫 | 🚫 | 🚫 | 🚀 | | | Modify the DOM when traversing it | Modifying the DOM (Document Object Model) as you traverse it can lead to situations where the loop becomes very resource-intensive, especially CPU cycles. | [cnumr best practices (3rd edition) BP_041](https://github.com/cnumr/best-practices/blob/main/chapters/BP_041_fr.md) | 🚫 | 🚫 | 🚧 | 🚫 | 🚫 | 🚫 | 🚫 | | | Edit DOM elements to make it invisible | When an element of the Document Object Model (DOM) needs to be modified by several properties, each change in style or content will generate a repaint or reflow. | [cnumr best practices (3rd edition) BP_042](https://github.com/cnumr/best-practices/blob/main/chapters/BP_042_fr.md) | 🚫 | 🚫 | 🚀 | 🚫 | 🚫 | 🚫 | 🚫 | +| GCI1066 | Logging format interpolation | When logging with formatted string, prefer using `%s` with kwargs, which will be deferred until it cannot be avoided, instead of immediate formatter `.format()` of `f""`. | | 🚫 | 🚫 | 🚫 | 🚀 | 🚫 | 🚫 | 🚫 | + ## Rules to be reworked / measured / clarified diff --git a/src/main/rules/GCI1066/GCI1066.json b/src/main/rules/GCI1066/GCI1066.json new file mode 100644 index 00000000..512523e2 --- /dev/null +++ b/src/main/rules/GCI1066/GCI1066.json @@ -0,0 +1,18 @@ +{ + "title": "Logging Format Interpolation - Avoid using immediate string formatter in logging calls.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "creedengo", + "eco-design", + "performance", + "python", + "logging", + "format" + ], + "defaultSeverity": "Minor" +} diff --git a/src/main/rules/GCI1066/python/GCI1066.asciidoc b/src/main/rules/GCI1066/python/GCI1066.asciidoc new file mode 100644 index 00000000..9a958011 --- /dev/null +++ b/src/main/rules/GCI1066/python/GCI1066.asciidoc @@ -0,0 +1,51 @@ +When logging with formatted string, prefer using `%s` and logging kwargs which will be deferred until it cannot be avoided, instead of immediate `.format()` of `f""` interpolation. + +== Non Compliant Code Example + +[source,python] +---- +import logging +logging.basicConfig(level=logging.INFO) +name = "world" +logging.debug(f"hello {world}") # Non Compliant: the replacement will be done immediately but will not be printed because current level is INFO +---- + +== Compliant Solution + +[source,python] +---- +import logging +logging.basicConfig(level=logging.INFO) +name = "world" +logging.debug("hello %s", name) # Compliant: the replacement will be avoided by logging module because it is not necessary +---- + + +== Relevance Analysis + +This rule is relevant to logging formatting. Using logging kwargs is more efficient than immediate builtin formatting. + +=== Configuration + +* Processor: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz, 4 cores +* RAM: 8 GB +* CO2 Emissions Measurement: Using https://mlco2.github.io/codecarbon/[CodeCarbon] + +=== Context + +Two approaches were benchmarked: +- *Non-compliant:* Using logging with `.format()` +- *Compliant:* Using logging with `%s` and kwargs + +=== Impact Analysis + +image::result.png[] + +== Conclusion + +Replacing `f""` and `"".format()` with `%s` and logging kwargs permits to defer template replacement when the log is not displayed. + +== References + +- https://docs.python.org/3/howto/logging.html#optimization +- https://pylint.pycqa.org/en/latest/user_guide/messages/warning/logging-format-interpolation.html diff --git a/src/main/rules/GCI1066/python/result.png b/src/main/rules/GCI1066/python/result.png new file mode 100644 index 00000000..fecd21ec Binary files /dev/null and b/src/main/rules/GCI1066/python/result.png differ