Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Put framework logging into LOGGING and fix import resetting logging #1644

Merged
merged 28 commits into from
Jun 29, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5d96b71
Put framework logging into LOGGING and guard configure_logging from a…
antonymilne Jun 22, 2022
a234f84
Fix tests
antonymilne Jun 22, 2022
2b23ee1
Update kedro/config/config.py
antonymilne Jun 22, 2022
aa78c06
Take 2 with no default_logger file at all
antonymilne Jun 24, 2022
1c5fa6c
Tidy
antonymilne Jun 24, 2022
b72e916
More tidy
antonymilne Jun 24, 2022
5ea3f8c
Merge branch 'main' into fix/parallel-runner-logging
antonymilne Jun 24, 2022
de4cb59
Apply suggestions from code review
antonymilne Jun 24, 2022
1f36779
Fix up tests
antonymilne Jun 24, 2022
880bc29
More fix tests
antonymilne Jun 24, 2022
15f117e
Fix MANIFEST.in
antonymilne Jun 24, 2022
f5ccde4
Lint
antonymilne Jun 24, 2022
0abfd6a
Fix linkcheck
antonymilne Jun 24, 2022
e603ba2
Update RELEASE
antonymilne Jun 24, 2022
d5dd2ec
Merge branch 'main' into fix/parallel-runner-logging
antonymilne Jun 27, 2022
f8708f2
Tidy
antonymilne Jun 29, 2022
35ca6f1
Update RELEASE.md
antonymilne Jun 29, 2022
8a321c3
More tidy
antonymilne Jun 29, 2022
e1ac1f3
Merge remote-tracking branch 'origin/fix/parallel-runner-logging' int…
antonymilne Jun 29, 2022
5c6312e
Update kedro/framework/cli/micropkg.py
antonymilne Jun 29, 2022
904b899
Tidy
antonymilne Jun 29, 2022
3edb592
Merge remote-tracking branch 'origin/fix/parallel-runner-logging' int…
antonymilne Jun 29, 2022
3ece394
Add tests
antonymilne Jun 29, 2022
70d9dd7
Cleanup after tests
antonymilne Jun 29, 2022
08cda7a
Lint
antonymilne Jun 29, 2022
55110c0
Update docs/conf.py
antonymilne Jun 29, 2022
46fa3ad
Update docs/source/logging/logging.md
antonymilne Jun 29, 2022
b269dce
Update docs/conf.py
antonymilne Jun 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions kedro/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ class ConfigLoader(AbstractConfigLoader):
>>> conf_path = str(project_path / settings.CONF_SOURCE)
>>> conf_loader = ConfigLoader(conf_source=conf_path, env="local")
>>>
>>> conf_logging = conf_loader.get('logging*')
>>> logging.config.dictConfig(conf_logging) # set logging conf
>>> logging_config = conf_loader.get('logging*')
>>> logging.config.dictConfig(logging_config) # set logging conf
antonymilne marked this conversation as resolved.
Show resolved Hide resolved
>>>
>>> conf_catalog = conf_loader.get('catalog*', 'catalog*/**')
>>> conf_params = conf_loader.get('**/parameters.yml')
Expand Down
21 changes: 10 additions & 11 deletions kedro/config/default_logger.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
"""This module facilitates the loading of the default ``kedro.config``
for setting up the logging
"""

import logging.config
import os
import sys
from pathlib import Path

import click
import yaml
from rich.traceback import install

CURRENT_DIR = os.path.dirname(__file__)
from kedro.framework.project import configure_logging


with open(os.path.join(CURRENT_DIR, "logging.yml"), encoding="utf-8") as conf_file:
LOGGING_CONFIG = yaml.safe_load(conf_file.read())
logging.config.dictConfig(LOGGING_CONFIG)
logging.captureWarnings(True)
def configure_default_logging():
logging_config = yaml.safe_load((Path(__file__).parent / "logging.yml").read_text())
configure_logging(logging_config)

# We suppress click here to hide tracebacks related to it conversely,
# kedro is not suppressed to show its tracebacks for easier debugging.
# sys.executable is used to get the kedro executable path to hide the top level traceback.
install(show_locals=True, suppress=[click, os.path.dirname(sys.executable)])
# We suppress click here to hide tracebacks related to it conversely,
# kedro is not suppressed to show its tracebacks for easier debugging.
# sys.executable is used to get the kedro executable path to hide the top level traceback.
install(show_locals=True, suppress=[click, os.path.dirname(sys.executable)])
7 changes: 2 additions & 5 deletions kedro/framework/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
This module implements commands available from the kedro CLI.
"""
import importlib
import logging
import sys
import webbrowser
from collections import defaultdict
Expand All @@ -13,9 +12,8 @@
import click
import importlib_metadata

# pylint: disable=unused-import
import kedro.config.default_logger # noqa
from kedro import __version__ as version
from kedro.config.default_logger import configure_default_logging
from kedro.framework.cli.catalog import catalog_cli
from kedro.framework.cli.hooks import get_cli_hook_manager
from kedro.framework.cli.jupyter import jupyter_cli
Expand All @@ -42,8 +40,6 @@
v{version}
"""

logger = logging.getLogger(__name__)


@click.group(context_settings=CONTEXT_SETTINGS, name="Kedro")
@click.version_option(version, "--version", "-V", help="Show version and exit")
Expand Down Expand Up @@ -210,6 +206,7 @@ def main(): # pragma: no cover
"""Main entry point. Look for a ``cli.py``, and, if found, add its
commands to `kedro`'s before invoking the CLI.
"""
configure_default_logging()
_init_plugins()
cli_collection = KedroCLI(project_path=Path.cwd())
cli_collection()
10 changes: 6 additions & 4 deletions kedro/framework/project/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def configure(self, pipelines_module: Optional[str] = None) -> None:


PACKAGE_NAME = None
LOGGING = None
LOGGING_CONFIG = None

settings = _ProjectSettings()

Expand All @@ -206,10 +206,12 @@ def configure_project(package_name: str):


def configure_logging(logging_config: Dict[str, Any]) -> None:
"""Configure logging to make it available as a global variable."""
"""Configure logging and make it available as a global variable."""
logging.config.dictConfig(logging_config)
global LOGGING
LOGGING = logging_config
logging.captureWarnings(True)

global LOGGING_CONFIG
LOGGING_CONFIG = logging_config


def validate_settings():
Expand Down
12 changes: 6 additions & 6 deletions kedro/framework/session/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,27 +172,27 @@ def create( # pylint: disable=too-many-arguments
return session

def _get_logging_config(self) -> Dict[str, Any]:
conf_logging = self._get_config_loader().get(
logging_config = self._get_config_loader().get(
"logging*", "logging*/**", "**/logging*"
)
# turn relative paths in logging config into absolute path
# before initialising loggers
conf_logging = _convert_paths_to_absolute_posix(
project_path=self._project_path, conf_dictionary=conf_logging
logging_config = _convert_paths_to_absolute_posix(
project_path=self._project_path, conf_dictionary=logging_config
)
return conf_logging
return logging_config

def _setup_logging(self) -> None:
"""Register logging specified in logging directory."""
try:
conf_logging = self._get_logging_config()
logging_config = self._get_logging_config()
except MissingConfigException:
self._logger.debug(
"No project logging configuration loaded; "
"Kedro's default logging configuration will be used."
)
else:
configure_logging(conf_logging)
configure_logging(logging_config)

def _init_store(self) -> BaseSessionStore:
store_class = settings.SESSION_STORE_CLASS
Expand Down
19 changes: 9 additions & 10 deletions kedro/runner/parallel_runner.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""``ParallelRunner`` is an ``AbstractRunner`` implementation. It can
be used to run the ``Pipeline`` in parallel groups formed by toposort.
"""
import logging.config
import multiprocessing
import os
import pickle
Expand Down Expand Up @@ -81,14 +80,14 @@ class ParallelRunnerManager(SyncManager):


def _bootstrap_subprocess(
package_name: str, conf_logging: Optional[Dict[str, Any]] = None
package_name: str, logging_config: Optional[Dict[str, Any]] = None
):
# pylint: disable=import-outside-toplevel,cyclic-import
from kedro.framework.project import configure_project
from kedro.framework.project import configure_logging, configure_project

configure_project(package_name)
if conf_logging is not None:
logging.config.dictConfig(conf_logging)
if logging_config is not None:
configure_logging(logging_config)


def _run_node_synchronization( # pylint: disable=too-many-arguments
Expand All @@ -97,7 +96,7 @@ def _run_node_synchronization( # pylint: disable=too-many-arguments
is_async: bool = False,
session_id: str = None,
package_name: str = None,
conf_logging: Optional[Dict[str, Any]] = None,
logging_config: Optional[Dict[str, Any]] = None,
) -> Node:
"""Run a single `Node` with inputs from and outputs to the `catalog`.

Expand All @@ -111,14 +110,14 @@ def _run_node_synchronization( # pylint: disable=too-many-arguments
asynchronously with threads. Defaults to False.
session_id: The session id of the pipeline run.
package_name: The name of the project Python package.
conf_logging: A dictionary containing logging configuration.
logging_config: A dictionary containing logging configuration.

Returns:
The node argument.

"""
if multiprocessing.get_start_method() == "spawn" and package_name: # type: ignore
_bootstrap_subprocess(package_name, conf_logging)
_bootstrap_subprocess(package_name, logging_config)

hook_manager = _create_hook_manager()
_register_hooks(hook_manager, settings.HOOKS)
Expand Down Expand Up @@ -300,7 +299,7 @@ def _run( # pylint: disable=too-many-locals,useless-suppression
done = None
max_workers = self._get_required_workers_count(pipeline)

from kedro.framework.project import LOGGING, PACKAGE_NAME
from kedro.framework.project import LOGGING_CONFIG, PACKAGE_NAME

with ProcessPoolExecutor(max_workers=max_workers) as pool:
while True:
Expand All @@ -315,7 +314,7 @@ def _run( # pylint: disable=too-many-locals,useless-suppression
self._is_async,
session_id,
package_name=PACKAGE_NAME,
conf_logging=LOGGING,
logging_config=LOGGING_CONFIG,
)
)
if not futures:
Expand Down
8 changes: 4 additions & 4 deletions tests/runner/test_parallel_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,14 +359,14 @@ def mock_run_node(self, mocker):
def mock_configure_project(self, mocker):
return mocker.patch("kedro.framework.project.configure_project")

@pytest.mark.parametrize("conf_logging", [{"fake_logging_config": True}, {}])
@pytest.mark.parametrize("logging_config", [{"fake_logging_config": True}, {}])
def test_package_name_and_logging_provided(
self,
mock_logging,
mock_run_node,
mock_configure_project,
is_async,
conf_logging,
logging_config,
mocker,
):
mocker.patch("multiprocessing.get_start_method", return_value="spawn")
Expand All @@ -381,10 +381,10 @@ def test_package_name_and_logging_provided(
is_async,
session_id,
package_name=package_name,
conf_logging=conf_logging,
logging_config=logging_config,
)
mock_run_node.assert_called_once()
mock_logging.assert_called_once_with(conf_logging)
mock_logging.assert_called_once_with(logging_config)
mock_configure_project.assert_called_once_with(package_name)

def test_package_name_provided(
Expand Down