@@ -19,8 +19,10 @@ def timed_with_status(
1919 Parameters:
2020 - log: enable timing logs (default True)
2121 - log_prefix: prefix; falls back to function name
22- - log_args: names to include in logs (str or list/tuple of str).
23- - log_extra_args: extra arguments to include in logs (dict).
22+ - log_args: names to include in logs (str or list/tuple of str), values are taken from kwargs by name.
23+ - log_extra_args:
24+ - can be a dict: fixed contextual fields that are always attached to logs;
25+ - or a callable: like `fn(*args, **kwargs) -> dict`, used to dynamically generate contextual fields at runtime.
2426 """
2527
2628 if isinstance (log_args , str ):
@@ -51,12 +53,24 @@ def wrapper(*args, **kwargs):
5153 elapsed_ms = (time .perf_counter () - start ) * 1000.0
5254
5355 ctx_parts = []
56+ # 1) Collect parameters from kwargs by name
5457 for key in effective_log_args :
5558 val = kwargs .get (key )
5659 ctx_parts .append (f"{ key } ={ val } " )
5760
58- if log_extra_args :
59- ctx_parts .extend (f"{ key } ={ val } " for key , val in log_extra_args .items ())
61+ # 2) Support log_extra_args as dict or callable, so we can dynamically
62+ # extract values from self or other runtime context
63+ extra_items = {}
64+ try :
65+ if callable (log_extra_args ):
66+ extra_items = log_extra_args (* args , ** kwargs ) or {}
67+ elif isinstance (log_extra_args , dict ):
68+ extra_items = log_extra_args
69+ except Exception as e :
70+ logger .warning (f"[TIMER_WITH_STATUS] log_extra_args callback error: { e !r} " )
71+
72+ if extra_items :
73+ ctx_parts .extend (f"{ key } ={ val } " for key , val in extra_items .items ())
6074
6175 ctx_str = f" [{ ', ' .join (ctx_parts )} ]" if ctx_parts else ""
6276
0 commit comments