diff --git a/cacholote/config.py b/cacholote/config.py index e667242..25f6a18 100644 --- a/cacholote/config.py +++ b/cacholote/config.py @@ -15,6 +15,7 @@ # limitations under the License. from __future__ import annotations +import abc import datetime import logging import pathlib @@ -41,6 +42,14 @@ ) +class Context(abc.ABC): + @abc.abstractmethod + def __init__(self, *args: Any, **kwargs: Any) -> None: ... + + @abc.abstractmethod + def upload_log(self, *args: Any, **kwargs: Any) -> None: ... + + class Settings(pydantic_settings.BaseSettings): use_cache: bool = True cache_db_urlpath: Optional[str] = _DEFAULT_CACHE_DB_URLPATH @@ -61,6 +70,7 @@ class Settings(pydantic_settings.BaseSettings): _DEFAULT_LOGGER ) lock_timeout: Optional[float] = None + context: Optional[Context] = None @pydantic.field_validator("create_engine_kwargs") def validate_create_engine_kwargs( @@ -151,8 +161,10 @@ class set: Note that existing tags are overwritten. return_cache_entry: bool, default: False Whether to return the cache database entry rather than decoded results. - lock_timeout: fload, optional, default: None + lock_timeout: float, optional, default: None Time to wait before raising an error if a cache file is locked. + context: Context, optional, default: None + CADS context for internal use. """ def __init__(self, **kwargs: Any): diff --git a/cacholote/extra_encoders.py b/cacholote/extra_encoders.py index 8a4a47d..5b321e2 100644 --- a/cacholote/extra_encoders.py +++ b/cacholote/extra_encoders.py @@ -111,15 +111,26 @@ def _filesystem_is_local(fs: fsspec.AbstractFileSystem) -> bool: return isinstance(fs, fsspec.get_filesystem_class("file")) +def _kwargs_to_str(**kwargs: Any) -> str: + return " ".join([f"{k}={v}" for k, v in kwargs.items()]) + + @contextlib.contextmanager def _logging_timer(event: str, **kwargs: Any) -> Generator[float, None, None]: logger = config.get().logger + context = config.get().context logger.info(f"start {event}", **kwargs) + if event == "upload" and context is not None: + context.upload_log(f"start {event}. {_kwargs_to_str(**kwargs)}") + tic = time.perf_counter() yield tic toc = time.perf_counter() + kwargs["_".join(event.split() + ["time"])] = toc - tic # elapsed time logger.info(f"end {event}", **kwargs) + if event == "upload" and context is not None: + context.upload_log(f"end {event}. {_kwargs_to_str(**kwargs)}") class FileInfoModel(pydantic.BaseModel):