mirror of
https://github.com/capricornxl/ad-password-self-service.git
synced 2025-11-12 13:06:09 +08:00
fix some bugs
This commit is contained in:
149
utils/tracecalls.py
Normal file
149
utils/tracecalls.py
Normal file
@@ -0,0 +1,149 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os.path
|
||||
import re
|
||||
import sys
|
||||
from copy import deepcopy as dcopy
|
||||
from functools import wraps
|
||||
from traceback import format_exc
|
||||
from pwdselfservice.settings import BASE_DIR
|
||||
from pprint import pformat as cformat
|
||||
|
||||
|
||||
NOT_CHECK_CALL_FUNC_NAME = []
|
||||
|
||||
DEBUG_FLAG_FILE_PATH = os.path.join(BASE_DIR, '/log')
|
||||
|
||||
|
||||
class TraceFuncContext:
|
||||
def __init__(self, func_name, logger, log_head='Run function', debug_flag_name=None, verbose=1,
|
||||
pretty=False, indent=0, check_calls=None):
|
||||
self.name = func_name
|
||||
self.logger = logger
|
||||
self.debug_flag_name = debug_flag_name
|
||||
self.log_head = log_head
|
||||
self.verbose = verbose
|
||||
self.pretty = pretty
|
||||
self.indent = indent
|
||||
self.check_calls = check_calls
|
||||
self.copied_verbose = dcopy(verbose)
|
||||
self.is_exit = False
|
||||
self.debug_flag_suffix = '.debug.flag'
|
||||
if self.verbose is not None:
|
||||
self.check_calls = None
|
||||
|
||||
def __enter__(self):
|
||||
sys.settrace(self.get_callbacks)
|
||||
|
||||
def check_debug_flag(self):
|
||||
if self.debug_flag_name:
|
||||
if os.path.isfile(os.path.join(DEBUG_FLAG_FILE_PATH, '{}{}'.format(
|
||||
self.debug_flag_name, self.debug_flag_suffix))):
|
||||
self.verbose = 2
|
||||
else:
|
||||
self.verbose = self.copied_verbose
|
||||
|
||||
@staticmethod
|
||||
def check_in_excludes(func_name):
|
||||
if len(NOT_CHECK_CALL_FUNC_NAME) > 0:
|
||||
regex_gen = r'{0}'.format('|'.join(NOT_CHECK_CALL_FUNC_NAME))
|
||||
re_c = re.compile(regex_gen, flags=re.IGNORECASE)
|
||||
return re_c.search(func_name)
|
||||
return False
|
||||
|
||||
def get_callbacks(self, frame, event, arg=None):
|
||||
self.check_debug_flag()
|
||||
__co_name = frame.f_code.co_name
|
||||
if event != 'call': # Only trace call
|
||||
return
|
||||
if self.verbose:
|
||||
if self.verbose == 1 or self.verbose == 'v':
|
||||
self.check_calls = [self.name]
|
||||
if __co_name not in self.check_calls:
|
||||
return
|
||||
elif self.verbose == 2 or self.verbose == 'vv':
|
||||
if self.check_calls is None:
|
||||
self.check_calls = list(set(frame.f_code.co_names))
|
||||
self.check_calls.append(self.name)
|
||||
if __co_name not in self.check_calls or self.check_in_excludes(__co_name):
|
||||
return
|
||||
else:
|
||||
raise ValueError("UNKNOWN VERBOSE VALUE: support verbose is 1/2 or v/vv...")
|
||||
else:
|
||||
if self.check_calls is None:
|
||||
self.check_calls = [self.name]
|
||||
else:
|
||||
if isinstance(self.check_calls, list):
|
||||
self.check_calls.append(self.name)
|
||||
else:
|
||||
raise ValueError("CHECK CALLS TYPE ERROR: check_calls need a list or tuple with function name.")
|
||||
if __co_name not in self.check_calls:
|
||||
return
|
||||
return self.get_code_line
|
||||
|
||||
def get_code_line(self, frame, event, agr=None):
|
||||
# 正常情况下只有line或return事件才做记录
|
||||
if event not in ['line', 'return']:
|
||||
return
|
||||
__code = frame.f_code
|
||||
__func_name = __code.co_name
|
||||
__line_num = frame.f_lineno
|
||||
__locals = frame.f_locals
|
||||
if __func_name == self.name:
|
||||
self.logger.info(
|
||||
"{4} [{0}] trace detail "
|
||||
"--- {1} {2}, locals as following: {5}{3}{5}".format(__func_name,
|
||||
event,
|
||||
__line_num,
|
||||
cformat(__locals, indent=self.indent)
|
||||
if self.pretty else __locals,
|
||||
self.log_head,
|
||||
'\n' if self.pretty else ''
|
||||
))
|
||||
else:
|
||||
self.logger.info(
|
||||
"{5} [{0}] call [{1}] trace detail "
|
||||
"--- {2} {3}, locals as following: {6}{4}{6}".format(self.name,
|
||||
__func_name,
|
||||
event,
|
||||
__line_num,
|
||||
cformat(__locals, indent=self.indent)
|
||||
if self.pretty else __locals,
|
||||
self.log_head,
|
||||
'\n' if self.pretty else ''
|
||||
))
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
sys.settrace(None)
|
||||
|
||||
|
||||
def decorator_logger(logger, log_head='Run function', debug_flag_name=None, verbose=1, check_calls=None,
|
||||
pretty=False, indent=0):
|
||||
def decorator(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
func_consts = func.__code__.co_consts
|
||||
logger.debug("{4} [{0}] entering trace with --- consts-{3}, args-{1}, kwargs-{2}...".format(
|
||||
func.__name__, args, kwargs, func_consts, log_head))
|
||||
|
||||
with TraceFuncContext(func.__name__, logger,
|
||||
log_head=log_head,
|
||||
debug_flag_name=debug_flag_name,
|
||||
verbose=verbose,
|
||||
check_calls=check_calls,
|
||||
pretty=pretty,
|
||||
indent=indent
|
||||
):
|
||||
try:
|
||||
func_res = func(*args, **kwargs)
|
||||
logger.debug("{4} [{0}] exiting trace with --- consts-{3}, args-{1}, kwargs-{2}...".format(
|
||||
func.__name__, args, kwargs, func_consts, log_head))
|
||||
return func_res
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
"{4} [{0}] has exception, trace with --- consts-{3}, args-{1}, kwargs-{2}. Trackback as "
|
||||
"following: ".format(
|
||||
func.__name__, args, kwargs, func_consts, log_head))
|
||||
logger.error(format_exc())
|
||||
raise e
|
||||
return wrapper
|
||||
return decorator
|
||||
Reference in New Issue
Block a user