Skip to content

Commit

Permalink
Refactor the logging setup loggic (#3896)
Browse files Browse the repository at this point in the history
* Refactor the logging setup loggic

Signed-off-by: Nok <nok.lam.chan@quantumblack.com>

* fixing the linting error and delay log message

Signed-off-by: Nok <nok.lam.chan@quantumblack.com>

---------

Signed-off-by: Nok <nok.lam.chan@quantumblack.com>
  • Loading branch information
noklam authored Jun 25, 2024
1 parent 9883223 commit 413dbca
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 53 deletions.
42 changes: 18 additions & 24 deletions kedro/framework/project/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,39 +217,33 @@ class _ProjectLogging(UserDict):
def __init__(self) -> None:
"""Initialise project logging. The path to logging configuration is given in
environment variable KEDRO_LOGGING_CONFIG (defaults to conf/logging.yml)."""

# Check if a user path is set in the environment variable
logger = logging.getLogger(__name__)
user_logging_path = os.environ.get("KEDRO_LOGGING_CONFIG")
project_logging_path = Path("conf/logging.yml")
default_logging_path = Path(
Path(__file__).parent / "rich_logging.yml"
if importlib.util.find_spec("rich")
else Path(__file__).parent / "default_logging.yml",
)
path: str | Path
msg = ""

# Check if the default logging configuration exists
default_logging_path = Path("conf/logging.yml")
if not default_logging_path.exists():
default_logging_path = Path(
os.environ.get(
"KEDRO_LOGGING_CONFIG",
Path(__file__).parent / "rich_logging.yml"
if importlib.util.find_spec("rich")
else Path(__file__).parent / "default_logging.yml",
)
)
if user_logging_path:
path = user_logging_path

# Use the user path if available, otherwise, use the default path
if user_logging_path and Path(user_logging_path).exists():
path = Path(user_logging_path)
elif project_logging_path.exists():
path = project_logging_path
msg = "You can change this by setting the KEDRO_LOGGING_CONFIG environment variable accordingly."
else:
# Fallback to the framework default loggings
path = default_logging_path

msg = f"Using '{str(path)}' as logging configuration. " + msg

# Load and apply the logging configuration
logging_config = Path(path).read_text(encoding="utf-8")
self.configure(yaml.safe_load(logging_config))

# Log info about the logging configuration
if not user_logging_path and default_logging_path == Path("conf/logging.yml"):
logger = logging.getLogger(__name__)
logger.info(
f"Using `{path}` as logging configuration. "
f"You can change this by setting the KEDRO_LOGGING_CONFIG environment variable accordingly."
)
logger.info(msg)

def configure(self, logging_config: dict[str, Any]) -> None:
"""Configure project logging using ``logging_config`` (e.g. from project
Expand Down
49 changes: 20 additions & 29 deletions tests/framework/project/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,20 @@ def test_project_logging_in_default_logging_config(default_logging_config_with_p
assert logging.getLogger("test_project").level == logging.INFO


def test_environment_variable_logging_config(monkeypatch, tmp_path):
config_path = Path(tmp_path) / "logging.yml"
monkeypatch.setenv("KEDRO_LOGGING_CONFIG", config_path.absolute())
logging_config = {"version": 1, "loggers": {"kedro": {"level": "WARNING"}}}
def test_environment_variable_logging_config(monkeypatch, tmp_path, caplog):
config_path = (Path(tmp_path) / "logging.yml").absolute()
monkeypatch.setenv("KEDRO_LOGGING_CONFIG", config_path)
logging_config = {"version": 1, "loggers": {"kedro": {"level": "DEBUG"}}}
with config_path.open("w", encoding="utf-8") as f:
yaml.dump(logging_config, f)
from kedro.framework.project import _ProjectLogging

LOGGING = _ProjectLogging()

assert LOGGING.data == logging_config
assert logging.getLogger("kedro").level == logging.WARNING
assert logging.getLogger("kedro").level == logging.DEBUG
expected_message = f"Using '{config_path}'"
assert expected_message in "".join(caplog.messages).strip("\n")


def test_configure_logging():
Expand Down Expand Up @@ -146,31 +148,20 @@ def test_rich_traceback_disabled_on_databricks(
rich_pretty_install.assert_called()


def test_default_logging_info_emission(monkeypatch, capsys):
# Expected path and logging configuration
expected_path = Path("conf/logging.yml")
dummy_logging_config = yaml.dump(
{"version": 1, "loggers": {"kedro": {"level": "INFO"}}}
)

# Setup environment and path mocks
monkeypatch.delenv("KEDRO_LOGGING_CONFIG", raising=False)
monkeypatch.setattr(Path, "exists", lambda x: x == expected_path)
monkeypatch.setattr(
Path,
"read_text",
lambda x, encoding="utf-8": dummy_logging_config
if x == expected_path
else FileNotFoundError("File not found"),
)
def test_environment_variable_logging_config2(monkeypatch, tmp_path, caplog):
config_path = (Path(tmp_path) / "conf" / "logging.yml").absolute()
config_path.parent.mkdir(parents=True)
logging_config = {"version": 1, "loggers": {"kedro": {"level": "DEBUG"}}}
with config_path.open("w", encoding="utf-8") as f:
yaml.dump(logging_config, f)
import os

from kedro.framework.project import _ProjectLogging

_ProjectLogging()

captured = capsys.readouterr()
os.chdir(tmp_path)
LOGGING = _ProjectLogging()

expected_message = f"Using `{expected_path}`"
assert (
expected_message in captured.out
), f"Expected message not found in logs: {captured.out}"
assert LOGGING.data == logging_config
assert logging.getLogger("kedro").level == logging.DEBUG
expected_message = "You can change this by setting the KEDRO_LOGGING_CONFIG environment variable accordingly."
assert expected_message in "".join(caplog.messages).strip("\n")

0 comments on commit 413dbca

Please sign in to comment.