diff --git a/src/palace/manager/api/lanes.py b/src/palace/manager/api/lanes.py index efb1f6c05d..6b2c37f30b 100644 --- a/src/palace/manager/api/lanes.py +++ b/src/palace/manager/api/lanes.py @@ -1,5 +1,3 @@ -import logging - from sqlalchemy.orm import Session import palace.manager.core.classifier as genres @@ -26,6 +24,7 @@ from palace.manager.sqlalchemy.model.library import Library from palace.manager.sqlalchemy.util import create from palace.manager.util.languages import LanguageCodes +from palace.manager.util.log import logger_for_function def load_lanes(_db, library, collection_ids): @@ -851,7 +850,7 @@ def create_lane_for_small_collection(_db, library, parent, languages, priority=0 try: language_identifier = LanguageCodes.name_for_languageset(languages) except ValueError as e: - logging.getLogger().warning( + logger_for_function().warning( "Could not create a lane for small collection with languages %s", languages ) return 0 @@ -923,7 +922,7 @@ def create_lane_for_tiny_collection(_db, library, parent, languages, priority=0) try: name = LanguageCodes.name_for_languageset(languages) except ValueError as e: - logging.getLogger().warning( + logger_for_function().warning( "Could not create a lane for tiny collection with languages %s", languages ) return 0 diff --git a/src/palace/manager/celery/monitoring.py b/src/palace/manager/celery/monitoring.py index ac7c5dbaa8..a8746be04c 100644 --- a/src/palace/manager/celery/monitoring.py +++ b/src/palace/manager/celery/monitoring.py @@ -13,7 +13,7 @@ from palace.manager.util import chunks from palace.manager.util.datetime_helpers import utc_now -from palace.manager.util.log import LoggerMixin +from palace.manager.util.log import LoggerMixin, logger_for_cls if TYPE_CHECKING: from mypy_boto3_cloudwatch.literals import StandardUnitType @@ -156,7 +156,7 @@ def __init__( # We use logger_for_cls instead of just inheriting from LoggerMixin # because the base class Polaroid already defines a logger attribute, # which conflicts with the logger() method in LoggerMixin. - self.logger = LoggerMixin.logger_for_cls(self.__class__) + self.logger = logger_for_cls(self.__class__) region = self.app.conf.get("cloudwatch_statistics_region") dryrun = self.app.conf.get("cloudwatch_statistics_dryrun") self.cloudwatch_client = ( diff --git a/src/palace/manager/util/log.py b/src/palace/manager/util/log.py index 1c718df441..d3efc8e254 100644 --- a/src/palace/manager/util/log.py +++ b/src/palace/manager/util/log.py @@ -1,4 +1,5 @@ import functools +import inspect import logging import time from collections.abc import Callable, Generator @@ -88,13 +89,27 @@ def elapsed_time_logging( log_method(f"{prefix}Completed. (elapsed time: {elapsed_time:0.4f} seconds)") +def logger_for_function() -> logging.Logger: + try: + stack = inspect.stack() + previous_frame = stack[1] + fn_name = previous_frame.function + module = inspect.getmodule(previous_frame.frame) + module_name = module.__name__ # type: ignore[union-attr] + except: + fn_name = "" + module_name = "palace.manager" + + return logging.getLogger(f"{module_name}.{fn_name}") + + +def logger_for_cls(cls: type[object]) -> logging.Logger: + return logging.getLogger(f"{cls.__module__}.{cls.__name__}") + + class LoggerMixin: """Mixin that adds a logger with a standardized name""" - @staticmethod - def logger_for_cls(cls: type[object]) -> logging.Logger: - return logging.getLogger(f"{cls.__module__}.{cls.__name__}") - @classmethod @functools.cache def logger(cls) -> logging.Logger: @@ -104,7 +119,7 @@ def logger(cls) -> logging.Logger: This is cached so that we don't create a new logger every time it is called. """ - return cls.logger_for_cls(cls) + return logger_for_cls(cls) @property def log(self) -> logging.Logger: diff --git a/tests/manager/util/test_log.py b/tests/manager/util/test_log.py index 56c1df1905..13c859501b 100644 --- a/tests/manager/util/test_log.py +++ b/tests/manager/util/test_log.py @@ -1,8 +1,10 @@ +from unittest.mock import patch + import pytest from pytest import LogCaptureFixture from palace.manager.service.logging.configuration import LogLevel -from palace.manager.util.log import LoggerMixin, log_elapsed_time +from palace.manager.util.log import LoggerMixin, log_elapsed_time, logger_for_function class MockClass(LoggerMixin): @@ -51,3 +53,12 @@ def test_log_elapsed_time_invalid(caplog: LogCaptureFixture): with pytest.raises(RuntimeError): log_elapsed_time(log_level=LogLevel.info, message_prefix="Test")(lambda: None)() assert len(caplog.records) == 0 + + +def test_logger_for_function(): + logger = logger_for_function() + assert logger.name == "tests.manager.util.test_log.test_logger_for_function" + + with patch("palace.manager.util.log.inspect", side_effect=Exception("Boom")): + logger = logger_for_function() + assert logger.name == "palace.manager."