Last active
March 11, 2023 17:23
-
-
Save brettschneider/80d8b46d0ea5f6d57832bc86cd296ab0 to your computer and use it in GitHub Desktop.
Decorator to make function log calls for later examination
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from dataclasses import dataclass | |
from datetime import datetime, timedelta | |
from functools import update_wrapper | |
@dataclass(frozen=True) | |
class Call: | |
func: callable | |
call_time: datetime | |
duration: timedelta | |
args: list | |
kwargs: dict | |
result: any = None | |
exception: Exception = None | |
def __repr__(self): | |
fn = self.func.__name__ | |
ct = str(self.call_time) | |
d = str(self.duration) | |
a = self.args | |
kw = self.kwargs | |
r = f"[{str(self.result)}]" if self.result else self.result | |
e = f"[{self.exception}]" if self.exception else self.exception | |
return f"Call(func={fn}, call_time={ct}, duration={d}, " \ | |
f"args={a}, kwargs={kw}, result={r}, exception={e}" | |
class log_calls: | |
"""Make the decorated function log all calls to it""" | |
def __init__(self, func): | |
self.func = func | |
self.calls: list[Call] = [] | |
update_wrapper(self, func) | |
def __call__(self, *args, **kwargs): | |
exc = None | |
start = datetime.utcnow() | |
try: | |
result = self.func(*args, **kwargs) | |
except Exception as ex: | |
exc = ex | |
duration = datetime.utcnow() - start | |
if exc: | |
self.calls.append(Call(self.func, start, duration, args, kwargs, None, exc)) | |
raise exc | |
else: | |
self.calls.append(Call(self.func, start, duration, args, kwargs, result, None)) | |
return result | |
if __name__ == '__main__': | |
@log_calls | |
def greet(name: str): | |
if name in ['Sadie', 'Bently']: | |
raise ValueError("Pets can't be greeted.") | |
return f"Why hello, {name}." | |
@log_calls | |
def farewell(name: str): | |
return f"See you next time {name}." | |
print(f"Making attempts to call\n{'-'*80}") | |
for p in ['Steve', 'Sadie', 'Jen']: | |
try: | |
print(greet(p)) | |
print(farewell(p)) | |
except Exception as ex: | |
print('SOMETHING TERRIBLE HAPPENED!', ex) | |
print(f"\nGreeting call log\n{'-'*80}") | |
for c in greet.calls: | |
print(c) | |
print(f"\nFarewell call log\n{'-'*80}") | |
for c in farewell.calls: | |
print(c) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment