diff --git a/lib/iris/analysis/maths.py b/lib/iris/analysis/maths.py index 3a38b3b283..161819a3ac 100644 --- a/lib/iris/analysis/maths.py +++ b/lib/iris/analysis/maths.py @@ -10,7 +10,6 @@ from functools import lru_cache import inspect -import logging import math import operator import warnings @@ -23,6 +22,7 @@ import iris.analysis from iris.common import SERVICES, Resolve from iris.common.lenient import _lenient_client +from iris.config import get_logger import iris.coords import iris.cube import iris.exceptions @@ -30,7 +30,7 @@ # Configure the logger. -logger = logging.getLogger(__name__) +logger = get_logger(__name__) @lru_cache(maxsize=128, typed=True) diff --git a/lib/iris/common/metadata.py b/lib/iris/common/metadata.py index af097ab4ec..da079fe019 100644 --- a/lib/iris/common/metadata.py +++ b/lib/iris/common/metadata.py @@ -9,13 +9,13 @@ from collections.abc import Iterable, Mapping from copy import deepcopy from functools import wraps -import logging import re import numpy as np import numpy.ma as ma from xxhash import xxh64_hexdigest +from ..config import get_logger from .lenient import _LENIENT from .lenient import _lenient_service as lenient_service from .lenient import _qualname as qualname @@ -40,7 +40,7 @@ _TOKEN_PARSE = re.compile(r"""^[a-zA-Z0-9][\w\.\+\-@]*$""") # Configure the logger. -logger = logging.getLogger(__name__) +logger = get_logger(__name__, fmt="[%(cls)s.%(funcName)s]") def _hexdigest(value): diff --git a/lib/iris/common/resolve.py b/lib/iris/common/resolve.py index 7098eaa65e..34c4333579 100644 --- a/lib/iris/common/resolve.py +++ b/lib/iris/common/resolve.py @@ -11,14 +11,15 @@ from dask.array.core import broadcast_shapes import numpy as np -from iris.common import LENIENT +from ..config import get_logger +from . import LENIENT __all__ = ["Resolve"] # Configure the logger. -logger = logging.getLogger(__name__) +logger = get_logger(__name__, fmt="[%(funcName)s]") _AuxCoverage = namedtuple( diff --git a/lib/iris/config.py b/lib/iris/config.py index eeef1873f9..cc918a296a 100644 --- a/lib/iris/config.py +++ b/lib/iris/config.py @@ -32,11 +32,77 @@ import configparser import contextlib -import logging.config +import logging import os.path -import pathlib import warnings -import yaml + + +def get_logger(name, datefmt=None, fmt=None, level=None, propagate=None): + """ + Create a :class:`logging.Logger` with a :class:`logging.StreamHandler` + and custom :class:`logging.Formatter`. + + Args: + + * name: + The name of the logger. Typically this is the module filename that + owns the logger. + + Kwargs: + + * datefmt: + The date format string of the :class:`logging.Formatter`. + Defaults to ``%d-%m-%Y %H:%M:%S``. + + * fmt: + The additional format string of the :class:`logging.Formatter`. + This is appended to the default format string + ``%(asctime)s %(name)s %(levelname)s - %(message)s``. + + * level: + The threshold level of the logger. Defaults to ``INFO``. + + * propagate: + Sets the ``propagate`` attribute of the :class:`logging.Logger`, + which determines whether events logged to this logger will be + passed to the handlers of higher level loggers. Defaults to + ``False``. + + """ + if datefmt is None: + # Default date format string. + datefmt = "%d-%m-%Y %H:%M:%S" + + # Default format string. + _fmt = "%(asctime)s %(name)s %(levelname)s - %(message)s" + # Append additional format string, if appropriate. + fmt = _fmt if fmt is None else f"{_fmt} {fmt}" + + if level is None: + # Default logging level. + level = "INFO" + + if propagate is None: + # Default logging propagate behaviour. + propagate = False + + # Create the named logger. + logger = logging.getLogger(name) + logger.setLevel(level) + logger.propagate = propagate + + # Create a formatter. + formatter = logging.Formatter(fmt=fmt, datefmt=datefmt) + + # Create a logging handler. + handler = logging.StreamHandler() + # handler.setLevel(level) + handler.setFormatter(formatter) + + # Add the handler to the logger. + logger.addHandler(handler) + + return logger # Returns simple string options @@ -84,15 +150,6 @@ def get_dir_option(section, option, default=None): config = configparser.ConfigParser() config.read([os.path.join(CONFIG_PATH, "site.cfg")]) -# Configure logging. -fname_logging = pathlib.Path(CONFIG_PATH) / "logging.yaml" -if not fname_logging.exists(): - emsg = f"Logging configuration file '{fname_logging!s}' does not exist." - raise FileNotFoundError(emsg) -with open(fname_logging) as fi: - logging.config.dictConfig(yaml.safe_load(fi)) -del fname_logging - ################## # Resource options _RESOURCE_SECTION = "Resources" diff --git a/lib/iris/etc/logging.yaml b/lib/iris/etc/logging.yaml deleted file mode 100644 index a73906e7db..0000000000 --- a/lib/iris/etc/logging.yaml +++ /dev/null @@ -1,45 +0,0 @@ -version: 1 - -formatters: - basic: - format: "%(asctime)s %(name)s %(levelname)s - %(message)s" - datefmt: "%d-%m-%Y %H:%M:%S" - basic-cls-func: - format: "%(asctime)s %(name)s %(levelname)s - %(message)s [%(cls)s.%(funcName)s]" - datefmt: "%d-%m-%Y %H:%M:%S" - basic-func: - format: "%(asctime)s %(name)s %(levelname)s - %(message)s [%(funcName)s]" - -handlers: - console: - class: logging.StreamHandler - formatter: basic - stream: ext://sys.stdout - console-cls-func: - class: logging.StreamHandler - formatter: basic-cls-func - stream: ext://sys.stdout - console-func: - class: logging.StreamHandler - formatter: basic-func - stream: ext://sys.stdout - -loggers: - iris.common.metadata: - level: INFO - handlers: [console-cls-func] - propagate: no - iris.common.resolve: - level: INFO - handlers: [console-func] - propagate: no - matplotlib: - level: INFO - PIL: - level: INFO - urllib3: - level: INFO - -root: - level: INFO - handlers: [console]