naeural-client 2.0.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.
- naeural_client/__init__.py +13 -0
- naeural_client/_ver.py +13 -0
- naeural_client/base/__init__.py +6 -0
- naeural_client/base/distributed_custom_code_presets.py +44 -0
- naeural_client/base/generic_session.py +1763 -0
- naeural_client/base/instance.py +616 -0
- naeural_client/base/payload/__init__.py +1 -0
- naeural_client/base/payload/payload.py +66 -0
- naeural_client/base/pipeline.py +1499 -0
- naeural_client/base/plugin_template.py +5209 -0
- naeural_client/base/responses.py +209 -0
- naeural_client/base/transaction.py +157 -0
- naeural_client/base_decentra_object.py +143 -0
- naeural_client/bc/__init__.py +3 -0
- naeural_client/bc/base.py +1046 -0
- naeural_client/bc/chain.py +0 -0
- naeural_client/bc/ec.py +324 -0
- naeural_client/certs/__init__.py +0 -0
- naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt +22 -0
- naeural_client/code_cheker/__init__.py +1 -0
- naeural_client/code_cheker/base.py +520 -0
- naeural_client/code_cheker/checker.py +294 -0
- naeural_client/comm/__init__.py +2 -0
- naeural_client/comm/amqp_wrapper.py +338 -0
- naeural_client/comm/mqtt_wrapper.py +539 -0
- naeural_client/const/README.md +3 -0
- naeural_client/const/__init__.py +9 -0
- naeural_client/const/base.py +101 -0
- naeural_client/const/comms.py +80 -0
- naeural_client/const/environment.py +26 -0
- naeural_client/const/formatter.py +7 -0
- naeural_client/const/heartbeat.py +111 -0
- naeural_client/const/misc.py +20 -0
- naeural_client/const/payload.py +190 -0
- naeural_client/default/__init__.py +1 -0
- naeural_client/default/instance/__init__.py +4 -0
- naeural_client/default/instance/chain_dist_custom_job_01_plugin.py +54 -0
- naeural_client/default/instance/custom_web_app_01_plugin.py +118 -0
- naeural_client/default/instance/net_mon_01_plugin.py +45 -0
- naeural_client/default/instance/view_scene_01_plugin.py +28 -0
- naeural_client/default/session/mqtt_session.py +72 -0
- naeural_client/io_formatter/__init__.py +2 -0
- naeural_client/io_formatter/base/__init__.py +1 -0
- naeural_client/io_formatter/base/base_formatter.py +80 -0
- naeural_client/io_formatter/default/__init__.py +3 -0
- naeural_client/io_formatter/default/a_dummy.py +51 -0
- naeural_client/io_formatter/default/aixp1.py +113 -0
- naeural_client/io_formatter/default/default.py +22 -0
- naeural_client/io_formatter/io_formatter_manager.py +96 -0
- naeural_client/logging/__init__.py +1 -0
- naeural_client/logging/base_logger.py +2056 -0
- naeural_client/logging/logger_mixins/__init__.py +12 -0
- naeural_client/logging/logger_mixins/class_instance_mixin.py +92 -0
- naeural_client/logging/logger_mixins/computer_vision_mixin.py +443 -0
- naeural_client/logging/logger_mixins/datetime_mixin.py +344 -0
- naeural_client/logging/logger_mixins/download_mixin.py +421 -0
- naeural_client/logging/logger_mixins/general_serialization_mixin.py +242 -0
- naeural_client/logging/logger_mixins/json_serialization_mixin.py +481 -0
- naeural_client/logging/logger_mixins/pickle_serialization_mixin.py +301 -0
- naeural_client/logging/logger_mixins/process_mixin.py +63 -0
- naeural_client/logging/logger_mixins/resource_size_mixin.py +81 -0
- naeural_client/logging/logger_mixins/timers_mixin.py +501 -0
- naeural_client/logging/logger_mixins/upload_mixin.py +260 -0
- naeural_client/logging/logger_mixins/utils_mixin.py +675 -0
- naeural_client/logging/small_logger.py +93 -0
- naeural_client/logging/tzlocal/__init__.py +20 -0
- naeural_client/logging/tzlocal/unix.py +231 -0
- naeural_client/logging/tzlocal/utils.py +113 -0
- naeural_client/logging/tzlocal/win32.py +151 -0
- naeural_client/logging/tzlocal/windows_tz.py +718 -0
- naeural_client/plugins_manager_mixin.py +273 -0
- naeural_client/utils/__init__.py +2 -0
- naeural_client/utils/comm_utils.py +44 -0
- naeural_client/utils/dotenv.py +75 -0
- naeural_client-2.0.0.dist-info/METADATA +365 -0
- naeural_client-2.0.0.dist-info/RECORD +78 -0
- naeural_client-2.0.0.dist-info/WHEEL +4 -0
- naeural_client-2.0.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,501 @@
|
|
1
|
+
import traceback
|
2
|
+
import numpy as np
|
3
|
+
|
4
|
+
from collections import OrderedDict, deque
|
5
|
+
from time import perf_counter, sleep, time
|
6
|
+
|
7
|
+
|
8
|
+
DEFAULT_SECTION = 'main'
|
9
|
+
DEFAULT_THRESHOLD_NO_SHOW = 0
|
10
|
+
PERIODS = [60 * 60, 24 * 60 * 60, 30 * 24 * 60 * 60]
|
11
|
+
PERIODS_STR = ["hour", "day", "month"]
|
12
|
+
MAX_PERIOD_LAPS = 20
|
13
|
+
DEFAULT_PERIODIC_MULTIPLIER = 3
|
14
|
+
|
15
|
+
MAX_LAPS = 100
|
16
|
+
ZERO_THRESHOLD = 5e-4
|
17
|
+
|
18
|
+
_OBSOLETE_SECTION_TIME = 3600 # sections older than 1 hour are archived
|
19
|
+
|
20
|
+
class _TimersMixin(object):
|
21
|
+
"""
|
22
|
+
Mixin for timers functionalities that are attached to `pye2.Logger`.
|
23
|
+
|
24
|
+
This mixin cannot be instantiated because it is built just to provide some additional
|
25
|
+
functionalities for `pye2.Logger`
|
26
|
+
|
27
|
+
In this mixin we can use any attribute/method of the Logger.
|
28
|
+
"""
|
29
|
+
|
30
|
+
def __init__(self):
|
31
|
+
super(_TimersMixin, self).__init__()
|
32
|
+
self.timers = None
|
33
|
+
self.timer_level = None # no actual purpose following addition of graph
|
34
|
+
self.sections_last_used = {}
|
35
|
+
self.opened_timers = None
|
36
|
+
self.timers_graph = None
|
37
|
+
self._timer_error = None
|
38
|
+
self.default_timers_section = DEFAULT_SECTION
|
39
|
+
self.__timer_mutex = False
|
40
|
+
|
41
|
+
self.start_show_timer = None
|
42
|
+
|
43
|
+
self.reset_timers()
|
44
|
+
return
|
45
|
+
|
46
|
+
def _maybe_create_timers_section(self, section=None):
|
47
|
+
section = section or self.default_timers_section
|
48
|
+
|
49
|
+
if section in self.timers:
|
50
|
+
return
|
51
|
+
|
52
|
+
self.timers[section] = OrderedDict()
|
53
|
+
self.timer_level[section] = 0
|
54
|
+
self.opened_timers[section] = deque()
|
55
|
+
self.timers_graph[section] = OrderedDict()
|
56
|
+
self.timers_graph[section]["ROOT"] = {"SLOW" : OrderedDict(), "FAST" : OrderedDict()}
|
57
|
+
self._timer_error[section] = False
|
58
|
+
return
|
59
|
+
|
60
|
+
def reset_timers(self):
|
61
|
+
self.timers = {}
|
62
|
+
self.timer_level = {}
|
63
|
+
self.opened_timers = {}
|
64
|
+
self.timers_graph = {}
|
65
|
+
self._timer_error = {}
|
66
|
+
|
67
|
+
self._maybe_create_timers_section()
|
68
|
+
return
|
69
|
+
|
70
|
+
@staticmethod
|
71
|
+
def get_empty_timer():
|
72
|
+
return {
|
73
|
+
'MEAN': 0,
|
74
|
+
'MAX': 0,
|
75
|
+
'COUNT': 0,
|
76
|
+
'START': 0,
|
77
|
+
'END': 0,
|
78
|
+
'PASS': True,
|
79
|
+
'LEVEL': 0,
|
80
|
+
|
81
|
+
'START_COUNT': 0,
|
82
|
+
'STOP_COUNT': 0,
|
83
|
+
|
84
|
+
'LAPS' : deque(maxlen=MAX_LAPS),
|
85
|
+
'HISTORY': {
|
86
|
+
'LAST': [None for _ in range(len(PERIODS))],
|
87
|
+
'DEQUES': [deque(maxlen=MAX_PERIOD_LAPS) for _ in range(len(PERIODS))],
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
def restart_timer(self, sname, section=None):
|
92
|
+
section = section or self.default_timers_section
|
93
|
+
self.timers[section][sname] = self.get_empty_timer()
|
94
|
+
return
|
95
|
+
|
96
|
+
def _add_in_timers_graph(self, sname, section=None):
|
97
|
+
section = section or self.default_timers_section
|
98
|
+
self.timers[section][sname]['LEVEL'] = self.timer_level[section]
|
99
|
+
if sname not in self.timers_graph[section]:
|
100
|
+
self.timers_graph[section][sname] = {"SLOW" : OrderedDict(), "FAST" : OrderedDict()}
|
101
|
+
|
102
|
+
self.timers_graph[section][sname]["FAST"] = OrderedDict() ## there is no ordered set, so we use OrderedDict with no values
|
103
|
+
return
|
104
|
+
|
105
|
+
def start_timer(self, sname, section=None):
|
106
|
+
section = section or self.default_timers_section
|
107
|
+
if section == self.default_timers_section:
|
108
|
+
assert self.is_main_thread, "Attempted to run threaded timer '{}' without section".format(sname)
|
109
|
+
|
110
|
+
self._maybe_create_timers_section(section)
|
111
|
+
|
112
|
+
if not self.DEBUG:
|
113
|
+
return -1
|
114
|
+
|
115
|
+
if sname not in self.timers[section]:
|
116
|
+
self.restart_timer(sname, section)
|
117
|
+
|
118
|
+
curr_time = perf_counter()
|
119
|
+
self._add_in_timers_graph(sname, section=section)
|
120
|
+
self.timers[section][sname]['START'] = curr_time
|
121
|
+
self.timers[section][sname]['START_COUNT'] += 1
|
122
|
+
if len(self.opened_timers[section]) >= 1:
|
123
|
+
parent = self.opened_timers[section][-1]
|
124
|
+
else:
|
125
|
+
parent = "ROOT"
|
126
|
+
#endif
|
127
|
+
|
128
|
+
self.timers_graph[section][parent]["FAST"][sname] = None
|
129
|
+
self.timers_graph[section][parent]["SLOW"][sname] = None
|
130
|
+
|
131
|
+
self.timer_level[section] += 1
|
132
|
+
self.opened_timers[section].append(sname)
|
133
|
+
|
134
|
+
faulty_timers = self._get_section_faulty_timers(section)
|
135
|
+
if len(faulty_timers) > 0 and not self._timer_error[section]:
|
136
|
+
self.P("Something is wrong with the timers in section '{}':".format(section), color='r')
|
137
|
+
for ft in faulty_timers:
|
138
|
+
self.P(" {}: {}".format(ft, self.timers[section][ft]), color='r')
|
139
|
+
self._timer_error[section] = True
|
140
|
+
#endif
|
141
|
+
|
142
|
+
return curr_time
|
143
|
+
|
144
|
+
def get_time_until_now(self, sname, section=None):
|
145
|
+
section = section or self.default_timers_section
|
146
|
+
ctimer = self.timers[section][sname]
|
147
|
+
return perf_counter() - ctimer['START']
|
148
|
+
|
149
|
+
def get_faulty_timers(self):
|
150
|
+
dct_faulty = {}
|
151
|
+
for section in self.timers:
|
152
|
+
dct_faulty[section] = self._get_section_faulty_timers(section)
|
153
|
+
return dct_faulty
|
154
|
+
|
155
|
+
def _get_section_faulty_timers(self, section=None):
|
156
|
+
section = section or self.default_timers_section
|
157
|
+
lst_faulty = []
|
158
|
+
for tmr_name, tmr in self.timers[section].items():
|
159
|
+
if (tmr['START_COUNT'] - tmr['STOP_COUNT']) > 1:
|
160
|
+
lst_faulty.append(tmr_name)
|
161
|
+
return lst_faulty
|
162
|
+
|
163
|
+
def end_timer_no_skip(self, sname, section=None, periodic=False):
|
164
|
+
return self.end_timer(sname, skip_first_timing=False, section=section, periodic=periodic)
|
165
|
+
|
166
|
+
def get_opened_timer(self, section=None):
|
167
|
+
section = section or self.default_timers_section
|
168
|
+
timer = self.opened_timers[section][-1]
|
169
|
+
return timer, perf_counter() - self.timers[section][timer]['START']
|
170
|
+
|
171
|
+
def get_periodic_multiplier(self):
|
172
|
+
if self.config_data is None:
|
173
|
+
return DEFAULT_PERIODIC_MULTIPLIER
|
174
|
+
return self.config_data.get('PERIODIC_MULTIPLIER', DEFAULT_PERIODIC_MULTIPLIER)
|
175
|
+
|
176
|
+
def add_periodic_record(self, sname, record, section=None, idx=0, check=False):
|
177
|
+
chistory = self.timers[section][sname]['HISTORY']
|
178
|
+
dq_size = len(chistory['DEQUES'][idx])
|
179
|
+
if check and dq_size > 2:
|
180
|
+
cmean = np.array(chistory['DEQUES'][idx]).mean()
|
181
|
+
cstd = np.std(chistory['DEQUES'][idx])
|
182
|
+
cnt = self.timers[section][sname]['COUNT']
|
183
|
+
q = self.get_periodic_multiplier()
|
184
|
+
limit = cmean + cstd * q
|
185
|
+
if limit < record:
|
186
|
+
self.P(
|
187
|
+
f"[WARNING]Timer {'' if section is None else section + '|'}{sname} "
|
188
|
+
f"took longer than expected at iter {cnt} based on {dq_size} records ("
|
189
|
+
f"{round(record, 3)} > {round(limit, 3)}[{round(cmean, 3)}+{round(q, 3)}*{round(cstd, 3)}]) [{PERIODS_STR[idx]}]",
|
190
|
+
color='r'
|
191
|
+
)
|
192
|
+
# endif warning
|
193
|
+
# endif anomaly check
|
194
|
+
chistory['DEQUES'][idx].append(record)
|
195
|
+
chistory['LAST'][idx] = self.timers[section][sname]['END']
|
196
|
+
return
|
197
|
+
|
198
|
+
def end_timer(self, sname, skip_first_timing=False, section=None, periodic=False):
|
199
|
+
section = section or self.default_timers_section
|
200
|
+
if sname not in self.timers[section]:
|
201
|
+
return
|
202
|
+
result = 0
|
203
|
+
self.sections_last_used[section] = time()
|
204
|
+
if self.DEBUG:
|
205
|
+
self.opened_timers[section].pop()
|
206
|
+
self.timer_level[section] -= 1
|
207
|
+
|
208
|
+
ctimer = self.timers[section][sname]
|
209
|
+
ctimer['STOP_COUNT'] += 1
|
210
|
+
ctimer['END'] = perf_counter()
|
211
|
+
result = ctimer['END'] - ctimer['START']
|
212
|
+
ctimer['LAPS'].append(result)
|
213
|
+
if periodic:
|
214
|
+
chistory = ctimer['HISTORY']
|
215
|
+
for i, period in enumerate(PERIODS):
|
216
|
+
if chistory['LAST'][i] is None:
|
217
|
+
self.add_periodic_record(sname, result, section=section, idx=i)
|
218
|
+
elif ctimer['END'] - chistory['LAST'][i] > period:
|
219
|
+
self.add_periodic_record(sname, result, section=section, idx=i, check=True)
|
220
|
+
# endif periodic record
|
221
|
+
# endfor i, period
|
222
|
+
# endif periodic
|
223
|
+
_count = ctimer['COUNT']
|
224
|
+
_prev_avg = ctimer['MEAN']
|
225
|
+
avg = _count * _prev_avg
|
226
|
+
|
227
|
+
if ctimer['PASS'] and skip_first_timing:
|
228
|
+
ctimer['PASS'] = False
|
229
|
+
return result # do not record first timing in average nor the max
|
230
|
+
|
231
|
+
ctimer['MAX'] = max(ctimer['MAX'], result)
|
232
|
+
|
233
|
+
ctimer['COUNT'] = _count + 1
|
234
|
+
avg += result
|
235
|
+
avg = avg / ctimer["COUNT"]
|
236
|
+
ctimer['MEAN'] = avg
|
237
|
+
return result
|
238
|
+
|
239
|
+
def stop_timer(self, sname, skip_first_timing=False, section=None, periodic=False):
|
240
|
+
return self.end_timer(sname=sname, skip_first_timing=skip_first_timing, section=section, periodic=periodic)
|
241
|
+
|
242
|
+
def show_timer_total(self, sname, section=None):
|
243
|
+
section = section or self.default_timers_section
|
244
|
+
ctimer = self.timers[section][sname]
|
245
|
+
cnt = ctimer['COUNT']
|
246
|
+
val = ctimer['MEAN'] * cnt
|
247
|
+
self.P(" {} = {:.3f} in {} laps".format(sname, val, cnt))
|
248
|
+
return
|
249
|
+
|
250
|
+
def _format_timer(self, key, section, was_recently_seen,
|
251
|
+
summary='mean',
|
252
|
+
show_levels=True,
|
253
|
+
show_max=True,
|
254
|
+
show_last=True,
|
255
|
+
show_count=True,
|
256
|
+
div=None,
|
257
|
+
threshold_no_show=None,
|
258
|
+
max_key_size=30,
|
259
|
+
):
|
260
|
+
|
261
|
+
if threshold_no_show is None:
|
262
|
+
threshold_no_show = DEFAULT_THRESHOLD_NO_SHOW
|
263
|
+
|
264
|
+
ctimer = self.timers[section].get(key, None)
|
265
|
+
|
266
|
+
if ctimer is None:
|
267
|
+
return
|
268
|
+
|
269
|
+
mean_time = ctimer['MEAN']
|
270
|
+
np_laps = np.array(ctimer['LAPS'])
|
271
|
+
if len(np_laps) > 0:
|
272
|
+
laps_mean = np_laps.mean()
|
273
|
+
laps_std = np_laps.std()
|
274
|
+
laps_zcount = (np_laps <= ZERO_THRESHOLD).sum()
|
275
|
+
laps_nzcount = len(np_laps) - laps_zcount
|
276
|
+
laps_nz_mean = np_laps.sum() / laps_nzcount if laps_nzcount > 0 else -1
|
277
|
+
laps_low_cnt = (np_laps <= max(ZERO_THRESHOLD, laps_mean - laps_std)).sum()
|
278
|
+
laps_low_prc = laps_low_cnt / np_laps.shape[0] * 100
|
279
|
+
else:
|
280
|
+
# not mandatory but nice for forever opened 1 time timers
|
281
|
+
laps_mean = -1
|
282
|
+
laps_std = -1
|
283
|
+
laps_zcount = -1
|
284
|
+
laps_nzcount = -1
|
285
|
+
laps_nz_mean = -1
|
286
|
+
laps_low_cnt = -1
|
287
|
+
laps_low_prc = -1
|
288
|
+
# end not mandatory
|
289
|
+
|
290
|
+
count = ctimer['COUNT']
|
291
|
+
|
292
|
+
if mean_time < threshold_no_show:
|
293
|
+
return
|
294
|
+
|
295
|
+
max_time = ctimer['MAX']
|
296
|
+
current_time = np_laps[-1] if len(np_laps) > 0 else -1 # ctimer['END'] - ctimer['START']
|
297
|
+
|
298
|
+
if not was_recently_seen:
|
299
|
+
key = '[' + key[:max_key_size] + ']'
|
300
|
+
|
301
|
+
if show_levels:
|
302
|
+
s_key = ' ' * ctimer['LEVEL'] + key[:max_key_size]
|
303
|
+
else:
|
304
|
+
s_key = key[:max_key_size]
|
305
|
+
msg = None
|
306
|
+
if summary in ['mean', 'avg']:
|
307
|
+
# self.verbose_log(" {} = {:.4f}s (max lap = {:.4f}s)".format(s_key,mean_time,max_time))
|
308
|
+
msg = " {} = {:.4f}s/q:{:.4f}s/nz:{:.4f}s".format(s_key, mean_time, laps_mean, laps_nz_mean)
|
309
|
+
else:
|
310
|
+
# self.verbose_log(" {} = {:.4f}s (max lap = {:.4f}s)".format(s_key,total, max_time))
|
311
|
+
total = mean_time * count
|
312
|
+
msg = " {} = {:.4f}s".format(s_key, total)
|
313
|
+
if show_max:
|
314
|
+
msg += ", max: {:.4f}s".format(max_time)
|
315
|
+
if show_last:
|
316
|
+
msg += ", lst: {:.4f}s".format(current_time)
|
317
|
+
if show_count:
|
318
|
+
msg += ", c: {}/L:{:.0f}%".format(count, laps_low_prc)
|
319
|
+
if div is not None:
|
320
|
+
msg += ", itr(B{}): {:.4f}s".format(div, mean_time / div)
|
321
|
+
return msg
|
322
|
+
|
323
|
+
def show_timers(self, indent=4, **kwargs):
|
324
|
+
color = kwargs.pop('color', 'n')
|
325
|
+
lst_logs = self.format_timers(**kwargs)
|
326
|
+
if indent > 0:
|
327
|
+
lst_logs = [" " * indent + l for l in lst_logs]
|
328
|
+
if len(lst_logs) > 0:
|
329
|
+
full_log = "\n".join(lst_logs)
|
330
|
+
self.verbose_log(full_log.lstrip(), color=color)
|
331
|
+
return
|
332
|
+
|
333
|
+
def show_timings(self, **kwargs):
|
334
|
+
self.show_timers(**kwargs)
|
335
|
+
return
|
336
|
+
|
337
|
+
def format_timers(self, summary=None,
|
338
|
+
title=None,
|
339
|
+
show_levels=True,
|
340
|
+
show_max=True,
|
341
|
+
show_last=True,
|
342
|
+
show_count=True,
|
343
|
+
div=None,
|
344
|
+
threshold_no_show=None,
|
345
|
+
selected_sections=None,
|
346
|
+
obsolete_section_time=_OBSOLETE_SECTION_TIME,
|
347
|
+
):
|
348
|
+
|
349
|
+
if selected_sections is not None:
|
350
|
+
assert isinstance(selected_sections, list)
|
351
|
+
|
352
|
+
if threshold_no_show is None:
|
353
|
+
threshold_no_show = DEFAULT_THRESHOLD_NO_SHOW
|
354
|
+
|
355
|
+
if summary is None:
|
356
|
+
summary = 'mean'
|
357
|
+
|
358
|
+
if title is None:
|
359
|
+
title = ''
|
360
|
+
|
361
|
+
lst_logs = []
|
362
|
+
self.start_show_timer = time()
|
363
|
+
try:
|
364
|
+
while self.__timer_mutex:
|
365
|
+
elapsed_in_show = time() - self.start_show_timer
|
366
|
+
if elapsed_in_show > 15:
|
367
|
+
raise ValueError("show_timers: Run time exceeded! Mutex is locked for more than 15 seconds.")
|
368
|
+
sleep(0.001)
|
369
|
+
# end while
|
370
|
+
self.__timer_mutex = True
|
371
|
+
|
372
|
+
self.start_show_timer = time()
|
373
|
+
self.__dfs_stack = deque(maxlen=100)
|
374
|
+
|
375
|
+
def dfs(visited, graph, node, was_recently_seen, logs, sect):
|
376
|
+
self.__dfs_stack.append(node)
|
377
|
+
elapsed_in_show = time() - self.start_show_timer
|
378
|
+
|
379
|
+
if elapsed_in_show > 5:
|
380
|
+
raise ValueError("show_timers: Run time exceeded! DFS took longer than 5 seconds. Stack: {}".format(self.__dfs_stack))
|
381
|
+
|
382
|
+
if node not in visited:
|
383
|
+
formatted_node = self._format_timer(
|
384
|
+
key=node,
|
385
|
+
section=sect,
|
386
|
+
was_recently_seen=was_recently_seen,
|
387
|
+
summary=summary,
|
388
|
+
show_levels=show_levels, show_last=show_last,
|
389
|
+
show_max=show_max, show_count=show_count, div=div,
|
390
|
+
threshold_no_show=threshold_no_show
|
391
|
+
)
|
392
|
+
if formatted_node is not None:
|
393
|
+
logs.append(formatted_node)
|
394
|
+
visited.add(node)
|
395
|
+
slow_keys = list(graph[node]["SLOW"].keys())
|
396
|
+
fast_keys = list(graph[node]["FAST"].keys())
|
397
|
+
for neighbour in slow_keys:
|
398
|
+
recently_seen = neighbour in fast_keys
|
399
|
+
dfs(visited, graph, neighbour, recently_seen, logs, sect)
|
400
|
+
#endfor
|
401
|
+
#endif
|
402
|
+
#enddef
|
403
|
+
|
404
|
+
if self.DEBUG:
|
405
|
+
if len(title) > 0:
|
406
|
+
title = ' ' + title
|
407
|
+
header = "Timing results{} at {}:".format(title, self.now_str(nice_print=True, short=True))
|
408
|
+
if threshold_no_show > 0:
|
409
|
+
header += " (discarding entries with time < {})".format(threshold_no_show)
|
410
|
+
lst_logs.append(header)
|
411
|
+
|
412
|
+
## SORTING sections and keeping the default section the first one ..
|
413
|
+
keys = list(self.timers.keys())
|
414
|
+
if selected_sections is not None:
|
415
|
+
keys = selected_sections
|
416
|
+
|
417
|
+
add_back_default_section = False
|
418
|
+
if self.default_timers_section in keys:
|
419
|
+
add_back_default_section = True
|
420
|
+
keys.pop(keys.index(self.default_timers_section))
|
421
|
+
keys.sort()
|
422
|
+
if add_back_default_section:
|
423
|
+
keys = [self.default_timers_section] + keys
|
424
|
+
|
425
|
+
old_sections = []
|
426
|
+
for section in keys:
|
427
|
+
last_see_ago = None
|
428
|
+
if section in self.sections_last_used:
|
429
|
+
last_see_ago = time() - self.sections_last_used[section]
|
430
|
+
if last_see_ago > obsolete_section_time:
|
431
|
+
old_sections.append(section)
|
432
|
+
continue
|
433
|
+
lst_logs.append("Section '{}'{}".format(
|
434
|
+
section, " last seen {:.1f}s ago".format(last_see_ago) if last_see_ago is not None else ""
|
435
|
+
))
|
436
|
+
buffer_visited = set()
|
437
|
+
dfs(buffer_visited, self.timers_graph[section], "ROOT", True, lst_logs, section)
|
438
|
+
if len(old_sections) > 0:
|
439
|
+
lst_logs.append("Archived {} sections older than {:.1f} hrs.".format(
|
440
|
+
len(old_sections), obsolete_section_time / 3600,
|
441
|
+
))
|
442
|
+
else:
|
443
|
+
self.verbose_log("DEBUG not activated!")
|
444
|
+
except Exception as exc:
|
445
|
+
self.P("EXCEPTION in show_timers: {}. Stacktrace:\n{}".format(exc, traceback.format_exc()), color='r')
|
446
|
+
self.__timer_mutex = False
|
447
|
+
return lst_logs
|
448
|
+
|
449
|
+
def get_timing_dict(self, skey, section=None):
|
450
|
+
section = section or self.default_timers_section
|
451
|
+
timers_section = self.timers.get(section, {})
|
452
|
+
dct = timers_section.get(skey, {})
|
453
|
+
return dct
|
454
|
+
|
455
|
+
def get_timer(self, skey, section=None):
|
456
|
+
return self.get_timing_dict(skey, section=section)
|
457
|
+
|
458
|
+
def get_timer_overall_mean(self, skey, section=None):
|
459
|
+
tmr = self.get_timer(skey, section=section)
|
460
|
+
result = tmr.get('MEAN', 0)
|
461
|
+
return result
|
462
|
+
|
463
|
+
def get_timer_mean(self, skey, section=None):
|
464
|
+
tmr = self.get_timer(skey, section=section)
|
465
|
+
laps = tmr.get('LAPS', [])
|
466
|
+
result = np.mean(laps) if len(laps) > 0 else -1
|
467
|
+
return result
|
468
|
+
|
469
|
+
|
470
|
+
def get_timer_count(self, skey, section=None):
|
471
|
+
tmr = self.get_timer(skey, section=section)
|
472
|
+
result = tmr.get('COUNT', 0)
|
473
|
+
return result
|
474
|
+
|
475
|
+
def import_timers_section(self, dct_timers, dct_timers_graph, section, overwrite=False):
|
476
|
+
if self.__timer_mutex:
|
477
|
+
# we skip this import until next time
|
478
|
+
self.P("WARNING: Cannot import section '{}' with {} timers while processing sections!".format(
|
479
|
+
section, len(dct_timers)
|
480
|
+
), color='r')
|
481
|
+
return
|
482
|
+
if section in self.timers and not overwrite:
|
483
|
+
self.P("WARNING: Cannot import section '{}' with {} timers as there is already a existing section".format(
|
484
|
+
section, len(dct_timers)
|
485
|
+
), color='r')
|
486
|
+
return False
|
487
|
+
self.timers[section] = dct_timers
|
488
|
+
self.timers_graph[section] = dct_timers_graph
|
489
|
+
self.sections_last_used[section] = time()
|
490
|
+
return True
|
491
|
+
|
492
|
+
def export_timers_section(self, section=None):
|
493
|
+
section = section or self.default_timers_section
|
494
|
+
if section not in self.timers:
|
495
|
+
self.P("WARNING: Cannot export unexisting timers section '{}'".format(
|
496
|
+
section
|
497
|
+
), color='r')
|
498
|
+
return None, None
|
499
|
+
dct_timers = self.timers[section]
|
500
|
+
dct_timers_graph = self.timers_graph[section]
|
501
|
+
return dct_timers, dct_timers_graph
|