Skip to content

Commit 3d79a4e

Browse files
committed
add counter
1 parent 943b873 commit 3d79a4e

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

src/zarr/store/logging.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
import inspect
44
import logging
55
import time
6+
from collections import defaultdict
67
from contextlib import contextmanager
78
from typing import TYPE_CHECKING
89

9-
from zarr.abc.store import Store
10+
from zarr.abc.store import AccessMode, Store
1011

1112
if TYPE_CHECKING:
1213
from collections.abc import AsyncGenerator, Generator
@@ -16,6 +17,7 @@
1617

1718
class LoggingStore(Store):
1819
_store: Store
20+
counter: defaultdict[str, int]
1921

2022
def __init__(
2123
self,
@@ -24,6 +26,7 @@ def __init__(
2426
log_handler: logging.Handler | None = None,
2527
):
2628
self._store = store
29+
self.counter = defaultdict(int)
2730

2831
self._configure_logger(log_level, log_handler)
2932

@@ -44,16 +47,19 @@ def _default_handler(self) -> logging.Handler:
4447
"""Define a default log handler"""
4548
handler = logging.StreamHandler()
4649
handler.setLevel(self.log_level)
47-
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
48-
handler.setFormatter(formatter)
50+
handler.setFormatter(
51+
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
52+
)
4953
return handler
5054

5155
@contextmanager
5256
def log(self) -> Generator[None, None, None]:
53-
op = f"{type(self._store).__name__}.{inspect.stack()[2].function}"
57+
method = inspect.stack()[2].function
58+
op = f"{type(self._store).__name__}.{method}"
5459
self.logger.info(f"Calling {op}")
5560
start_time = time.time()
5661
try:
62+
self.counter[method] += 1
5763
yield
5864
finally:
5965
end_time = time.time()
@@ -79,6 +85,16 @@ def supports_listing(self) -> bool:
7985
with self.log():
8086
return self._store.supports_listing
8187

88+
@property
89+
def _mode(self) -> AccessMode: # type: ignore[override]
90+
with self.log():
91+
return self._store._mode
92+
93+
@property
94+
def _is_open(self) -> bool: # type: ignore[override]
95+
with self.log():
96+
return self._store._is_open
97+
8298
async def empty(self) -> bool:
8399
with self.log():
84100
return await self._store.empty()

tests/v3/test_store/test_logging.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import pytest
66

7+
import zarr
78
from zarr.core.buffer import default_buffer_prototype
89
from zarr.store.logging import LoggingStore
910

@@ -33,3 +34,17 @@ async def test_logging_store(store: Store, caplog) -> None:
3334
assert str(store) in tup[0]
3435
assert f"Calling {type(store).__name__}.list" in caplog.record_tuples[0][2]
3536
assert f"Finished {type(store).__name__}.list" in caplog.record_tuples[1][2]
37+
38+
39+
@pytest.mark.parametrize("store", ("local", "memory", "zip"), indirect=["store"])
40+
async def test_logging_store_counter(store: Store) -> None:
41+
wrapped = LoggingStore(store=store, log_level="DEBUG")
42+
43+
arr = zarr.create(shape=(10,), store=wrapped, overwrite=True)
44+
arr[:] = 1
45+
46+
assert wrapped.counter["set"] == 2
47+
assert wrapped.counter["get"] == 0 # 1 if overwrite=False
48+
assert wrapped.counter["list"] == 0
49+
assert wrapped.counter["list_dir"] == 0
50+
assert wrapped.counter["list_prefix"] == 0

0 commit comments

Comments
 (0)