|
1 | 1 | import logging
|
2 |
| -from typing import Callable, List, Optional, TypeVar |
| 2 | +from typing import Callable, List, Optional, Set, Union |
3 | 3 |
|
4 | 4 | from .logger import Logger
|
5 | 5 |
|
6 |
| -PowertoolsLogger = TypeVar("PowertoolsLogger", bound=Logger) |
7 |
| - |
8 | 6 |
|
9 | 7 | def copy_config_to_registered_loggers(
|
10 |
| - source_logger: PowertoolsLogger, |
11 |
| - exclude: Optional[List[str]] = None, |
12 |
| - include: Optional[List[str]] = None, |
| 8 | + source_logger: Logger, |
| 9 | + log_level: Optional[str] = None, |
| 10 | + exclude: Optional[Set[str]] = None, |
| 11 | + include: Optional[Set[str]] = None, |
13 | 12 | ) -> None:
|
14 |
| - """Enable powertools logging for imported libraries. |
15 | 13 |
|
16 |
| - Attach source logger handlers to external loggers. |
17 |
| - Modify logger level based on source logger attribute. |
18 |
| - Ensure powertools logger itself is excluded from registered list. |
| 14 | + """Copies source Logger level and handler to all registered loggers for consistent formatting. |
| 15 | +
|
| 16 | + Parameters |
| 17 | + ---------- |
| 18 | + source_logger : Logger |
| 19 | + Powertools Logger to copy configuration from |
| 20 | + log_level : str, optional |
| 21 | + Logging level to set to registered loggers, by default uses source_logger logging level |
| 22 | + include : Optional[Set[str]], optional |
| 23 | + List of logger names to include, by default all registered loggers are included |
| 24 | + exclude : Optional[Set[str]], optional |
| 25 | + List of logger names to exclude, by default None |
19 | 26 | """
|
20 | 27 |
|
21 |
| - if include and not exclude: |
22 |
| - loggers = include |
23 |
| - filter_func = _include_registered_loggers_filter |
24 |
| - elif include and exclude: |
25 |
| - exclude = [source_logger.name, *exclude] |
26 |
| - loggers = list(set(include) - set(exclude)) |
| 28 | + level = log_level or source_logger.level |
| 29 | + |
| 30 | + # Assumptions: Only take parent loggers not children (dot notation rule) |
| 31 | + # Steps: |
| 32 | + # 1. Default operation: Include all registered loggers |
| 33 | + # 2. Only include set? Only add Loggers in the list and ignore all else |
| 34 | + # 3. Include and exclude set? Add Logger if it’s in include and not in exclude |
| 35 | + # 4. Only exclude set? Ignore Logger in the excluding list |
| 36 | + |
| 37 | + # Exclude source logger by default |
| 38 | + if exclude: |
| 39 | + exclude.add(source_logger.name) |
| 40 | + else: |
| 41 | + exclude = set(source_logger.name) |
| 42 | + |
| 43 | + # Prepare loggers set |
| 44 | + if include: |
| 45 | + loggers = include.difference(exclude) |
27 | 46 | filter_func = _include_registered_loggers_filter
|
28 |
| - elif not include and exclude: |
29 |
| - loggers = [source_logger.name, *exclude] |
30 |
| - filter_func = _exclude_registered_loggers_filter |
31 | 47 | else:
|
32 |
| - loggers = [source_logger.name] |
| 48 | + loggers = exclude |
33 | 49 | filter_func = _exclude_registered_loggers_filter
|
34 | 50 |
|
35 | 51 | registered_loggers = _find_registered_loggers(source_logger, loggers, filter_func)
|
36 | 52 | for logger in registered_loggers:
|
37 |
| - _configure_logger(source_logger, logger) |
| 53 | + _configure_logger(source_logger, logger, level) |
38 | 54 |
|
39 | 55 |
|
40 |
| -def _include_registered_loggers_filter(loggers: List[str]): |
| 56 | +def _include_registered_loggers_filter(loggers: Set[str]): |
41 | 57 | return [logging.getLogger(name) for name in logging.root.manager.loggerDict if "." not in name and name in loggers]
|
42 | 58 |
|
43 | 59 |
|
44 |
| -def _exclude_registered_loggers_filter(loggers: List[str]) -> List[logging.Logger]: |
| 60 | +def _exclude_registered_loggers_filter(loggers: Set[str]) -> List[logging.Logger]: |
45 | 61 | return [
|
46 | 62 | logging.getLogger(name) for name in logging.root.manager.loggerDict if "." not in name and name not in loggers
|
47 | 63 | ]
|
48 | 64 |
|
49 | 65 |
|
50 | 66 | def _find_registered_loggers(
|
51 |
| - source_logger: PowertoolsLogger, loggers: List[str], filter_func: Callable |
| 67 | + source_logger: Logger, loggers: Set[str], filter_func: Callable[[Set[str]], List[logging.Logger]] |
52 | 68 | ) -> List[logging.Logger]:
|
53 | 69 | """Filter root loggers based on provided parameters."""
|
54 | 70 | root_loggers = filter_func(loggers)
|
55 | 71 | source_logger.debug(f"Filtered root loggers: {root_loggers}")
|
56 | 72 | return root_loggers
|
57 | 73 |
|
58 | 74 |
|
59 |
| -def _configure_logger(source_logger: PowertoolsLogger, logger: logging.Logger) -> None: |
| 75 | +def _configure_logger(source_logger: Logger, logger: logging.Logger, level: Union[int, str]) -> None: |
60 | 76 | logger.handlers = []
|
61 |
| - logger.setLevel(source_logger.level) |
62 |
| - source_logger.debug(f"Logger {logger} reconfigured to use logging level {source_logger.level}") |
| 77 | + logger.setLevel(level) |
| 78 | + source_logger.debug(f"Logger {logger} reconfigured to use logging level {level}") |
63 | 79 | for source_handler in source_logger.handlers:
|
64 | 80 | logger.addHandler(source_handler)
|
65 | 81 | source_logger.debug(f"Logger {logger} reconfigured to use {source_handler}")
|
0 commit comments