Coverage for mindsdb / utilities / profiler / profiler.py: 43%
79 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
1import time
2from datetime import datetime, timezone
3from functools import wraps
5import mindsdb.utilities.hooks as hooks
6from mindsdb.utilities.config import Config
7from mindsdb.utilities.context import context as ctx
10def _get_current_node(profiling: dict) -> dict:
11 """ return the node that the pointer points to
13 Args:
14 profiling (dict): whole profiling data
16 Returns:
17 dict: current node
18 """
19 current_node = profiling['tree']
20 for child_index in profiling['pointer']:
21 current_node = current_node['children'][child_index]
22 return current_node
25def start_node(tag: str):
26 """ Add a new node to profiling
28 Args:
29 tag (str): name of new node
30 """
31 profiling = ctx.profiling
32 new_node = {
33 'start_at': time.perf_counter(),
34 'start_at_thread': time.thread_time(),
35 'start_at_process': time.process_time(),
36 'stop_at': None,
37 'name': tag,
38 'children': []
39 }
40 if profiling['pointer'] is None:
41 if profiling['level'] != 1:
42 # profiling was activated not in the root of nodes tree
43 return
44 profiling['pointer'] = []
45 profiling['tree'] = new_node
46 profiling['tree']['time_start_at'] = datetime.now(timezone.utc)
47 else:
48 current_node = _get_current_node(profiling)
49 profiling['pointer'].append(len(current_node['children']))
50 current_node['children'].append(new_node)
53def stop_current_node():
54 """ Mark current node as completed and move pointer up
55 """
56 profiling = ctx.profiling
57 if profiling['pointer'] is None:
58 # profiling was activated not in the root of nodes tree
59 return
60 current_node = _get_current_node(profiling)
61 current_node['stop_at'] = time.perf_counter()
62 current_node['stop_at_thread'] = time.thread_time()
63 current_node['stop_at_process'] = time.process_time()
64 if len(profiling['pointer']) > 0:
65 profiling['pointer'] = profiling['pointer'][:-1]
66 else:
67 if ctx.profiling['enabled'] is True:
68 _send_profiling_results()
69 profiling['pointer'] = None
72def set_meta(**kwargs):
73 """ Add any additional info to profiling data
75 Args:
76 **kwargs (dict): metadata to add
77 """
78 if profiling_enabled() is True: 78 ↛ 79line 78 didn't jump to line 79 because the condition on line 78 was never true
79 ctx.profiling.update(kwargs)
82def _send_profiling_results():
83 """ Send profiling results to storage
84 """
85 ctx.profiling['company_id'] = ctx.company_id
86 ctx.profiling['hostname'] = Config().get('aws_meta_data', {}).get('public-hostname', '?')
87 ctx.profiling['instance_id'] = Config().get('aws_meta_data', {}).get('instance-id', '?')
88 hooks.send_profiling_results(ctx.profiling)
91def enable():
92 ctx.profiling['enabled'] = True
95def disable():
96 ctx.profiling['enabled'] = False
99def profiling_enabled():
100 try:
101 return ctx.profiling['enabled'] is True
102 except AttributeError:
103 return False
106def start(tag):
107 """ add new node to profiling data
108 """
109 ctx.profiling['level'] += 1
110 if profiling_enabled() is True: 110 ↛ 111line 110 didn't jump to line 111 because the condition on line 110 was never true
111 start_node(tag)
114def stop():
115 """ finalize current node and move pointer up
116 """
117 ctx.profiling['level'] -= 1
118 if profiling_enabled() is True: 118 ↛ 119line 118 didn't jump to line 119 because the condition on line 118 was never true
119 stop_current_node()
122class Context:
123 def __init__(self, tag):
124 self.tag = tag
126 def __enter__(self):
127 start(self.tag)
129 def __exit__(self, exc_type, exc_value, traceback):
130 stop()
133def profile(tag: str = None):
134 def decorator(function):
135 @wraps(function)
136 def wrapper(*args, **kwargs):
137 if profiling_enabled() is True: 137 ↛ 138line 137 didn't jump to line 138 because the condition on line 137 was never true
138 with Context(tag or f'{function.__name__}|{function.__module__}'):
139 result = function(*args, **kwargs)
140 else:
141 result = function(*args, **kwargs)
142 return result
143 return wrapper
144 return decorator