diff --git a/changelog/37.misc.rst b/changelog/37.misc.rst new file mode 100644 index 00000000..c41ebf25 --- /dev/null +++ b/changelog/37.misc.rst @@ -0,0 +1 @@ +Modules now import the shared ``seismometer`` logger from ``seismometer.core.logger`` instead of each calling ``logging.getLogger("seismometer")``. diff --git a/src/seismometer/__init__.py b/src/seismometer/__init__.py index f6bb50ce..70465c70 100644 --- a/src/seismometer/__init__.py +++ b/src/seismometer/__init__.py @@ -10,12 +10,12 @@ import pandas as pd from seismometer.core.autometrics import initialize_otel_config +from seismometer.core.logger import logger # isort: split from seismometer.api import * __version__ = importlib.metadata.version("seismometer") -logger = logging.getLogger("seismometer") def run_startup( diff --git a/src/seismometer/api/plots.py b/src/seismometer/api/plots.py index d3890f58..58e97342 100644 --- a/src/seismometer/api/plots.py +++ b/src/seismometer/api/plots.py @@ -1,4 +1,3 @@ -import logging from typing import Any, Optional import numpy as np @@ -9,6 +8,7 @@ from seismometer.controls.decorators import disk_cached_html_segment from seismometer.core.autometrics import store_call_parameters from seismometer.core.decorators import export +from seismometer.core.logger import logger from seismometer.data import get_cohort_data, get_cohort_performance_data from seismometer.data import pandas_helpers as pdh from seismometer.data import telemetry @@ -24,8 +24,6 @@ from seismometer.html import template from seismometer.seismogram import Seismogram -logger = logging.getLogger("seismometer") - @export def plot_cohort_hist(): diff --git a/src/seismometer/api/reports.py b/src/seismometer/api/reports.py index e113b1c7..12c4cd79 100644 --- a/src/seismometer/api/reports.py +++ b/src/seismometer/api/reports.py @@ -1,18 +1,16 @@ -import logging from typing import Optional from seismometer.controls.categorical import ExploreCategoricalPlots from seismometer.controls.categorical_single_column import ExploreSingleCategoricalPlots from seismometer.core.autometrics import store_call_parameters from seismometer.core.decorators import export +from seismometer.core.logger import logger from seismometer.data.filter import FilterRule from seismometer.report.profiling import ComparisonReportWrapper, SingleReportWrapper from seismometer.seismogram import Seismogram from seismometer.table.analytics_table import ExploreBinaryModelAnalytics from seismometer.table.fairness import ExploreBinaryModelFairness -logger = logging.getLogger("seismometer") - @export class ExploreFairnessAudit(ExploreBinaryModelFairness): diff --git a/src/seismometer/api/templates.py b/src/seismometer/api/templates.py index 1435a971..9bd2db4a 100644 --- a/src/seismometer/api/templates.py +++ b/src/seismometer/api/templates.py @@ -1,5 +1,3 @@ -import logging - import pandas as pd from IPython.display import HTML from pandas.io.formats.style import Styler @@ -10,8 +8,6 @@ from seismometer.html import template from seismometer.seismogram import Seismogram -logger = logging.getLogger("seismometer") - def _get_info_dict(plot_help: bool) -> dict[str, str | list[str]]: """ diff --git a/src/seismometer/configuration/model.py b/src/seismometer/configuration/model.py index b2975ee6..099cf488 100644 --- a/src/seismometer/configuration/model.py +++ b/src/seismometer/configuration/model.py @@ -1,11 +1,10 @@ -import logging from collections import Counter from pathlib import Path from typing import Any, List, Literal, Optional, Union from pydantic import BaseModel, Field, ValidationInfo, field_validator, model_validator -logger = logging.getLogger("seismometer") +from seismometer.core.logger import logger FileLike = str | Path DirLike = str | Path diff --git a/src/seismometer/controls/categorical.py b/src/seismometer/controls/categorical.py index dbe019b7..fa8c314e 100644 --- a/src/seismometer/controls/categorical.py +++ b/src/seismometer/controls/categorical.py @@ -1,4 +1,3 @@ -import logging from collections import defaultdict from typing import List, Optional, Union @@ -15,6 +14,7 @@ from seismometer.controls.styles import BOX_GRID_LAYOUT, html_title from seismometer.core.autometrics import store_call_parameters from seismometer.core.decorators import export +from seismometer.core.logger import logger from seismometer.data import telemetry from seismometer.data.filter import FilterRule from seismometer.html import template @@ -22,8 +22,6 @@ from seismometer.plot.mpl.likert import likert_plot from seismometer.seismogram import Seismogram -logger = logging.getLogger("seismometer") - """ The maximum number of categories allowed in a categorical column. """ diff --git a/src/seismometer/controls/categorical_single_column.py b/src/seismometer/controls/categorical_single_column.py index 02c31751..fea6036d 100644 --- a/src/seismometer/controls/categorical_single_column.py +++ b/src/seismometer/controls/categorical_single_column.py @@ -1,4 +1,3 @@ -import logging from typing import Optional import traitlets @@ -12,14 +11,13 @@ from seismometer.controls.styles import BOX_GRID_LAYOUT, WIDE_LABEL_STYLE, html_title from seismometer.core.autometrics import store_call_parameters from seismometer.core.decorators import export +from seismometer.core.logger import logger from seismometer.data import telemetry from seismometer.html import template from seismometer.plot.mpl._ux import MAX_CATEGORY_SIZE from seismometer.plot.mpl.likert import likert_plot from seismometer.seismogram import Seismogram -logger = logging.getLogger("seismometer") - class OrdinalCategoricalSinglePlot: def __init__( diff --git a/src/seismometer/controls/cohort_comparison.py b/src/seismometer/controls/cohort_comparison.py index 94cff68a..79834cfc 100644 --- a/src/seismometer/controls/cohort_comparison.py +++ b/src/seismometer/controls/cohort_comparison.py @@ -1,17 +1,15 @@ -import logging from functools import partial from typing import Optional from IPython.display import display from ipywidgets import Box, Button, Output, VBox +from seismometer.core.logger import logger from seismometer.data.filter import filter_rule_from_cohort_dictionary from .selection import MultiSelectionListWidget from .styles import BOX_GRID_LAYOUT, WIDE_BUTTON_LAYOUT -logger = logging.getLogger("seismometer") - GENERATE_REPORT = "Generate Report" GENERATING_REPORT = "Generating Report..." diff --git a/src/seismometer/controls/decorators.py b/src/seismometer/controls/decorators.py index eaac8cea..4a0a68ce 100644 --- a/src/seismometer/controls/decorators.py +++ b/src/seismometer/controls/decorators.py @@ -3,7 +3,6 @@ As for all of the utils subpackage, no other custom sub-packages should be referenced. """ import hashlib -import logging import os import shutil from functools import wraps @@ -15,8 +14,7 @@ from ipywidgets import Widget from seismometer.core.decorators import DiskCachedFunction - -logger = logging.getLogger("seismometer") +from seismometer.core.logger import logger def html_load(filepath) -> HTML: diff --git a/src/seismometer/controls/explore.py b/src/seismometer/controls/explore.py index 6b0373b4..5bc4d95c 100644 --- a/src/seismometer/controls/explore.py +++ b/src/seismometer/controls/explore.py @@ -1,4 +1,3 @@ -import logging import os from functools import wraps from typing import Any, Callable, Literal, Optional @@ -14,8 +13,6 @@ from .styles import BOX_GRID_LAYOUT, WIDE_LABEL_STYLE, html_title from .thresholds import MonotonicProbabilitySliderListWidget -logger = logging.getLogger("seismometer") - # region Model Evaluation Header Controls def _combine_scores_checkbox(per_context): diff --git a/src/seismometer/controls/thresholds.py b/src/seismometer/controls/thresholds.py index 6229d2e4..d66351b8 100644 --- a/src/seismometer/controls/thresholds.py +++ b/src/seismometer/controls/thresholds.py @@ -1,4 +1,3 @@ -import logging import operator from collections.abc import Iterable from typing import Optional @@ -10,8 +9,6 @@ from .styles import WIDE_LABEL_STYLE -logger = logging.getLogger("seismometer") - class ProbabilitySliderListWidget(ValueWidget, VBox): """ diff --git a/src/seismometer/core/decorators.py b/src/seismometer/core/decorators.py index c14ca697..40deca6f 100644 --- a/src/seismometer/core/decorators.py +++ b/src/seismometer/core/decorators.py @@ -4,7 +4,6 @@ """ import builtins import hashlib -import logging import os import shutil import sys @@ -16,7 +15,7 @@ import numpy as np import pandas as pd -logger = logging.getLogger("seismometer") +from seismometer.core.logger import logger def export(orig_fn): diff --git a/src/seismometer/core/io.py b/src/seismometer/core/io.py index fffe4aaf..6595a4ba 100644 --- a/src/seismometer/core/io.py +++ b/src/seismometer/core/io.py @@ -1,6 +1,5 @@ import hashlib import json -import logging import os import re import unicodedata @@ -11,8 +10,9 @@ import nbformat import yaml +from seismometer.core.logger import logger + Pathlike = str | Path -logger = logging.getLogger("seismometer") # region io-accessor functions read_ipynb = partial(nbformat.read, as_version=nbformat.current_nbformat) diff --git a/src/seismometer/core/logger.py b/src/seismometer/core/logger.py index 3de66086..a72d4b1a 100644 --- a/src/seismometer/core/logger.py +++ b/src/seismometer/core/logger.py @@ -4,6 +4,10 @@ logging.basicConfig() +# The package logger. Import it from here rather than calling `logging.getLogger("seismometer")` +# in each module, so every module logs under the same name. +logger = logging.getLogger("seismometer") + def init_logger(name: str = "seismometer") -> None: logger = logging.getLogger(name) diff --git a/src/seismometer/data/binary_performance.py b/src/seismometer/data/binary_performance.py index 3400f14c..5c45f569 100644 --- a/src/seismometer/data/binary_performance.py +++ b/src/seismometer/data/binary_performance.py @@ -1,10 +1,10 @@ import itertools -import logging from typing import Any, List, Optional import numpy as np import pandas as pd +from seismometer.core.logger import logger from seismometer.data import pandas_helpers as pdh from seismometer.data.filter import FilterRule from seismometer.seismogram import Seismogram @@ -12,8 +12,6 @@ from . import BinaryClassifierMetricGenerator from .performance import MONOTONIC_METRICS, THRESHOLD -logger = logging.getLogger("seismometer") - GENERATED_COLUMNS = [ "Positives", "Prevalence", diff --git a/src/seismometer/data/loader/event.py b/src/seismometer/data/loader/event.py index 3fac2867..0b4b3c7f 100644 --- a/src/seismometer/data/loader/event.py +++ b/src/seismometer/data/loader/event.py @@ -1,15 +1,12 @@ -import logging - import pandas as pd import seismometer.data.pandas_helpers as pdh from seismometer.configuration import ConfigProvider from seismometer.configuration.model import Event +from seismometer.core.logger import logger from .pipeline import ConfigOnlyHook -logger = logging.getLogger("seismometer") - def get_data_loader(config: ConfigProvider) -> ConfigOnlyHook: """ diff --git a/src/seismometer/data/loader/pipeline.py b/src/seismometer/data/loader/pipeline.py index 8575998d..915ccfff 100644 --- a/src/seismometer/data/loader/pipeline.py +++ b/src/seismometer/data/loader/pipeline.py @@ -1,11 +1,9 @@ -import logging from typing import Callable, Optional, TypeAlias import pandas as pd from seismometer.configuration import ConfigProvider - -logger = logging.getLogger("seismometer") +from seismometer.core.logger import logger ConfigOnlyHook: TypeAlias = Callable[[ConfigProvider], pd.DataFrame] ConfigOnlyHook.__doc__ = """ diff --git a/src/seismometer/data/loader/prediction.py b/src/seismometer/data/loader/prediction.py index c8fe1cde..e14b71a7 100644 --- a/src/seismometer/data/loader/prediction.py +++ b/src/seismometer/data/loader/prediction.py @@ -1,5 +1,4 @@ import csv -import logging import warnings import numpy as np @@ -8,11 +7,10 @@ import seismometer.data.pandas_helpers as pdh from seismometer.configuration import ConfigProvider, ConfigurationError +from seismometer.core.logger import logger from .pipeline import ConfigOnlyHook -logger = logging.getLogger("seismometer") - def get_data_loader(config: ConfigProvider) -> ConfigOnlyHook: """ diff --git a/src/seismometer/data/pandas_helpers.py b/src/seismometer/data/pandas_helpers.py index 5da66899..0e195024 100644 --- a/src/seismometer/data/pandas_helpers.py +++ b/src/seismometer/data/pandas_helpers.py @@ -7,8 +7,7 @@ from seismometer.configuration import ConfigurationError from seismometer.configuration.model import MergeStrategies - -logger = logging.getLogger("seismometer") +from seismometer.core.logger import logger MAXIMUM_COUNT_CATS = 15 diff --git a/src/seismometer/data/performance.py b/src/seismometer/data/performance.py index 3ccfe187..7d474465 100644 --- a/src/seismometer/data/performance.py +++ b/src/seismometer/data/performance.py @@ -1,4 +1,3 @@ -import logging from numbers import Number from pathlib import Path from typing import Callable, Optional, Tuple, Union @@ -7,11 +6,11 @@ import pandas as pd from sklearn.metrics import auc +from seismometer.core.logger import logger + from .confidence import PRConfidenceParam, ROCConfidenceParam, confidence_dict from .decorators import export -logger = logging.getLogger("seismometer") - DEFAULT_RHO = 1 / 3 PathLike = Union[str, Path] diff --git a/src/seismometer/html/template.py b/src/seismometer/html/template.py index 2e83fa47..b05a66d9 100644 --- a/src/seismometer/html/template.py +++ b/src/seismometer/html/template.py @@ -1,12 +1,12 @@ -import logging from typing import Any from IPython.display import HTML, SVG from jinja2 import Environment, PackageLoader, TemplateNotFound +from seismometer.core.logger import logger + FULL_WIDTH_STYLE = "width: 100%; max-width: 1200px;" -logger = logging.getLogger("seismometer") # Initializing Jinja package_loader = PackageLoader("seismometer", "html/resources") diff --git a/src/seismometer/plot/mpl/timeseries.py b/src/seismometer/plot/mpl/timeseries.py index e37b0e07..57821133 100644 --- a/src/seismometer/plot/mpl/timeseries.py +++ b/src/seismometer/plot/mpl/timeseries.py @@ -1,4 +1,3 @@ -import logging from typing import Optional import matplotlib.pyplot as plt @@ -8,8 +7,6 @@ from .decorators import model_plot -logger = logging.getLogger("seismometer") - @model_plot def compare_series( diff --git a/src/seismometer/report/alerting.py b/src/seismometer/report/alerting.py index 94bcd254..31c5a11e 100644 --- a/src/seismometer/report/alerting.py +++ b/src/seismometer/report/alerting.py @@ -29,17 +29,15 @@ show: true """ -import logging from pathlib import Path from typing import Optional import yaml from pydantic import BaseModel, Field +from seismometer.core.logger import logger from seismometer.plot.mpl._ux import alert_colors -logger = logging.getLogger("seismometer") - class ParsedAlert(BaseModel): name: str diff --git a/src/seismometer/report/profiling.py b/src/seismometer/report/profiling.py index fae2a5bb..d4de1d23 100644 --- a/src/seismometer/report/profiling.py +++ b/src/seismometer/report/profiling.py @@ -1,5 +1,4 @@ import json -import logging import os import re from abc import ABC @@ -14,12 +13,12 @@ import seismometer.report from seismometer.core.io import slugify +from seismometer.core.logger import logger from seismometer.data import telemetry from .alerting import AlertConfigProvider, ParsedAlert, ParsedAlertList PROFILING_CONFIG_PATH = _files(seismometer.report) / "report_config.yml" -logger = logging.getLogger("seismometer") def filter_unsupported_columns(df: DataFrame) -> DataFrame: diff --git a/src/seismometer/seismogram.py b/src/seismometer/seismogram.py index 1279e41e..464a1f87 100644 --- a/src/seismometer/seismogram.py +++ b/src/seismometer/seismogram.py @@ -1,5 +1,4 @@ import json -import logging from functools import lru_cache from typing import Optional @@ -8,6 +7,7 @@ from seismometer.configuration import AggregationStrategies, ConfigProvider, MergeStrategies from seismometer.configuration.model import CohortHierarchy, Metric +from seismometer.core.logger import logger from seismometer.core.patterns import Singleton from seismometer.data import pandas_helpers as pdh from seismometer.data import resolve_cohorts @@ -16,7 +16,6 @@ from seismometer.report.alerting import AlertConfigProvider MAXIMUM_NUM_COHORTS = 25 -logger = logging.getLogger("seismometer") class Seismogram(object, metaclass=Singleton): diff --git a/src/seismometer/table/analytics_table.py b/src/seismometer/table/analytics_table.py index 16b69bc6..323561aa 100644 --- a/src/seismometer/table/analytics_table.py +++ b/src/seismometer/table/analytics_table.py @@ -1,4 +1,3 @@ -import logging from enum import Enum from typing import Any, List, Optional @@ -14,6 +13,7 @@ from seismometer.controls.selection import MultiselectDropdownWidget, MultiSelectionListWidget from seismometer.controls.styles import BOX_GRID_LAYOUT, html_title from seismometer.controls.thresholds import MonotonicProbabilitySliderListWidget +from seismometer.core.logger import logger from seismometer.data import pandas_helpers as pdh from seismometer.data import telemetry from seismometer.data.binary_performance import GENERATED_COLUMNS, generate_analytics_data @@ -23,8 +23,6 @@ from .analytics_table_config import COLORING_CONFIG_DEFAULT, AnalyticsTableConfig -logger = logging.getLogger("seismometer") - # region Analytics Table diff --git a/src/seismometer/table/fairness.py b/src/seismometer/table/fairness.py index 6d2c864f..33bd178d 100644 --- a/src/seismometer/table/fairness.py +++ b/src/seismometer/table/fairness.py @@ -1,4 +1,3 @@ -import logging from enum import Enum from typing import Any, Callable, Optional @@ -17,8 +16,6 @@ from seismometer.data.filter import FilterRule from seismometer.data.performance import BinaryClassifierMetricGenerator, MetricGenerator -logger = logging.getLogger("seismometer") - COUNT = "Count" COHORT = "Cohort" CLASS = "Class" diff --git a/tests/core/test_logger.py b/tests/core/test_logger.py new file mode 100644 index 00000000..7a120a2c --- /dev/null +++ b/tests/core/test_logger.py @@ -0,0 +1,15 @@ +import logging + +from seismometer.core.logger import logger + + +def test_logger_is_the_package_logger(): + assert logger is logging.getLogger("seismometer") + + +def test_modules_share_the_package_logger(): + from seismometer.api import plots + from seismometer.data import pandas_helpers + + assert plots.logger is logger + assert pandas_helpers.logger is logger