Skip to content

Commit 131b30f

Browse files
committed
feat(logger-utils): allow preserving log level for discovered 3P loggers
1 parent 7668f06 commit 131b30f

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

aws_lambda_powertools/logging/utils.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,21 @@
99
def copy_config_to_registered_loggers(
1010
source_logger: Logger,
1111
log_level: Optional[Union[int, str]] = None,
12+
ignore_log_level=False,
1213
exclude: Optional[Set[str]] = None,
1314
include: Optional[Set[str]] = None,
1415
) -> None:
1516
"""Copies source Logger level and handler to all registered loggers for consistent formatting.
1617
1718
Parameters
1819
----------
20+
ignore_log_level
1921
source_logger : Logger
2022
Powertools for AWS Lambda (Python) Logger to copy configuration from
2123
log_level : Union[int, str], optional
2224
Logging level to set to registered loggers, by default uses source_logger logging level
25+
ignore_log_level: bool
26+
Whether to not touch log levels for discovered loggers. log_level param is disregarded when this is set.
2327
include : Optional[Set[str]], optional
2428
List of logger names to include, by default all registered loggers are included
2529
exclude : Optional[Set[str]], optional
@@ -54,7 +58,7 @@ def copy_config_to_registered_loggers(
5458

5559
registered_loggers = _find_registered_loggers(source_logger, loggers, filter_func)
5660
for logger in registered_loggers:
57-
_configure_logger(source_logger, logger, level)
61+
_configure_logger(source_logger=source_logger, logger=logger, level=level, ignore_log_level=ignore_log_level)
5862

5963

6064
def _include_registered_loggers_filter(loggers: Set[str]):
@@ -78,13 +82,21 @@ def _find_registered_loggers(
7882
return root_loggers
7983

8084

81-
def _configure_logger(source_logger: Logger, logger: logging.Logger, level: Union[int, str]) -> None:
85+
def _configure_logger(
86+
source_logger: Logger,
87+
logger: logging.Logger,
88+
level: Union[int, str],
89+
ignore_log_level: bool = False,
90+
) -> None:
91+
# customers may not want to copy the same log level from Logger to discovered loggers
92+
if not ignore_log_level:
93+
logger.setLevel(level)
94+
source_logger.debug(f"Logger {logger} reconfigured to use logging level {level}")
95+
8296
logger.handlers = []
83-
logger.setLevel(level)
8497
logger.propagate = False # ensure we don't propagate logs to existing loggers, #1073
8598
source_logger.append_keys(name="%(name)s") # include logger name, see #1267
8699

87-
source_logger.debug(f"Logger {logger} reconfigured to use logging level {level}")
88100
for source_handler in source_logger.handlers:
89101
logger.addHandler(source_handler)
90102
source_logger.debug(f"Logger {logger} reconfigured to use {source_handler}")

tests/functional/test_logger_utils.py

+22-3
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ def test_copy_config_to_ext_loggers_include_exclude(stdout, logger, log_level):
131131
# AND external logger_1 is also in EXCLUDE list
132132
utils.copy_config_to_registered_loggers(
133133
source_logger=powertools_logger,
134-
include={logger_1.name, logger_2.name},
135134
exclude={logger_1.name},
135+
include={logger_1.name, logger_2.name},
136136
)
137137
msg = "test message3"
138138
logger_2.info(msg)
@@ -175,8 +175,8 @@ def test_copy_config_to_ext_loggers_custom_log_level(stdout, logger, log_level,
175175
# AND external logger used with custom log_level
176176
utils.copy_config_to_registered_loggers(
177177
source_logger=powertools_logger,
178-
include={logger.name},
179178
log_level=level_to_set,
179+
include={logger.name},
180180
)
181181
msg = "test message4"
182182
logger.warning(msg)
@@ -263,7 +263,7 @@ def test_copy_config_to_ext_loggers_no_duplicate_logs(stdout, logger, log_level)
263263

264264
# WHEN configuration copied from Powertools for AWS Lambda (Python) logger
265265
# AND external logger used with custom log_level
266-
utils.copy_config_to_registered_loggers(source_logger=powertools_logger, include={logger.name}, log_level=level)
266+
utils.copy_config_to_registered_loggers(source_logger=powertools_logger, log_level=level, include={logger.name})
267267
msg = "test message4"
268268
logger.warning(msg)
269269

@@ -294,3 +294,22 @@ def test_logger_name_is_included_during_copy(stdout, logger, log_level):
294294
assert logger1_log["name"] == logger_1.name
295295
assert logger2_log["name"] == logger_2.name
296296
assert pt_log["name"] == powertools_logger.name
297+
298+
299+
def test_copy_config_to_ext_loggers_but_preserve_log_levels(stdout, logger, log_level):
300+
# GIVEN two external loggers and Powertools for AWS Lambda (Python) logger initialized
301+
third_party_log_level = logging.CRITICAL
302+
303+
logger_1 = logger()
304+
logger_2 = logger()
305+
logger_1.setLevel(third_party_log_level)
306+
logger_2.setLevel(third_party_log_level)
307+
308+
powertools_logger = Logger(service=service_name(), stream=stdout)
309+
310+
# WHEN configuration copied from Powertools for AWS Lambda (Python) logger to ALL external loggers
311+
utils.copy_config_to_registered_loggers(source_logger=powertools_logger, ignore_log_level=True)
312+
313+
# THEN external loggers log levels should be preserved
314+
assert logger_1.level != powertools_logger.log_level
315+
assert logger_2.level != powertools_logger.log_level

0 commit comments

Comments
 (0)