|
19 | 19 | Optional, |
20 | 20 | TypeVar, |
21 | 21 | Union, |
22 | | - cast, |
23 | 22 | overload, |
24 | 23 | ) |
25 | 24 |
|
26 | 25 | from aws_lambda_powertools.logging.constants import ( |
27 | | - LOGGER_ATTRIBUTE_HANDLER, |
28 | | - LOGGER_ATTRIBUTE_POWERTOOLS_HANDLER, |
29 | 26 | LOGGER_ATTRIBUTE_PRECONFIGURED, |
30 | 27 | ) |
31 | 28 | from aws_lambda_powertools.shared import constants |
|
37 | 34 | from aws_lambda_powertools.utilities import jmespath_utils |
38 | 35 |
|
39 | 36 | from ..shared.types import AnyCallableT |
40 | | -from .exceptions import InvalidLoggerSamplingRateError, OrphanedChildLoggerError |
| 37 | +from .exceptions import InvalidLoggerSamplingRateError |
41 | 38 | from .filters import SuppressFilter |
42 | 39 | from .formatter import ( |
43 | 40 | RESERVED_FORMATTER_CUSTOM_KEYS, |
@@ -239,14 +236,14 @@ def __init__( |
239 | 236 | self.child = child |
240 | 237 | self.logger_formatter = logger_formatter |
241 | 238 | self._stream = stream or sys.stdout |
| 239 | + self.logger_handler = logger_handler or logging.StreamHandler(self._stream) |
242 | 240 | self.log_uncaught_exceptions = log_uncaught_exceptions |
243 | 241 |
|
244 | 242 | self._is_deduplication_disabled = resolve_truthy_env_var_choice( |
245 | 243 | env=os.getenv(constants.LOGGER_LOG_DEDUPLICATION_ENV, "false"), |
246 | 244 | ) |
247 | 245 | self._default_log_keys = {"service": self.service, "sampling_rate": self.sampling_rate} |
248 | 246 | self._logger = self._get_logger() |
249 | | - self.logger_handler = logger_handler or self._get_handler() |
250 | 247 |
|
251 | 248 | # NOTE: This is primarily to improve UX, so IDEs can autocomplete LambdaPowertoolsFormatter options |
252 | 249 | # previously, we masked all of them as kwargs thus limiting feature discovery |
@@ -285,18 +282,6 @@ def _get_logger(self) -> logging.Logger: |
285 | 282 |
|
286 | 283 | return logging.getLogger(logger_name) |
287 | 284 |
|
288 | | - def _get_handler(self) -> logging.Handler: |
289 | | - # is a logger handler already configured? |
290 | | - if getattr(self, LOGGER_ATTRIBUTE_HANDLER, None): |
291 | | - return self.logger_handler |
292 | | - |
293 | | - # for children, use parent's handler |
294 | | - if self.child: |
295 | | - return getattr(self._logger.parent, LOGGER_ATTRIBUTE_POWERTOOLS_HANDLER, None) # type: ignore[return-value] # always checked in formatting |
296 | | - |
297 | | - # otherwise, create a new stream handler (first time init) |
298 | | - return logging.StreamHandler(self._stream) |
299 | | - |
300 | 285 | def _init_logger( |
301 | 286 | self, |
302 | 287 | formatter_options: Optional[Dict] = None, |
@@ -335,7 +320,6 @@ def _init_logger( |
335 | 320 | # std logging will return the same Logger with our attribute if name is reused |
336 | 321 | logger.debug(f"Marking logger {self.service} as preconfigured") |
337 | 322 | self._logger.init = True # type: ignore[attr-defined] |
338 | | - self._logger.powertools_handler = self.logger_handler # type: ignore[attr-defined] |
339 | 323 |
|
340 | 324 | def _configure_sampling(self) -> None: |
341 | 325 | """Dynamically set log level based on sampling rate |
@@ -691,20 +675,15 @@ def removeFilter(self, filter: logging._FilterType) -> None: # noqa: A002 # fil |
691 | 675 | @property |
692 | 676 | def registered_handler(self) -> logging.Handler: |
693 | 677 | """Convenience property to access the first logger handler""" |
694 | | - return self._get_handler() |
| 678 | + # We ignore mypy here because self.child encodes whether or not self._logger.parent is |
| 679 | + # None, mypy can't see this from context but we can |
| 680 | + handlers = self._logger.parent.handlers if self.child else self._logger.handlers # type: ignore[union-attr] |
| 681 | + return handlers[0] |
695 | 682 |
|
696 | 683 | @property |
697 | 684 | def registered_formatter(self) -> BasePowertoolsFormatter: |
698 | 685 | """Convenience property to access the first logger formatter""" |
699 | | - handler = self.registered_handler |
700 | | - if handler is None: |
701 | | - raise OrphanedChildLoggerError( |
702 | | - "Orphan child loggers cannot append nor remove keys until a parent is initialized first. " |
703 | | - "To solve this issue, you can A) make sure a parent logger is initialized first, or B) move append/remove keys operations to a later stage." # noqa: E501 |
704 | | - "Reference: https://docs.powertools.aws.dev/lambda/python/latest/core/logger/#reusing-logger-across-your-code", |
705 | | - ) |
706 | | - |
707 | | - return cast(BasePowertoolsFormatter, handler.formatter) |
| 686 | + return self.registered_handler.formatter # type: ignore[return-value] |
708 | 687 |
|
709 | 688 | @property |
710 | 689 | def log_level(self) -> int: |
|
0 commit comments