logger-36 2025.22__py3-none-any.whl → 2025.23__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.
- logger_36/catalog/handler/memory.py +98 -0
- logger_36/constant/record.py +0 -1
- logger_36/task/storage.py +52 -20
- logger_36/type/logger.py +51 -135
- logger_36/version.py +1 -1
- {logger_36-2025.22.dist-info → logger_36-2025.23.dist-info}/METADATA +1 -1
- {logger_36-2025.22.dist-info → logger_36-2025.23.dist-info}/RECORD +9 -8
- {logger_36-2025.22.dist-info → logger_36-2025.23.dist-info}/WHEEL +0 -0
- {logger_36-2025.22.dist-info → logger_36-2025.23.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
"""
|
2
|
+
Copyright CNRS (https://www.cnrs.fr/index.php/en)
|
3
|
+
Contributor(s): Eric Debreuve (eric.debreuve@cnrs.fr) since 2023
|
4
|
+
SEE COPYRIGHT NOTICE BELOW
|
5
|
+
"""
|
6
|
+
|
7
|
+
import json
|
8
|
+
import logging as l
|
9
|
+
import typing as h
|
10
|
+
|
11
|
+
from logger_36.type.handler import handler_t as base_t
|
12
|
+
|
13
|
+
formats_h = h.Literal["json", "message", "raw"]
|
14
|
+
|
15
|
+
|
16
|
+
class memory_handler_t(base_t):
|
17
|
+
def __init__(
|
18
|
+
self, name: str | None, message_width: int, level: int, format_: formats_h
|
19
|
+
) -> None:
|
20
|
+
""""""
|
21
|
+
assert format_ in h.get_args(formats_h)
|
22
|
+
|
23
|
+
base_t.__init__(self, name, message_width, None, level)
|
24
|
+
|
25
|
+
self.format_ = format_
|
26
|
+
self.records = []
|
27
|
+
|
28
|
+
@classmethod
|
29
|
+
def New(
|
30
|
+
cls,
|
31
|
+
/,
|
32
|
+
*,
|
33
|
+
name: str | None = None,
|
34
|
+
message_width: int = -1,
|
35
|
+
level: int = l.NOTSET,
|
36
|
+
format_: formats_h = "message",
|
37
|
+
**_,
|
38
|
+
) -> h.Self:
|
39
|
+
""""""
|
40
|
+
return cls(name, message_width, level, format_)
|
41
|
+
|
42
|
+
def emit(self, record: l.LogRecord, /) -> None:
|
43
|
+
""""""
|
44
|
+
level = record.levelno
|
45
|
+
|
46
|
+
if self.format_ == "raw":
|
47
|
+
is_not_a_rule = True
|
48
|
+
elif self.format_ == "message":
|
49
|
+
record, is_not_a_rule = self.MessageFromRecord(record)
|
50
|
+
else:
|
51
|
+
record = json.dumps(record.__dict__)
|
52
|
+
is_not_a_rule = True
|
53
|
+
|
54
|
+
self.records.append((level, record, is_not_a_rule))
|
55
|
+
|
56
|
+
def EmitMessage(self, message: str, /) -> None:
|
57
|
+
""""""
|
58
|
+
if self.format_ == "message":
|
59
|
+
message_key = "msg"
|
60
|
+
else:
|
61
|
+
message_key = "message"
|
62
|
+
record = l.makeLogRecord(
|
63
|
+
{"name": "<UNKNOWN LOGGER>", "levelno": l.INFO, message_key: message}
|
64
|
+
)
|
65
|
+
self.emit(record)
|
66
|
+
|
67
|
+
|
68
|
+
"""
|
69
|
+
COPYRIGHT NOTICE
|
70
|
+
|
71
|
+
This software is governed by the CeCILL license under French law and
|
72
|
+
abiding by the rules of distribution of free software. You can use,
|
73
|
+
modify and/ or redistribute the software under the terms of the CeCILL
|
74
|
+
license as circulated by CEA, CNRS and INRIA at the following URL
|
75
|
+
"http://www.cecill.info".
|
76
|
+
|
77
|
+
As a counterpart to the access to the source code and rights to copy,
|
78
|
+
modify and redistribute granted by the license, users are provided only
|
79
|
+
with a limited warranty and the software's author, the holder of the
|
80
|
+
economic rights, and the successive licensors have only limited
|
81
|
+
liability.
|
82
|
+
|
83
|
+
In this respect, the user's attention is drawn to the risks associated
|
84
|
+
with loading, using, modifying and/or developing or reproducing the
|
85
|
+
software by the user in light of its specific status of free software,
|
86
|
+
that may mean that it is complicated to manipulate, and that also
|
87
|
+
therefore means that it is reserved for developers and experienced
|
88
|
+
professionals having in-depth computer knowledge. Users are therefore
|
89
|
+
encouraged to load and test the software's suitability as regards their
|
90
|
+
requirements in conditions enabling the security of their systems and/or
|
91
|
+
data to be ensured and, more generally, to use and operate it in the
|
92
|
+
same conditions as regards security.
|
93
|
+
|
94
|
+
The fact that you are presently reading this means that you have had
|
95
|
+
knowledge of the CeCILL license and that you accept its terms.
|
96
|
+
|
97
|
+
SEE LICENCE NOTICE: file README-LICENCE-utf8.txt at project source root.
|
98
|
+
"""
|
logger_36/constant/record.py
CHANGED
logger_36/task/storage.py
CHANGED
@@ -10,25 +10,28 @@ from pathlib import Path as path_t
|
|
10
10
|
|
11
11
|
from logger_36.constant.html import BODY_PLACEHOLDER, MINIMAL_HTML, TITLE_PLACEHOLDER
|
12
12
|
from logger_36.instance.logger import L
|
13
|
+
from logger_36.type.logger import logger_t
|
13
14
|
|
14
15
|
|
15
|
-
def SaveLOGasHTML(
|
16
|
+
def SaveLOGasHTML(
|
17
|
+
path: str | path_t | io_base_t | None = None, /, *, logger: logger_t = L
|
18
|
+
) -> None:
|
16
19
|
"""
|
17
20
|
From first console handler found.
|
18
21
|
"""
|
19
22
|
cannot_save = "Cannot save logging record as HTML"
|
20
23
|
|
21
24
|
if path is None:
|
22
|
-
for handler in
|
25
|
+
for handler in logger.handlers:
|
23
26
|
if isinstance(handler, l.FileHandler):
|
24
27
|
path = path_t(handler.baseFilename).with_suffix(".htm")
|
25
28
|
break
|
26
29
|
else:
|
27
|
-
|
30
|
+
logger.warning(f"{cannot_save}: No file handler to build a filename from.")
|
28
31
|
return
|
29
32
|
|
30
33
|
if path.exists():
|
31
|
-
|
34
|
+
logger.warning(
|
32
35
|
f'{cannot_save}: Automatically generated path "{path}" already exists.'
|
33
36
|
)
|
34
37
|
return
|
@@ -38,13 +41,38 @@ def SaveLOGasHTML(path: str | path_t | io_base_t | None = None) -> None:
|
|
38
41
|
actual_file = isinstance(path, path_t)
|
39
42
|
|
40
43
|
if actual_file and path.exists():
|
41
|
-
|
44
|
+
logger.warning(f'{cannot_save}: File "{path}" already exists.')
|
42
45
|
return
|
43
46
|
|
44
|
-
|
45
|
-
|
47
|
+
for handler in logger.handlers:
|
48
|
+
records = getattr(handler, "records", None)
|
49
|
+
if isinstance(records, list) and (
|
50
|
+
(records.__len__() == 0)
|
51
|
+
or all(
|
52
|
+
isinstance(_, tuple)
|
53
|
+
and isinstance(_[0], int)
|
54
|
+
and isinstance(_[1], dict | str | l.LogRecord)
|
55
|
+
and isinstance(_[2], bool)
|
56
|
+
for _ in records
|
57
|
+
)
|
58
|
+
):
|
59
|
+
break
|
60
|
+
else:
|
61
|
+
logger.warning(f"{cannot_save}: No handlers with recording capability found.")
|
62
|
+
return
|
63
|
+
|
64
|
+
if records.__len__() == 0:
|
65
|
+
return
|
66
|
+
|
67
|
+
if isinstance(records[0][1], str):
|
68
|
+
records = map(_HighlightedEvent, records)
|
69
|
+
else:
|
70
|
+
records = map(lambda _: str(_[1]), records)
|
71
|
+
body = "\n".join(records)
|
72
|
+
html = MINIMAL_HTML.replace(TITLE_PLACEHOLDER, logger.name).replace(
|
46
73
|
BODY_PLACEHOLDER, body
|
47
74
|
)
|
75
|
+
|
48
76
|
if actual_file:
|
49
77
|
with open(path, "w") as accessor:
|
50
78
|
accessor.write(html)
|
@@ -52,21 +80,25 @@ def SaveLOGasHTML(path: str | path_t | io_base_t | None = None) -> None:
|
|
52
80
|
path.write(html)
|
53
81
|
|
54
82
|
|
55
|
-
def _HighlightedEvent(event: tuple[int, str], /) -> str:
|
83
|
+
def _HighlightedEvent(event: tuple[int, str, bool], /) -> str:
|
56
84
|
""""""
|
57
|
-
level, message = event
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
85
|
+
level, message, is_not_a_rule = event
|
86
|
+
|
87
|
+
if is_not_a_rule:
|
88
|
+
if level == l.DEBUG:
|
89
|
+
color = "BlueViolet"
|
90
|
+
elif level == l.INFO:
|
91
|
+
color = "black"
|
92
|
+
elif level == l.WARNING:
|
93
|
+
color = "gold"
|
94
|
+
elif level == l.ERROR:
|
95
|
+
color = "orange"
|
96
|
+
elif level == l.CRITICAL:
|
97
|
+
color = "red"
|
98
|
+
else:
|
99
|
+
color = "black"
|
68
100
|
else:
|
69
|
-
color = "
|
101
|
+
color = "DarkTurquoise"
|
70
102
|
|
71
103
|
return f'<span style="color:{color}">{message}</span>'
|
72
104
|
|
logger_36/type/logger.py
CHANGED
@@ -41,11 +41,7 @@ from logger_36.constant.logger import WARNING_LOGGER_NAME, WARNING_TYPE_COMPILED
|
|
41
41
|
from logger_36.constant.memory import UNKNOWN_MEMORY_USAGE
|
42
42
|
from logger_36.constant.message import LINE_INDENT, TIME_LENGTH_m_1, expected_op_h
|
43
43
|
from logger_36.constant.path import PROJECT_FILE_RELATIVE, USER_FOLDER
|
44
|
-
from logger_36.constant.record import
|
45
|
-
INTERNAL_INFO_ATTR,
|
46
|
-
SHOW_W_RULE_ATTR,
|
47
|
-
SHOW_WHERE_ATTR,
|
48
|
-
)
|
44
|
+
from logger_36.constant.record import SHOW_W_RULE_ATTR, SHOW_WHERE_ATTR
|
49
45
|
from logger_36.task.format.message import MessageWithActualExpected
|
50
46
|
from logger_36.task.measure.chronos import ElapsedTime
|
51
47
|
from logger_36.task.measure.memory import CurrentUsage as CurrentMemoryUsage
|
@@ -79,21 +75,15 @@ class logger_t(base_t):
|
|
79
75
|
_should_activate_log_interceptions: Loggers instantiated after a logger_t logger
|
80
76
|
will be missed by an early call of ToggleLogInterceptions. Therefore, passing True
|
81
77
|
for activate_log_interceptions only sets _should_activate_log_interceptions to True,
|
82
|
-
which is later checked in AddHandler to effectively call ToggleLogInterceptions
|
83
|
-
_warming_up is False (which normally indicates that the handler about to
|
84
|
-
be added is the last one).
|
85
|
-
|
86
|
-
_warming_up: Must not be False until at least one handler has been added.
|
78
|
+
which is later checked in AddHandler to effectively call ToggleLogInterceptions.
|
87
79
|
"""
|
88
80
|
|
89
|
-
should_record_messages: bool = False
|
90
|
-
should_monitor_memory_usage: bool = False
|
91
81
|
exit_on_error: bool = False # Implies exit_on_critical.
|
92
82
|
exit_on_critical: bool = False
|
93
|
-
|
83
|
+
should_monitor_memory_usage: bool = False
|
94
84
|
|
95
|
-
|
96
|
-
|
85
|
+
history: dict[date_time_t, str] = d.field(init=False, default_factory=dict)
|
86
|
+
n_events: dict[int, int] = d.field(init=False, default_factory=dict)
|
97
87
|
|
98
88
|
last_message_now: date_time_t = d.field(init=False, default=_DATE_TIME_ORIGIN)
|
99
89
|
last_message_date: date_t = d.field(init=False, default=_DATE_ORIGIN)
|
@@ -105,12 +95,9 @@ class logger_t(base_t):
|
|
105
95
|
init=False, default_factory=dict
|
106
96
|
)
|
107
97
|
intercepts_exceptions: bool = d.field(init=False, default=False)
|
108
|
-
_recording_handler: handler_extension_t | None = d.field(init=False, default=None)
|
109
98
|
|
110
99
|
# Used only until the last handler is added (see AddHandler).
|
111
100
|
_should_activate_log_interceptions: bool = d.field(init=False, default=False)
|
112
|
-
_warming_up: bool = d.field(init=False, default=True)
|
113
|
-
_on_hold: list[l.LogRecord] | None = d.field(init=False, default_factory=list)
|
114
101
|
|
115
102
|
name_: d.InitVar[str | None] = None
|
116
103
|
level_: d.InitVar[int] = l.NOTSET
|
@@ -168,7 +155,6 @@ class logger_t(base_t):
|
|
168
155
|
if name_ is None:
|
169
156
|
name_ = f"{type(self).__name__}:{hex(id(self))[2:]}"
|
170
157
|
|
171
|
-
self.handle = self._HandleWarmUp
|
172
158
|
base_t.__init__(self, name_)
|
173
159
|
self.setLevel(level_)
|
174
160
|
self.propagate = False # Part of base_t.
|
@@ -177,15 +163,7 @@ class logger_t(base_t):
|
|
177
163
|
self.exit_on_critical = True
|
178
164
|
|
179
165
|
for level_id in l.getLevelNamesMapping().values():
|
180
|
-
self.
|
181
|
-
|
182
|
-
if self.should_record_messages:
|
183
|
-
self.ActivateMessageRecording()
|
184
|
-
|
185
|
-
self.info(
|
186
|
-
f'New logger "{self.name}" for "{PROJECT_FILE_RELATIVE}"',
|
187
|
-
extra={INTERNAL_INFO_ATTR: True},
|
188
|
-
)
|
166
|
+
self.n_events[level_id] = 0
|
189
167
|
|
190
168
|
if activate_wrn_interceptions:
|
191
169
|
self.ToggleWarningInterceptions(True)
|
@@ -197,29 +175,12 @@ class logger_t(base_t):
|
|
197
175
|
if self.should_monitor_memory_usage:
|
198
176
|
self.ActivateMemoryUsageMonitoring()
|
199
177
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
if (date := now.date()) != self.last_message_date:
|
204
|
-
self._AcknowledgeDateChange(date)
|
205
|
-
|
206
|
-
# When.
|
207
|
-
record.when_or_elapsed = (TIME_LENGTH_m_1 + 1) * "."
|
208
|
-
# Where.
|
209
|
-
if record.levelno != l.INFO:
|
210
|
-
_ = _RecordLocation(record, True)
|
211
|
-
# What.
|
212
|
-
if not isinstance(record.msg, str):
|
213
|
-
record.msg = str(record.msg)
|
214
|
-
|
215
|
-
self._on_hold.append(record)
|
178
|
+
self.history[date_time_t.now()] = (
|
179
|
+
f'Logger "{self.name}" instantiation for "{PROJECT_FILE_RELATIVE}"'
|
180
|
+
)
|
216
181
|
|
217
|
-
def
|
182
|
+
def handle(self, record: l.LogRecord, /) -> None:
|
218
183
|
""""""
|
219
|
-
is_internal_info = getattr(record, INTERNAL_INFO_ATTR, False)
|
220
|
-
if is_internal_info and not self.verbose:
|
221
|
-
return
|
222
|
-
|
223
184
|
elapsed_time, now = ElapsedTime(should_return_now=True)
|
224
185
|
|
225
186
|
if (date := now.date()) != self.last_message_date:
|
@@ -244,7 +205,8 @@ class logger_t(base_t):
|
|
244
205
|
if not isinstance(record.msg, str):
|
245
206
|
record.msg = str(record.msg)
|
246
207
|
|
247
|
-
|
208
|
+
base_t.handle(self, record)
|
209
|
+
self.n_events[record.levelno] += 1
|
248
210
|
|
249
211
|
if self.should_monitor_memory_usage:
|
250
212
|
self.memory_usages.append((where, CurrentMemoryUsage()))
|
@@ -256,29 +218,6 @@ class logger_t(base_t):
|
|
256
218
|
# __post_init__ set self.exit_on_critical if self.exit_on_error.
|
257
219
|
s.exit(1)
|
258
220
|
|
259
|
-
def _HandleRaw(self, record: l.LogRecord, /) -> None:
|
260
|
-
""""""
|
261
|
-
if self.should_record_messages:
|
262
|
-
message = self._recording_handler.MessageFromRecord(record)[0]
|
263
|
-
self.recorded.append((record.levelno, message))
|
264
|
-
|
265
|
-
base_t.handle(self, record)
|
266
|
-
self.events[record.levelno] += 1
|
267
|
-
|
268
|
-
def _FlushRecordsOnHold(self) -> None:
|
269
|
-
"""
|
270
|
-
should_record_messages and verbose must have been set by now.
|
271
|
-
"""
|
272
|
-
for held in self._on_hold:
|
273
|
-
if self.verbose or not getattr(held, INTERNAL_INFO_ATTR, False):
|
274
|
-
self._HandleRaw(held)
|
275
|
-
|
276
|
-
self._on_hold.clear()
|
277
|
-
self._on_hold = None
|
278
|
-
self._warming_up = False
|
279
|
-
|
280
|
-
self.handle = self._HandleRoutine
|
281
|
-
|
282
221
|
def _AcknowledgeDateChange(self, date: date_t, /) -> None:
|
283
222
|
""""""
|
284
223
|
self.last_message_date = date
|
@@ -291,38 +230,12 @@ class logger_t(base_t):
|
|
291
230
|
SHOW_W_RULE_ATTR: True,
|
292
231
|
}
|
293
232
|
)
|
294
|
-
|
295
|
-
if self._warming_up:
|
296
|
-
self._on_hold.append(record)
|
297
|
-
else:
|
298
|
-
self._HandleRaw(record)
|
299
|
-
|
300
|
-
def ActivateMessageRecording(self) -> None:
|
301
|
-
""""""
|
302
|
-
self._recording_handler = handler_extension_t("recording_handler", 0, None)
|
303
|
-
self.should_record_messages = True # Useless if called from __post_init__.
|
304
|
-
self.info(
|
305
|
-
f'Message recording activated for logger "{self.name}"',
|
306
|
-
extra={INTERNAL_INFO_ATTR: True},
|
307
|
-
)
|
308
|
-
|
309
|
-
def ActivateMemoryUsageMonitoring(self) -> None:
|
310
|
-
""""""
|
311
|
-
if MEMORY_MEASURE_IS_AVAILABLE:
|
312
|
-
# Useless if called from __post_init__.
|
313
|
-
self.should_monitor_memory_usage = True
|
314
|
-
self.info(
|
315
|
-
f'Memory usage monitoring activated for logger "{self.name}"',
|
316
|
-
extra={INTERNAL_INFO_ATTR: True},
|
317
|
-
)
|
318
|
-
else:
|
319
|
-
self.should_monitor_memory_usage = False
|
320
|
-
self.error(MEMORY_MEASURE_ERROR)
|
233
|
+
base_t.handle(self, record)
|
321
234
|
|
322
235
|
def ResetEventCounts(self) -> None:
|
323
236
|
""""""
|
324
|
-
for level_id in self.
|
325
|
-
self.
|
237
|
+
for level_id in self.n_events:
|
238
|
+
self.n_events[level_id] = 0
|
326
239
|
|
327
240
|
def ToggleWarningInterceptions(self, state: bool, /) -> None:
|
328
241
|
""""""
|
@@ -335,7 +248,7 @@ class logger_t(base_t):
|
|
335
248
|
logger.handle = t.MethodType(_HandleForWarnings(self), logger)
|
336
249
|
|
337
250
|
l.captureWarnings(True)
|
338
|
-
self.
|
251
|
+
self.history[date_time_t.now()] = "Warning Interception: ON"
|
339
252
|
else:
|
340
253
|
if not self.intercepts_warnings:
|
341
254
|
return
|
@@ -345,12 +258,12 @@ class logger_t(base_t):
|
|
345
258
|
self.intercepted_wrn_handle = None
|
346
259
|
|
347
260
|
l.captureWarnings(False)
|
348
|
-
self.
|
261
|
+
self.history[date_time_t.now()] = "Warning Interception: OFF"
|
349
262
|
|
350
263
|
def ToggleLogInterceptions(self, state: bool, /) -> None:
|
351
264
|
""""""
|
352
265
|
if state:
|
353
|
-
if self.intercepts_logs:
|
266
|
+
if self._should_activate_log_interceptions or self.intercepts_logs:
|
354
267
|
return
|
355
268
|
|
356
269
|
# Note: Alternative to self.manager is logging.root.manager.
|
@@ -369,11 +282,14 @@ class logger_t(base_t):
|
|
369
282
|
intercepted = sorted(self.intercepted_log_handles.keys())
|
370
283
|
if intercepted.__len__() > 0:
|
371
284
|
as_str = ", ".join(intercepted)
|
372
|
-
self.
|
373
|
-
f"Now Intercepting LOGs from: {as_str}"
|
374
|
-
extra={INTERNAL_INFO_ATTR: True},
|
285
|
+
self.history[date_time_t.now()] = (
|
286
|
+
f"Now Intercepting LOGs from: {as_str}"
|
375
287
|
)
|
376
288
|
else:
|
289
|
+
if self._should_activate_log_interceptions:
|
290
|
+
self._should_activate_log_interceptions = False
|
291
|
+
return
|
292
|
+
|
377
293
|
if not self.intercepts_logs:
|
378
294
|
return
|
379
295
|
|
@@ -381,7 +297,7 @@ class logger_t(base_t):
|
|
381
297
|
logger = l.getLogger(name)
|
382
298
|
logger.handle = handle
|
383
299
|
self.intercepted_log_handles.clear()
|
384
|
-
self.
|
300
|
+
self.history[date_time_t.now()] = "Log Interception: OFF"
|
385
301
|
|
386
302
|
def ToggleExceptionInterceptions(self, state: bool, /) -> None:
|
387
303
|
""""""
|
@@ -392,7 +308,7 @@ class logger_t(base_t):
|
|
392
308
|
s.excepthook = self.DealWithException
|
393
309
|
thrd.excepthook = self.DealWithExceptionInThread
|
394
310
|
self.intercepts_exceptions = True
|
395
|
-
self.
|
311
|
+
self.history[date_time_t.now()] = "Exception Interception: ON"
|
396
312
|
else:
|
397
313
|
if not self.intercepts_exceptions:
|
398
314
|
return
|
@@ -400,7 +316,19 @@ class logger_t(base_t):
|
|
400
316
|
s.excepthook = s.__excepthook__
|
401
317
|
thrd.excepthook = thrd.__excepthook__
|
402
318
|
self.intercepts_exceptions = False
|
403
|
-
self.
|
319
|
+
self.history[date_time_t.now()] = "Exception Interception: OFF"
|
320
|
+
|
321
|
+
def ActivateMemoryUsageMonitoring(self) -> None:
|
322
|
+
""""""
|
323
|
+
if MEMORY_MEASURE_IS_AVAILABLE:
|
324
|
+
# Useless if called from __post_init__.
|
325
|
+
self.should_monitor_memory_usage = True
|
326
|
+
self.history[date_time_t.now()] = (
|
327
|
+
f'Memory usage monitoring activated for logger "{self.name}"'
|
328
|
+
)
|
329
|
+
else:
|
330
|
+
self.should_monitor_memory_usage = False
|
331
|
+
self.error(MEMORY_MEASURE_ERROR)
|
404
332
|
|
405
333
|
def AddHandler(
|
406
334
|
self,
|
@@ -413,21 +341,16 @@ class logger_t(base_t):
|
|
413
341
|
name: str | None = None,
|
414
342
|
level: int = l.INFO,
|
415
343
|
message_width: int = -1,
|
416
|
-
this_is_last_handler: bool = True,
|
417
344
|
**kwargs,
|
418
345
|
) -> None:
|
419
346
|
"""
|
420
347
|
Silently ignores re-holding request after un-holding.
|
421
348
|
"""
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
self._should_activate_log_interceptions = False
|
428
|
-
|
429
|
-
should_flush_on_hold = True
|
430
|
-
new_handler_warning = "\n(Handlers added from now on will miss above logs.)"
|
349
|
+
if self._should_activate_log_interceptions:
|
350
|
+
# Turn _should_activate_log_interceptions off before calling
|
351
|
+
# ToggleLogInterceptions because it checks it.
|
352
|
+
self._should_activate_log_interceptions = False
|
353
|
+
self.ToggleLogInterceptions(True)
|
431
354
|
|
432
355
|
if isinstance(handler_t_or_handler, type):
|
433
356
|
handler = handler_t_or_handler.New(
|
@@ -437,20 +360,13 @@ class logger_t(base_t):
|
|
437
360
|
handler = handler_t_or_handler
|
438
361
|
base_t.addHandler(self, handler)
|
439
362
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
f"{new_handler_warning}",
|
448
|
-
extra={INTERNAL_INFO_ATTR: True},
|
449
|
-
)
|
450
|
-
|
451
|
-
# Wait until after the handler has been added to flush messages on hold.
|
452
|
-
if should_flush_on_hold:
|
453
|
-
self._FlushRecordsOnHold()
|
363
|
+
path = getattr(handler, "baseFilename", "")
|
364
|
+
if isinstance(path, path_t) or (path.__len__() > 0):
|
365
|
+
path = f"\nPath: {path}"
|
366
|
+
self.history[date_time_t.now()] = (
|
367
|
+
f'New handler "{handler.name}" of type "{type(handler).__name__}" and '
|
368
|
+
f"level {handler.level}={l.getLevelName(handler.level)}{path}"
|
369
|
+
)
|
454
370
|
|
455
371
|
def MakeMonochrome(self) -> None:
|
456
372
|
""""""
|
logger_36/version.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
logger_36/__init__.py,sha256=mK6AD0eWI2Sk42oxleTvsxzYJ28FbHK5WNkpLgAhnNE,2129
|
2
|
-
logger_36/version.py,sha256=
|
2
|
+
logger_36/version.py,sha256=3y8_8Te0bVUofCcWg9yoGDEx2HlTct92Ol2Pk3NTA8w,1680
|
3
3
|
logger_36/api/content.py,sha256=DuT4UX4r_1DTXzuuRD-tvsTZk5X-Nj11loBKhuWOMw0,1791
|
4
4
|
logger_36/api/gpu.py,sha256=NNs1IvQ7bh8Dppm8O8K2YLWbm4rogc3Ie_-D6xzkX3g,1726
|
5
5
|
logger_36/api/memory.py,sha256=vOY4cTTrC3u7L0OrKXdPNlsCahYjCrY4h7iqpGZv9kU,2217
|
@@ -13,6 +13,7 @@ logger_36/catalog/handler/console.py,sha256=YEQN8fw7ra9w-5sJACNC4pktv9einm5ASP9T
|
|
13
13
|
logger_36/catalog/handler/console_rich.py,sha256=gPpq8ij1ZFTXaLgISaCTXDDwv7uWPivLeq2ttpiuKlk,6190
|
14
14
|
logger_36/catalog/handler/file.py,sha256=yg8GnsV6AmDsx1R5iZlsK-5idqD733gc09Syl02TG7Y,2458
|
15
15
|
logger_36/catalog/handler/generic.py,sha256=L8mLc-iQlBWKBqEN3-wIKy2yk_TVgqIWYn_P1hXDsQA,6361
|
16
|
+
logger_36/catalog/handler/memory.py,sha256=-31hTXgGImC6if4wJF6eegvwYhsYAQsDTkdoXIUxZB8,3224
|
16
17
|
logger_36/catalog/logger/chronos.py,sha256=S4m9TMPQy_Ju500mpE1jNzu2gZG-QKdVuvX9RVRKHR8,1911
|
17
18
|
logger_36/catalog/logger/gpu.py,sha256=Py5YY0nD_pqJzJsEKQYoOGHcPqyNVJ3J2noOS3hDL6g,2890
|
18
19
|
logger_36/catalog/logger/memory.py,sha256=J0ZGKO7j1FZA_aDGxpABtvzDy1RjCDiDmWYh4U98fEI,4253
|
@@ -29,7 +30,7 @@ logger_36/constant/logger.py,sha256=ZQYX9JiPsoivwRgYNtdEqRKCagSKD88lRqvxP8MX1ZE,
|
|
29
30
|
logger_36/constant/memory.py,sha256=Q_E5tTWa-cGaNwrE_xmKa3BxQG6oJO6DHczrxc_M4sE,1817
|
30
31
|
logger_36/constant/message.py,sha256=YJOEzdI0ZjUOdHo3CsiS56FVPhrfNoQYvXuUkprH61g,2312
|
31
32
|
logger_36/constant/path.py,sha256=OfLh70Jyc8po9Ls34nQh_bRr3PXyQ3kF9ciR9QPhiqI,2213
|
32
|
-
logger_36/constant/record.py,sha256=
|
33
|
+
logger_36/constant/record.py,sha256=VMqGxVTbtHpRiDOsYiXEoyYOocYFm8vtcRY-7zXzJrk,1796
|
33
34
|
logger_36/constant/rule.py,sha256=tBKQgPTt6G_p5eInDdWoEEAvQFz4WMSt5THsS5jvk14,1779
|
34
35
|
logger_36/constant/system.py,sha256=pLlLXG5sepQlSUOo3TphaGrHg8xzJBp-GxpL2NPP47k,1904
|
35
36
|
logger_36/extension/html_.py,sha256=W9SyiYsaaYHUrHLGAAN2wiJGXUlwOBJ5gzdjmEcnF18,3342
|
@@ -37,16 +38,16 @@ logger_36/extension/line.py,sha256=joeojQX1bZJM53333mOEU3s-YC5ExGOrN9Cu9Lh5-FU,2
|
|
37
38
|
logger_36/instance/logger.py,sha256=X_U10RYU1h2Aa70D8hBnmFyJZtRILK16KN-GB4xkHMU,1782
|
38
39
|
logger_36/instance/loggers.py,sha256=inBk4KKrQ-z3szaopQ29-qQwh1iSc842sWo5J6zJoiM,1725
|
39
40
|
logger_36/task/inspection.py,sha256=ZgPcrPo3h_kEnM-UpHDLg7PAFfB2fqsLFdfmi6hlPVA,4484
|
40
|
-
logger_36/task/storage.py,sha256=
|
41
|
+
logger_36/task/storage.py,sha256=a50M628062iGEymuj5d9iKo7Ad01OXCZrEQnfNqy0gY,4486
|
41
42
|
logger_36/task/format/memory.py,sha256=J1Oy3jw8wjSp2kuiRUm_VFpzXOHX2FOc7nuRrCyrskw,3723
|
42
43
|
logger_36/task/format/message.py,sha256=Rm6zymVEEGcgKfmxMPXP7q3PtwZJKlXGhqZ5tnvlwxA,3502
|
43
44
|
logger_36/task/measure/chronos.py,sha256=7ijMZgP4EP18HbLV2yCxpNpRS9724Wyk523f-nkbhUM,2529
|
44
45
|
logger_36/task/measure/memory.py,sha256=kkPHEIUTUhkCOLrAt01eLJLnsnkl0nFPNhFZdIB_JAw,1991
|
45
46
|
logger_36/type/handler.py,sha256=4LCFZzI4OEH6lVBrBQ09ZIvF0nq-_j7OOVnujBDyDWA,6665
|
46
47
|
logger_36/type/issue.py,sha256=QHAYf7QgrjJUtF2D46z6X630qTgeP_0FE5hIwf54RsE,2688
|
47
|
-
logger_36/type/logger.py,sha256=
|
48
|
+
logger_36/type/logger.py,sha256=nh7EuJvdkaDrtdHPWIjot2a2hGfAzwufMWm9_2KoDXM,24645
|
48
49
|
logger_36/type/loggers.py,sha256=7EX7Sg_RlduBjdfFlNZmUfNeDloH1xU30Rdkg_-rXh8,3172
|
49
|
-
logger_36-2025.
|
50
|
-
logger_36-2025.
|
51
|
-
logger_36-2025.
|
52
|
-
logger_36-2025.
|
50
|
+
logger_36-2025.23.dist-info/METADATA,sha256=d94bUT9zjDr1Yjny2bsSobExZ1W0MXcIv2hX_DLLGC8,6529
|
51
|
+
logger_36-2025.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
52
|
+
logger_36-2025.23.dist-info/top_level.txt,sha256=sM95BTMWmslEEgR_1pzwZsOeSp8C_QBiu8ImbFr0XLc,10
|
53
|
+
logger_36-2025.23.dist-info/RECORD,,
|
File without changes
|
File without changes
|