Skip to content

Commit b830394

Browse files
authored
Added logging root directory (#190)
Provides workaround for issue: #137 BUG=b/382252531
1 parent dce4c5e commit b830394

File tree

3 files changed

+75
-23
lines changed

3 files changed

+75
-23
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,14 +263,14 @@ Configure hatch to create virtual env in project folder.
263263
hatch config set dirs.env.virtual .env
264264
```
265265

266-
After, create all the python environments needed by running `hatch -e all run tests`.
266+
After, create all the python environments needed by running `hatch tests --all`.
267267

268268
Finally, configure vscode to use one of the selected environments:
269269
`cmd + shift + p` -> `python: Select Interpreter` -> Pick one of the folders in `./.env`
270270

271271
## Support
272272

273-
The kagglehub library has configured automatic logging which is stored in a log folder. The log destination is resolved via the [os.path.expanduser](https://docs.python.org/3/library/os.path.html#os.path.expanduser)
273+
The kagglehub library has configured automatic logging for console. For file based logging, setting the `KAGGLE_LOGGING_ENABLED=1` environment variable will output logs to a directory. The default log destination is resolved via the [os.path.expanduser](https://docs.python.org/3/library/os.path.html#os.path.expanduser)
274274

275275
The table below contains possible locations:
276276
| os | log path |
@@ -279,4 +279,6 @@ The table below contains possible locations:
279279
| linux | ~/.kaggle/logs/kagglehub.log |
280280
| windows | C:\Users\\%USERNAME%\\.kaggle\logs\kagglehub.log |
281281

282+
If needed, the root log directory can be overriden using the following environment variable: `KAGGLE_LOGGING_ROOT_DIR`
283+
282284
Please include the log to help troubleshoot issues.

src/kagglehub/logger.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import os
23
import sys
34
from logging import LogRecord
45
from logging.handlers import RotatingFileHandler
@@ -7,6 +8,9 @@
78

89
from kagglehub.config import get_log_verbosity
910

11+
KAGGLE_LOGGING_ROOT_DIR_ENV_VAR_NAME = "KAGGLE_LOGGING_ROOT_DIR"
12+
KAGGLE_LOGGING_ENABLED_ENV_VAR_NAME = "KAGGLE_LOGGING_ENABLED"
13+
1014
_FILE_BLOCK_KEY = "kaggle_file"
1115
EXTRA_FILE_BLOCK = {"block": _FILE_BLOCK_KEY}
1216
_CONSOLE_BLOCK_KEY = "console"
@@ -35,19 +39,21 @@ def _configure_logger(log_dir: Optional[Path] = None) -> None:
3539
handler = library_logger.handlers.pop()
3640
while handler.filters:
3741
handler.filters.pop()
38-
log_dir = Path.home() / ".kaggle" / "logs" if log_dir is None else log_dir
39-
log_dir.mkdir(exist_ok=True, parents=True)
40-
file_handler = RotatingFileHandler(
41-
str(log_dir / "kagglehub.log"), maxBytes=1024 * 1024 * 5, backupCount=5, delay=True
42-
)
43-
file_handler.addFilter(_block_logrecord_factory([_FILE_BLOCK_KEY]))
44-
formatter = logging.Formatter(
45-
"%(asctime)s - %(name)s - %(levelname)s - %(threadName)s - %(funcName)s - %(message)s"
46-
)
47-
file_handler.setFormatter(formatter)
48-
file_handler.setLevel(logging.DEBUG)
49-
library_logger.addHandler(file_handler)
50-
42+
logging_enabled = os.environ.get(KAGGLE_LOGGING_ENABLED_ENV_VAR_NAME, False)
43+
if str(logging_enabled).lower() in ("true", 1):
44+
log_root_dir = Path(os.environ.get(KAGGLE_LOGGING_ROOT_DIR_ENV_VAR_NAME, Path.home()))
45+
log_dir = log_root_dir / ".kaggle" / "logs" if log_dir is None else log_dir
46+
log_dir.mkdir(exist_ok=True, parents=True)
47+
file_handler = RotatingFileHandler(
48+
str(log_dir / "kagglehub.log"), maxBytes=1024 * 1024 * 5, backupCount=5, delay=True
49+
)
50+
file_handler.addFilter(_block_logrecord_factory([_FILE_BLOCK_KEY]))
51+
formatter = logging.Formatter(
52+
"%(asctime)s - %(name)s - %(levelname)s - %(threadName)s - %(funcName)s - %(message)s"
53+
)
54+
file_handler.setFormatter(formatter)
55+
file_handler.setLevel(logging.DEBUG)
56+
library_logger.addHandler(file_handler)
5157
sh = logging.StreamHandler(sys.stdout)
5258
sh.addFilter(_block_logrecord_factory([_CONSOLE_BLOCK_KEY]))
5359
sh.setLevel(get_log_verbosity())

tests/test_logger.py

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import logging
2+
import os
23
import unittest
34
from contextlib import redirect_stdout
45
from io import StringIO
56
from pathlib import Path
67
from tempfile import TemporaryDirectory
8+
from unittest import mock
79

810
from kagglehub.logger import (
911
_CONSOLE_BLOCK_KEY,
1012
EXTRA_CONSOLE_BLOCK,
1113
EXTRA_FILE_BLOCK,
14+
KAGGLE_LOGGING_ENABLED_ENV_VAR_NAME,
15+
KAGGLE_LOGGING_ROOT_DIR_ENV_VAR_NAME,
1216
_block_logrecord_factory,
1317
_configure_logger,
1418
)
@@ -64,14 +68,54 @@ def test_kagglehub_child_console_filter_discards_logrecord(self) -> None:
6468

6569
def test_kagglehub_file_filter(self) -> None:
6670
with TemporaryDirectory() as f:
67-
log_path = Path(f) / "testasdfasf-log"
68-
_configure_logger(log_path)
69-
logger = logging.getLogger("kagglehub")
70-
logger.info("HIDE", extra={**EXTRA_FILE_BLOCK})
71-
logger.info("SHOW")
72-
text = (log_path / "kagglehub.log").read_text()
73-
self.assertRegex(text, "^.*SHOW.*$")
74-
self.assertRegex(text, "^(?!.*HIDE).*$")
71+
with mock.patch.dict(os.environ, {KAGGLE_LOGGING_ENABLED_ENV_VAR_NAME: str(True)}):
72+
log_path = Path(f) / "testasdfasf-log"
73+
_configure_logger(log_path)
74+
logger = logging.getLogger("kagglehub")
75+
logger.info("HIDE", extra={**EXTRA_FILE_BLOCK})
76+
logger.info("SHOW")
77+
text = (log_path / "kagglehub.log").read_text()
78+
self.assertRegex(text, "^.*SHOW.*$")
79+
self.assertRegex(text, "^(?!.*HIDE).*$")
80+
81+
def test_log_env_variable_and_enabled(self) -> None:
82+
with TemporaryDirectory() as d:
83+
root_log_dir = Path(d) / "log"
84+
with mock.patch.dict(
85+
os.environ,
86+
{
87+
KAGGLE_LOGGING_ROOT_DIR_ENV_VAR_NAME: str(root_log_dir),
88+
KAGGLE_LOGGING_ENABLED_ENV_VAR_NAME: str(True),
89+
},
90+
):
91+
_configure_logger()
92+
logger = logging.getLogger("kagglehub")
93+
logger.info("goose")
94+
self.assertTrue((Path(root_log_dir) / ".kaggle/logs/kagglehub.log").exists(), "log file expected")
95+
96+
def test_log_disabled(self) -> None:
97+
with TemporaryDirectory() as d:
98+
log_dir = Path(d) / "log"
99+
with mock.patch.dict(
100+
os.environ,
101+
{KAGGLE_LOGGING_ENABLED_ENV_VAR_NAME: str(False)},
102+
):
103+
_configure_logger(log_dir)
104+
logger = logging.getLogger("kagglehub")
105+
logger.info("goose")
106+
self.assertFalse((log_dir / "kagglehub.log").exists(), "no log file expected")
107+
108+
def test_log_enabled(self) -> None:
109+
with TemporaryDirectory() as d:
110+
log_dir = Path(d) / "log"
111+
with mock.patch.dict(
112+
os.environ,
113+
{KAGGLE_LOGGING_ENABLED_ENV_VAR_NAME: str(True)},
114+
):
115+
_configure_logger(log_dir)
116+
logger = logging.getLogger("kagglehub")
117+
logger.info("goose")
118+
self.assertTrue((log_dir / "kagglehub.log").exists(), "log file expected")
75119

76120

77121
if __name__ == "__main__":

0 commit comments

Comments
 (0)