Skip to content

Instantly share code, notes, and snippets.

@siteshen
Created September 27, 2022 03:04
Show Gist options
  • Save siteshen/486d5ca29545c3989323bfbdc9df4cfe to your computer and use it in GitHub Desktop.
Save siteshen/486d5ca29545c3989323bfbdc9df4cfe to your computer and use it in GitHub Desktop.
Customizable decorator logging the input, output, exception, and cost of a function call.
import functools
import logging
import time
def log_func(
logger: logging.Logger,
*,
log_input=True,
input_level=logging.WARNING,
log_output=False,
output_level=logging.WARNING,
log_timing=False,
timing_level=logging.WARNING,
log_exception=False,
exception_level=logging.ERROR,
timing_timer=time.perf_counter,
):
def wrapper(fn):
@functools.wraps(fn)
def inner(*args, **kwargs):
display_kwargs = tuple(f"{k}={v}" for k, v in kwargs.items())
display_params = ", ".join([str(a) for a in args + display_kwargs])
fn_message = "{}({})".format(fn.__name__, display_params)
if log_timing:
start_time = timing_timer()
if log_input:
logger.log(input_level, f"calling function: {fn_message}")
if log_exception:
try:
rv = fn(*args, **kwargs)
except Exception as e:
logger.log(
exception_level,
f"exception in function: {fn_message} => {e.args}",
exc_info=e,
)
raise e
else:
rv = fn(*args, **kwargs)
if log_output:
logger.log(output_level, f"function called: {fn_message} => {rv}")
if log_timing:
cost = timing_timer() - start_time
logger.log(timing_level, f"function costs: {fn_message} => {cost}")
return rv
return inner
return wrapper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment