mindstudio-probe 1.2.1__py3-none-any.whl → 1.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. {mindstudio_probe-1.2.1.dist-info → mindstudio_probe-1.3.0.dist-info}/METADATA +3 -3
  2. {mindstudio_probe-1.2.1.dist-info → mindstudio_probe-1.3.0.dist-info}/RECORD +168 -150
  3. msprobe/README.md +27 -22
  4. msprobe/core/common/const.py +129 -60
  5. msprobe/core/common/decorator.py +50 -0
  6. msprobe/core/common/exceptions.py +3 -1
  7. msprobe/core/common/file_utils.py +25 -2
  8. msprobe/core/common/inplace_ops.yaml +1 -0
  9. msprobe/core/common/utils.py +43 -33
  10. msprobe/core/compare/acc_compare.py +43 -74
  11. msprobe/core/compare/check.py +2 -6
  12. msprobe/core/compare/highlight.py +2 -0
  13. msprobe/core/compare/layer_mapping/data_scope_parser.py +1 -1
  14. msprobe/core/compare/layer_mapping/layer_mapping.py +2 -1
  15. msprobe/core/compare/merge_result/merge_result.py +16 -9
  16. msprobe/core/compare/merge_result/utils.py +81 -0
  17. msprobe/core/compare/multiprocessing_compute.py +19 -12
  18. msprobe/core/compare/npy_compare.py +30 -12
  19. msprobe/core/compare/utils.py +30 -10
  20. msprobe/core/data_dump/api_registry.py +176 -0
  21. msprobe/core/data_dump/data_collector.py +58 -13
  22. msprobe/core/data_dump/data_processor/base.py +94 -10
  23. msprobe/core/data_dump/data_processor/factory.py +3 -0
  24. msprobe/core/data_dump/data_processor/mindspore_processor.py +33 -33
  25. msprobe/core/data_dump/data_processor/pytorch_processor.py +99 -18
  26. msprobe/core/data_dump/json_writer.py +61 -40
  27. msprobe/core/grad_probe/constant.py +1 -0
  28. msprobe/core/grad_probe/grad_compare.py +1 -1
  29. msprobe/core/overflow_check/abnormal_scene.py +2 -0
  30. msprobe/docs/01.installation.md +27 -1
  31. msprobe/docs/02.config_introduction.md +27 -23
  32. msprobe/docs/03.config_examples.md +24 -0
  33. msprobe/docs/05.data_dump_PyTorch.md +103 -16
  34. msprobe/docs/06.data_dump_MindSpore.md +76 -32
  35. msprobe/docs/07.accuracy_checker_PyTorch.md +11 -1
  36. msprobe/docs/08.accuracy_checker_online_PyTorch.md +3 -1
  37. msprobe/docs/09.accuracy_checker_MindSpore.md +5 -3
  38. msprobe/docs/10.accuracy_compare_PyTorch.md +59 -33
  39. msprobe/docs/11.accuracy_compare_MindSpore.md +40 -16
  40. msprobe/docs/12.overflow_check_PyTorch.md +3 -1
  41. msprobe/docs/13.overflow_check_MindSpore.md +4 -2
  42. msprobe/docs/14.data_parse_PyTorch.md +1 -7
  43. msprobe/docs/18.online_dispatch.md +1 -1
  44. msprobe/docs/19.monitor.md +332 -273
  45. msprobe/docs/21.visualization_PyTorch.md +42 -13
  46. msprobe/docs/22.visualization_MindSpore.md +43 -13
  47. msprobe/docs/23.generate_operator_PyTorch.md +9 -9
  48. msprobe/docs/27.dump_json_instruction.md +301 -27
  49. msprobe/docs/28.debugger_save_instruction.md +94 -0
  50. msprobe/docs/28.kernel_dump_MindSpore.md +69 -0
  51. msprobe/docs/29.data_dump_MSAdapter.md +229 -0
  52. msprobe/docs/30.overflow_check_MSAdapter.md +31 -0
  53. msprobe/docs/FAQ.md +3 -11
  54. msprobe/docs/img/compare_result.png +0 -0
  55. msprobe/docs/img/merge_result.png +0 -0
  56. msprobe/docs/img/monitor/step_count_per_record.png +0 -0
  57. msprobe/docs/img/visualization/vis_browser_1.png +0 -0
  58. msprobe/docs/img/visualization/vis_match_info.png +0 -0
  59. msprobe/docs/img/visualization/vis_precision_info.png +0 -0
  60. msprobe/docs/img/visualization/vis_search_info.png +0 -0
  61. msprobe/docs/img/visualization/vis_show_info.png +0 -0
  62. msprobe/docs/img/visualization/vis_showcase.png +0 -0
  63. msprobe/docs/img/visualization/vis_unmatch_info.png +0 -0
  64. msprobe/mindspore/__init__.py +4 -2
  65. msprobe/mindspore/api_accuracy_checker/api_accuracy_checker.py +32 -7
  66. msprobe/mindspore/api_accuracy_checker/api_runner.py +70 -22
  67. msprobe/mindspore/api_accuracy_checker/base_compare_algorithm.py +2 -1
  68. msprobe/mindspore/api_accuracy_checker/bench_functions/flash_attention_score.py +602 -0
  69. msprobe/mindspore/api_accuracy_checker/bench_functions/fusion_operator.py +41 -0
  70. msprobe/mindspore/api_accuracy_checker/compute_element.py +47 -1
  71. msprobe/mindspore/api_accuracy_checker/data_manager.py +2 -1
  72. msprobe/mindspore/api_accuracy_checker/multi_api_accuracy_checker.py +2 -1
  73. msprobe/mindspore/api_accuracy_checker/torch_mindtorch_importer.py +130 -0
  74. msprobe/mindspore/api_accuracy_checker/type_mapping.py +24 -1
  75. msprobe/mindspore/api_accuracy_checker/utils.py +6 -1
  76. msprobe/mindspore/common/const.py +61 -0
  77. msprobe/mindspore/common/utils.py +48 -18
  78. msprobe/mindspore/compare/ms_compare.py +27 -19
  79. msprobe/mindspore/compare/ms_graph_compare.py +6 -5
  80. msprobe/mindspore/debugger/debugger_config.py +31 -6
  81. msprobe/mindspore/debugger/precision_debugger.py +45 -14
  82. msprobe/mindspore/dump/dump_tool_factory.py +5 -3
  83. msprobe/mindspore/dump/hook_cell/api_register.py +142 -0
  84. msprobe/mindspore/dump/hook_cell/hook_cell.py +9 -10
  85. msprobe/mindspore/dump/hook_cell/support_wrap_ops.yaml +24 -26
  86. msprobe/mindspore/dump/jit_dump.py +21 -15
  87. msprobe/mindspore/dym_loader/hook_dynamic_loader.cc +22 -56
  88. msprobe/mindspore/dym_loader/hook_dynamic_loader.h +0 -1
  89. msprobe/mindspore/free_benchmark/api_pynative_self_check.py +10 -6
  90. msprobe/mindspore/free_benchmark/perturbation/perturbation_factory.py +4 -2
  91. msprobe/mindspore/free_benchmark/self_check_tool_factory.py +6 -3
  92. msprobe/mindspore/grad_probe/global_context.py +2 -0
  93. msprobe/mindspore/grad_probe/grad_analyzer.py +2 -1
  94. msprobe/mindspore/grad_probe/hook.py +2 -4
  95. msprobe/mindspore/monitor/anomaly_detect.py +404 -0
  96. msprobe/mindspore/monitor/distributed/__init__.py +0 -0
  97. msprobe/mindspore/monitor/distributed/distributed_ops.yaml +15 -0
  98. msprobe/mindspore/monitor/distributed/stack_blacklist.yaml +5 -0
  99. msprobe/mindspore/monitor/distributed/wrap_distributed.py +300 -0
  100. msprobe/mindspore/monitor/features.py +63 -0
  101. msprobe/mindspore/monitor/module_hook.py +873 -0
  102. msprobe/mindspore/monitor/module_spec_verifier.py +94 -0
  103. msprobe/mindspore/monitor/utils.py +309 -0
  104. msprobe/mindspore/ms_config.py +8 -2
  105. msprobe/mindspore/overflow_check/overflow_check_tool_factory.py +5 -3
  106. msprobe/mindspore/service.py +114 -34
  107. msprobe/pytorch/__init__.py +0 -1
  108. msprobe/pytorch/api_accuracy_checker/compare/api_precision_compare.py +3 -6
  109. msprobe/pytorch/api_accuracy_checker/generate_op_script/op_generator.py +12 -7
  110. msprobe/pytorch/api_accuracy_checker/generate_op_script/operator_replication.template +2 -2
  111. msprobe/pytorch/api_accuracy_checker/run_ut/multi_run_ut.py +4 -5
  112. msprobe/pytorch/api_accuracy_checker/run_ut/run_overflow_check.py +5 -5
  113. msprobe/pytorch/api_accuracy_checker/run_ut/run_ut.py +25 -6
  114. msprobe/pytorch/api_accuracy_checker/run_ut/run_ut_utils.py +28 -19
  115. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/attl.py +3 -1
  116. msprobe/pytorch/bench_functions/apply_adam.py +215 -0
  117. msprobe/pytorch/bench_functions/group_norm_silu.py +27 -0
  118. msprobe/pytorch/{parse.py → bench_functions/mish.py} +6 -4
  119. msprobe/pytorch/bench_functions/moe_gating_top_k_softmax.py +50 -0
  120. msprobe/pytorch/bench_functions/sort_v2.py +21 -0
  121. msprobe/pytorch/common/utils.py +97 -4
  122. msprobe/pytorch/debugger/debugger_config.py +19 -9
  123. msprobe/pytorch/debugger/precision_debugger.py +24 -1
  124. msprobe/pytorch/dump/module_dump/module_dump.py +4 -3
  125. msprobe/pytorch/dump/module_dump/module_processer.py +21 -35
  126. msprobe/pytorch/free_benchmark/common/utils.py +1 -1
  127. msprobe/pytorch/free_benchmark/compare/single_benchmark.py +1 -1
  128. msprobe/pytorch/free_benchmark/perturbed_layers/npu/add_noise.py +3 -3
  129. msprobe/pytorch/free_benchmark/perturbed_layers/npu/bit_noise.py +3 -3
  130. msprobe/pytorch/free_benchmark/perturbed_layers/npu/change_value.py +1 -1
  131. msprobe/pytorch/free_benchmark/perturbed_layers/npu/improve_precision.py +1 -1
  132. msprobe/pytorch/free_benchmark/result_handlers/check_handler.py +1 -1
  133. msprobe/pytorch/function_factory.py +8 -2
  134. msprobe/pytorch/grad_probe/grad_monitor.py +2 -2
  135. msprobe/pytorch/hook_module/api_register.py +131 -0
  136. msprobe/pytorch/hook_module/hook_module.py +19 -14
  137. msprobe/pytorch/hook_module/register_optimizer_hook.py +2 -1
  138. msprobe/pytorch/hook_module/support_wrap_ops.yaml +173 -75
  139. msprobe/pytorch/monitor/anomaly_detect.py +14 -29
  140. msprobe/pytorch/monitor/csv2tb.py +18 -14
  141. msprobe/pytorch/monitor/distributed/wrap_distributed.py +8 -2
  142. msprobe/pytorch/monitor/module_hook.py +238 -193
  143. msprobe/pytorch/monitor/module_metric.py +9 -6
  144. msprobe/pytorch/monitor/optimizer_collect.py +100 -67
  145. msprobe/pytorch/monitor/unittest/test_monitor.py +1 -1
  146. msprobe/pytorch/monitor/utils.py +76 -44
  147. msprobe/pytorch/online_dispatch/compare.py +0 -2
  148. msprobe/pytorch/online_dispatch/dispatch.py +9 -0
  149. msprobe/pytorch/online_dispatch/dump_compare.py +3 -0
  150. msprobe/pytorch/online_dispatch/utils.py +3 -0
  151. msprobe/pytorch/parse_tool/lib/interactive_cli.py +1 -6
  152. msprobe/pytorch/parse_tool/lib/utils.py +2 -1
  153. msprobe/pytorch/pt_config.py +30 -29
  154. msprobe/pytorch/service.py +114 -32
  155. msprobe/visualization/builder/graph_builder.py +75 -10
  156. msprobe/visualization/builder/msprobe_adapter.py +7 -6
  157. msprobe/visualization/compare/graph_comparator.py +42 -38
  158. msprobe/visualization/compare/mode_adapter.py +0 -19
  159. msprobe/visualization/graph/base_node.py +11 -3
  160. msprobe/visualization/graph/distributed_analyzer.py +71 -3
  161. msprobe/visualization/graph/graph.py +0 -11
  162. msprobe/visualization/graph/node_op.py +4 -3
  163. msprobe/visualization/graph_service.py +4 -5
  164. msprobe/visualization/utils.py +12 -35
  165. msprobe/mindspore/dump/hook_cell/api_registry.py +0 -205
  166. msprobe/mindspore/dump/hook_cell/wrap_api.py +0 -212
  167. msprobe/pytorch/hook_module/api_registry.py +0 -166
  168. msprobe/pytorch/hook_module/wrap_distributed.py +0 -75
  169. msprobe/pytorch/hook_module/wrap_functional.py +0 -66
  170. msprobe/pytorch/hook_module/wrap_npu_custom.py +0 -85
  171. msprobe/pytorch/hook_module/wrap_tensor.py +0 -69
  172. msprobe/pytorch/hook_module/wrap_torch.py +0 -84
  173. msprobe/pytorch/hook_module/wrap_vf.py +0 -60
  174. {mindstudio_probe-1.2.1.dist-info → mindstudio_probe-1.3.0.dist-info}/LICENSE +0 -0
  175. {mindstudio_probe-1.2.1.dist-info → mindstudio_probe-1.3.0.dist-info}/WHEEL +0 -0
  176. {mindstudio_probe-1.2.1.dist-info → mindstudio_probe-1.3.0.dist-info}/entry_points.txt +0 -0
  177. {mindstudio_probe-1.2.1.dist-info → mindstudio_probe-1.3.0.dist-info}/top_level.txt +0 -0
@@ -136,8 +136,8 @@ class AnomalyDataFactory(ABC):
136
136
  tag_name = tag[0]
137
137
  param_name = tag_name.split('/')[0]
138
138
  call_id = self.name2callid.get(tag_name, -1)
139
- if MonitorConst.VPP_SEP in param_name:
140
- vpp_stage = int(param_name.split(MonitorConst.VPP_SEP)[0])
139
+ if MonitorConst.NAME_SEP in param_name:
140
+ vpp_stage = int(param_name.split(MonitorConst.NAME_SEP)[0])
141
141
  else:
142
142
  vpp_stage = 0
143
143
 
@@ -161,10 +161,10 @@ class TrainStage:
161
161
  OPTIMIZER_STAGE = 2
162
162
 
163
163
 
164
- FORWARD_KEY = [MonitorConst.ACTV_IN, MonitorConst.ACTV_OUT]
165
- BACKWARD_KEY = [MonitorConst.ACTVGRAD_IN, MonitorConst.ACTVGRAD_OUT,
166
- MonitorConst.PRE_GRAD, MonitorConst.POST_GRAD, MonitorConst.ACC_GRAD]
167
- OPTIMIZER_KEY = [MonitorConst.EXP_AVG, MonitorConst.EFXP_AVG_SQ]
164
+ FORWARD_KEY = [MonitorConst.ACTV]
165
+ BACKWARD_KEY = [MonitorConst.ACTVGRAD, MonitorConst.PRE_GRAD,
166
+ MonitorConst.POST_GRAD, MonitorConst.ACC_GRAD]
167
+ OPTIMIZER_KEY = [MonitorConst.EXP_AVG, MonitorConst.EXP_AVG_SQ]
168
168
  TRAIN_STAGE = {
169
169
  **{key_: TrainStage.FORWARD_STAGE for key_ in FORWARD_KEY},
170
170
  **{key_: TrainStage.BACKWARD_STAGE for key_ in BACKWARD_KEY},
@@ -221,7 +221,7 @@ class GradAnomalyData:
221
221
  @staticmethod
222
222
  def get_train_stage(tag_name):
223
223
  """
224
- :param tag_name: "0:fc2_0/rank0/input", "0:fc1.weight/rank0/post_grad", "0:fc2.weight/rank0/efxp_avg_sq"
224
+ :param tag_name: "0:fc2.input:0/rank0/actv", "0:fc1.weight/rank0/post_grad", "0:fc2.weight/rank0/exp_avg_sq"
225
225
  :return: int, if forward return 0; if backward return 1; if optimizer return 2
226
226
  """
227
227
  key_ = tag_name.split("/")[-1]
@@ -361,10 +361,10 @@ class CSVWriterWithAD(BaseWriterWithAD):
361
361
 
362
362
  new_data = []
363
363
  for name, metric_value in self.context_dict.items():
364
- if MonitorConst.VPP_SEP not in name:
365
- new_data.append([name] + [step] + metric_value)
366
- else:
367
- new_data.append(name.split(MonitorConst.VPP_SEP) + [step] + metric_value)
364
+ new_line = name.split(MonitorConst.NAME_SEP) + metric_value
365
+ new_line.insert(2, step)
366
+ new_data.append(new_line)
367
+
368
368
  new_data = pd.DataFrame(new_data).round(self.ndigits).fillna("nan")
369
369
  write_df_to_csv(new_data, filepath, mode='a+', header=False)
370
370
  self.context_dict = defaultdict(list)
@@ -381,26 +381,11 @@ class CSVWriterWithAD(BaseWriterWithAD):
381
381
  def write_metrics(self, ops, metric_value, step, prefix=''):
382
382
  super().write_metrics(ops, metric_value, step, prefix='')
383
383
 
384
- # generate csv headers
385
- # set hashmap to reduce the number of headers generated.
386
- # 前向的norm用input.ops_和output.ops_,反向的用input_grad.ops_和output_grad.ops_
387
- if prefix in {"actv", "actv_grad"}:
388
- if prefix == "actv":
389
- input_and_output = [MonitorConst.ACTV_IN, MonitorConst.ACTV_OUT]
390
- else:
391
- input_and_output = [MonitorConst.ACTVGRAD_IN, MonitorConst.ACTVGRAD_OUT]
392
- ops_ = [MonitorConst.DOT.join(i) for i in itertools.product(input_and_output, ops)]
393
- csv_header = ["module_name", "step", *ops_]
384
+ if prefix in [MonitorConst.ACTV, MonitorConst.ACTVGRAD]:
385
+ self.header = MonitorConst.CSV_HEADER_XY + ops
394
386
  else:
395
- csv_header = ["param_name", "step", *ops]
396
-
397
- keys = list(metric_value.keys())
398
- if keys and MonitorConst.VPP_SEP in keys[0]:
399
- csv_header.insert(0, "vpp_stage")
400
-
401
- self.header = csv_header
387
+ self.header = MonitorConst.CSV_HEADER + ops
402
388
  self.write_csv(prefix, step)
403
- self.header = []
404
389
 
405
390
  def close(self):
406
391
  pass
@@ -22,37 +22,37 @@ from torch.utils.tensorboard import SummaryWriter
22
22
  from tqdm import tqdm
23
23
 
24
24
  from msprobe.core.common.const import MonitorConst
25
- from msprobe.core.common.file_utils import read_csv, create_directory, remove_path
25
+ from msprobe.core.common.file_utils import read_csv, create_directory, remove_path, recursive_chmod
26
26
  from msprobe.core.common.utils import is_int
27
+ from msprobe.core.common.decorator import recursion_depth_decorator
27
28
  from msprobe.pytorch.common.log import logger
28
29
  from msprobe.pytorch.monitor.utils import get_target_output_dir
29
30
 
30
31
  all_data_type_list = ["actv", "actv_grad", "exp_avg", "exp_avg_sq", "grad_unreduced", "grad_reduced", "param"]
31
32
  CSV_FILE_SUFFIX = r"_\d+-\d+\.csv"
33
+ MAX_PROCESS_NUM = 128
32
34
 
33
35
 
34
- def parse_step_line(data, line_id, name, ops):
35
- vp_id = data["vpp_stage"][line_id]
36
- module_name = data[name][line_id]
37
- step = data["step"][line_id]
36
+ def parse_step_line(line, ops):
37
+ vp_id = line["vpp_stage"]
38
+ module_name = line[MonitorConst.HEADER_NAME]
39
+ step = line["step"]
38
40
  vpp_name = f"vp{vp_id}:{module_name}"
41
+ if 'micro_step' in line:
42
+ vpp_name = f'{vpp_name}{MonitorConst.NAME_SEP}micro{line["micro_step"]}'
39
43
  ops_result = {}
40
44
  for op in ops:
41
- ops_result[op] = data[op][line_id]
45
+ ops_result[op] = line[op]
42
46
  return vpp_name, step, ops_result
43
47
 
44
48
 
45
49
  def parse_step_fn(filepath):
46
50
  data = read_csv(filepath)
47
-
48
- header = list(data.keys())
49
- name = header[MonitorConst.HEADER_NAME_INDEX]
50
- ops = header[MonitorConst.OPS_START_INDEX:]
51
-
51
+ ops = [k for k in data.keys() if k in MonitorConst.OP_LIST]
52
52
  parse_step_result = {}
53
53
 
54
- for line_id in range(len(data)):
55
- vpp_name, step, ops_result = parse_step_line(data, line_id, name, ops)
54
+ for _, line in data.iterrows():
55
+ vpp_name, step, ops_result = parse_step_line(line, ops)
56
56
  if vpp_name not in parse_step_result:
57
57
  parse_step_result[vpp_name] = {}
58
58
  if step in parse_step_result[vpp_name]:
@@ -78,6 +78,7 @@ def write_step(output_dirpath, parse_step_result, rank, data_type):
78
78
  writer.add_scalar(tag, value, step)
79
79
 
80
80
 
81
+ @recursion_depth_decorator("update_dict", max_depth=50)
81
82
  def update_dict(dict1, dict2):
82
83
  for key, value in dict2.items():
83
84
  if key in dict1:
@@ -117,11 +118,13 @@ def csv2tb_by_step_work(target_output_dirs, output_dirpath, data_type_list):
117
118
  def check_process_num(process_num):
118
119
  if not is_int(process_num) or process_num <= 0:
119
120
  raise ValueError(f"process_num({process_num}) is not a positive integer")
121
+ if process_num > MAX_PROCESS_NUM:
122
+ raise ValueError(f"The maximum supported process_num is {MAX_PROCESS_NUM}, current value: {process_num}.")
120
123
 
121
124
 
122
125
  def check_data_type_list(data_type_list):
123
126
  if data_type_list is None:
124
- logger.info(f"data_type_list is None, use defualt all_data_type_list: {all_data_type_list}")
127
+ logger.info(f"data_type_list is None, use default all_data_type_list: {all_data_type_list}")
125
128
  return
126
129
  if not isinstance(data_type_list, list):
127
130
  raise ValueError(f"data_type_list({data_type_list}) is not a list")
@@ -163,4 +166,5 @@ def csv2tensorboard_by_step(
163
166
  p.start()
164
167
  for p in processes:
165
168
  p.join()
169
+ recursive_chmod(output_dirpath)
166
170
  logger.info(f"output has been saved to: {output_dirpath}")
@@ -24,6 +24,7 @@ import torch.nn as nn
24
24
  from msprobe.core.common.const import MonitorConst
25
25
  from msprobe.core.common.file_utils import load_yaml
26
26
  from msprobe.pytorch.monitor.module_metric import get_metrics, get_summary_writer_tag_name
27
+ from msprobe.pytorch.common.log import logger
27
28
 
28
29
  try:
29
30
  import torch_npu
@@ -37,6 +38,7 @@ WrapDistributedOps = load_yaml(OpsPath).get("distributed", [])
37
38
 
38
39
  StackBlackListPath = os.path.join(os.path.dirname(__file__), "stack_blacklist.yaml")
39
40
  StackBlackList = load_yaml(StackBlackListPath).get("stack", [])
41
+ MAX_STRING_LENGTH = 1000
40
42
 
41
43
  distributed_func = {}
42
44
  for f in dir(dist):
@@ -139,6 +141,8 @@ def get_process_group(process_group):
139
141
 
140
142
 
141
143
  def stack_filter(stack):
144
+ if len(stack) > MAX_STRING_LENGTH:
145
+ logger.warning(f'The character string contains more than {MAX_STRING_LENGTH}. re match is skipped.')
142
146
  for pattern in StackBlackList:
143
147
  if re.search(pattern, stack):
144
148
  return False
@@ -188,10 +192,12 @@ def update_data(old, new):
188
192
 
189
193
 
190
194
  def is_target_line(codeline):
191
- stack = get_callstack()
192
- whole_stack = ';'.join(stack)
193
195
  if codeline == []:
194
196
  return True
197
+ stack = get_callstack()
198
+ whole_stack = ';'.join(stack)
199
+ if len(whole_stack) > MAX_STRING_LENGTH:
200
+ logger.warning(f'The character string contains more than {MAX_STRING_LENGTH}. re match is skipped.')
195
201
  for pattern in codeline:
196
202
  if re.search(pattern, whole_stack):
197
203
  return True