Coverage for /Users/buh/.pyenv/versions/3.12.9/envs/es-testbed/lib/python3.12/site-packages/es_testbed/debug.py: 100%
21 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-21 20:56 -0600
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-21 20:56 -0600
1"""Module for tiered debugging with a global TieredDebug instance.
3Provides a global `TieredDebug` instance and a `begin_end` decorator to
4log function entry and exit at specified debug levels. Designed for use
5in projects like ElasticKeeper and ElasticCheckpoint to trace function
6execution with configurable stack levels.
8Examples:
9 >>> from tiered_debug.debug import debug, begin_end
10 >>> debug.level = 3
11 >>> import logging
12 >>> debug.add_handler(logging.StreamHandler())
13 >>> @begin_end(debug, begin=2, end=3, stacklevel=2, extra={"func": "test"})
14 ... def example():
15 ... return "Test"
16 >>> example()
17 'Test'
18"""
20from functools import wraps
21from typing import Any, Dict, Optional
23from tiered_debug import TieredDebug
25DEFAULT_BEGIN = 2
26"""Default debug level for BEGIN messages."""
28DEFAULT_END = 3
29"""Default debug level for END messages."""
31debug = TieredDebug(level=1, stacklevel=3)
32"""Global TieredDebug instance with default level 1 and stacklevel 3."""
35def begin_end(
36 debug_obj: Optional[TieredDebug] = None,
37 begin: int = DEFAULT_BEGIN,
38 end: int = DEFAULT_END,
39 stacklevel: int = 2,
40 extra: Optional[Dict[str, Any]] = None,
41):
42 """Decorator to log function entry and exit at specified debug levels.
44 Logs "BEGIN CALL" at the `begin` level and "END CALL" at the `end`
45 level using the provided or global debug instance. Adjusts the
46 stacklevel by 1 to report the correct caller.
48 Args:
49 debug_obj: TieredDebug instance to use (default: global debug).
50 begin: Debug level for BEGIN message (1-5, default 2). (int)
51 end: Debug level for END message (1-5, default 3). (int)
52 stacklevel: Stack level for reporting (1-9, default 2). (int)
53 extra: Extra metadata dictionary (default None). (Dict[str, Any])
55 Returns:
56 Callable: Decorated function with logging.
58 Examples:
59 >>> debug.level = 3
60 >>> import logging
61 >>> debug.add_handler(logging.StreamHandler())
62 >>> @begin_end(debug, begin=2, end=3)
63 ... def test_func():
64 ... return "Result"
65 >>> test_func()
66 'Result'
67 """
68 debug_instance = debug_obj if debug_obj is not None else debug
70 def decorator(func):
71 @wraps(func)
72 def wrapper(*args, **kwargs):
73 effective_stacklevel = stacklevel + 1
74 debug_instance.log(
75 begin,
76 f"BEGIN CALL: {func.__name__}()",
77 stacklevel=effective_stacklevel,
78 extra=extra,
79 )
80 result = func(*args, **kwargs)
81 debug_instance.log(
82 end,
83 f"END CALL: {func.__name__}()",
84 stacklevel=effective_stacklevel,
85 extra=extra,
86 )
87 return result
89 return wrapper
91 return decorator