Coverage for backend/pinch_service/OpenPinch/src/utils/decorators.py: 72%
35 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
1import logging
2from time import perf_counter as timer
3from functools import wraps
4import atexit
5from collections import defaultdict
6from ..lib import config
8# Configure logging to both console and file
9logging.basicConfig(
10 level=logging.INFO,
11 format='%(asctime)s - %(levelname)s - %(message)s',
12 handlers=[
13 logging.FileHandler("timing.log"),
14 logging.StreamHandler()
15 ]
16)
18logger = logging.getLogger(__name__)
20_function_stats = defaultdict(lambda: {"count": 0, "total_time": 0.0})
22def timing_decorator(func=None, *, activate_overide=False):
23 """
24 Decorator to measure execution time and track per-function totals.
25 Supports both @timing_decorator and @timing_decorator(activate_overide=True)
26 """
28 def decorator(f):
29 @wraps(f)
30 def wrapper(*args, **kwargs):
31 if not (config.ACTIVATE_TIMING or activate_overide): 31 ↛ 32line 31 didn't jump to line 32 because the condition on line 31 was never true
32 return f(*args, **kwargs)
34 start_time = timer()
35 result = f(*args, **kwargs)
36 end_time = timer()
37 exec_time = end_time - start_time
39 stats = _function_stats[f.__name__]
40 stats["count"] += 1
41 stats["total_time"] += exec_time
43 if config.LOG_TIMING: 43 ↛ 44line 43 didn't jump to line 44 because the condition on line 43 was never true
44 logger.info(f"Function '{f.__name__}' executed in {exec_time:.6f} seconds.")
46 return result
47 return wrapper
49 # Handle both @timing_decorator and @timing_decorator(activate_overide=True)
50 if callable(func): 50 ↛ 52line 50 didn't jump to line 52 because the condition on line 50 was always true
51 return decorator(func)
52 return decorator
54@atexit.register
55def print_summary():
56 logger.info("==== Execution Time Summary ====")
57 for func_name, stats in _function_stats.items():
58 avg_time = stats["total_time"] / stats["count"]
59 logger.info(
60 f"{func_name}: {stats['count']} calls, "
61 f"total {stats['total_time']:.6f}s, "
62 f"average {avg_time:.6f}s"
63 )