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

feat: Developers can now customize the default logging configuration for their taps/targets by adding default_logging.yml to their package #2432

18 changes: 18 additions & 0 deletions docs/implementation/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,21 @@ This will send metrics to a `metrics.log`:
2022-09-29 00:48:53,302 INFO METRIC: {"metric_type": "timer", "metric": "sync_duration", "value": 0.5258760452270508, "tags": {"stream": "countries", "context": {}, "status": "succeeded"}}
2022-09-29 00:48:53,303 INFO METRIC: {"metric_type": "counter", "metric": "record_count", "value": 250, "tags": {"stream": "countries", "context": {}}}
```

## For package developers

If you're developing a tap or target package and would like to customize its logging configuration, you can put a `default_loggging.yml` file in the package root to set the default logging configuration for your package. This file will be used if the `SINGER_SDK_LOG_CONFIG` environment variable is not set:

```
.
├── README.md
├── poetry.lock
├── pyproject.toml
└── tap_example
    ├── __init__.py
    ├── __main__.py
    ├── default_logging.yml # <-- This file will be used if SINGER_SDK_LOG_CONFIG is not set
    ├── client.py
    ├── streams.py
    └── tap.py
```
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ backports-datetime-fromisoformat = { version = ">=2.0.1", python = "<3.11" }
click = "~=8.0"
fs = ">=2.4.16"
importlib-metadata = {version = "<9.0.0", python = "<3.12"}
importlib-resources = {version = ">=5.12.0,!=6.2.0,!=6.3.0,!=6.3.1", python = "<3.9"}
importlib-resources = {version = ">=5.12.0,!=6.2.0,!=6.3.0,!=6.3.1", python = "<3.10"}
inflection = ">=0.5.1"
joblib = ">=1.3.0"
jsonpath-ng = ">=1.5.3"
Expand Down
2 changes: 1 addition & 1 deletion singer_sdk/helpers/_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from singer_sdk.helpers._compat import Traversable

if sys.version_info < (3, 9):
if sys.version_info < (3, 10):
import importlib_resources
else:
import importlib.resources as importlib_resources
Expand Down
16 changes: 11 additions & 5 deletions singer_sdk/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,23 +394,29 @@ def _load_yaml_logging_config(path: Traversable | Path) -> t.Any: # noqa: ANN40
return yaml.safe_load(f)


def _get_default_config() -> t.Any: # noqa: ANN401
def _get_default_config_path(package: str) -> Traversable:
"""Get a logging configuration.

Args:
package: The package name to get the logging configuration for.

Returns:
A logging configuration.
"""
log_config_path = get_package_files("singer_sdk").joinpath("default_logging.yml")
return _load_yaml_logging_config(log_config_path)
filename = "default_logging.yml"
path = get_package_files(package) / filename
return path if path.is_file() else get_package_files("singer_sdk") / filename


def _setup_logging(config: t.Mapping[str, t.Any]) -> None:
def _setup_logging(config: t.Mapping[str, t.Any], *, package: str) -> None:
"""Setup logging.

Args:
package: The package name to get the logging configuration for.
config: A plugin configuration dictionary.
"""
logging.config.dictConfig(_get_default_config())
path = _get_default_config_path(package)
logging.config.dictConfig(_load_yaml_logging_config(path))

config = config or {}
metrics_log_level = config.get(METRICS_LOG_LEVEL_SETTING, "INFO").upper()
Expand Down
5 changes: 4 additions & 1 deletion singer_sdk/plugin_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,10 @@ def __init__(
if self._is_secret_config(k):
config_dict[k] = SecretString(v)
self._config = config_dict
metrics._setup_logging(self.config) # noqa: SLF001
metrics._setup_logging( # noqa: SLF001
self.config,
package=self.__module__.split(".", maxsplit=1)[0],
)
self.metrics_logger = metrics.get_metrics_logger()

self._validate_config(raise_errors=validate_config)
Expand Down
Loading