haiway 0.18.1__py3-none-any.whl → 0.19.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.
- haiway/__init__.py +0 -2
- haiway/context/access.py +53 -64
- haiway/context/observability.py +57 -35
- haiway/helpers/__init__.py +1 -2
- haiway/helpers/observability.py +54 -35
- haiway/helpers/tracing.py +36 -45
- haiway/opentelemetry/observability.py +60 -38
- haiway/state/structure.py +3 -151
- haiway/utils/__init__.py +2 -0
- haiway/utils/formatting.py +148 -0
- {haiway-0.18.1.dist-info → haiway-0.19.0.dist-info}/METADATA +1 -1
- {haiway-0.18.1.dist-info → haiway-0.19.0.dist-info}/RECORD +14 -13
- {haiway-0.18.1.dist-info → haiway-0.19.0.dist-info}/WHEEL +0 -0
- {haiway-0.18.1.dist-info → haiway-0.19.0.dist-info}/licenses/LICENSE +0 -0
haiway/__init__.py
CHANGED
@@ -20,7 +20,6 @@ from haiway.context import (
|
|
20
20
|
)
|
21
21
|
from haiway.helpers import (
|
22
22
|
LoggerObservability,
|
23
|
-
ResultTrace,
|
24
23
|
asynchronous,
|
25
24
|
cache,
|
26
25
|
retry,
|
@@ -87,7 +86,6 @@ __all__ = (
|
|
87
86
|
"ObservabilityMetricRecording",
|
88
87
|
"ObservabilityScopeEntering",
|
89
88
|
"ObservabilityScopeExiting",
|
90
|
-
"ResultTrace",
|
91
89
|
"ScopeContext",
|
92
90
|
"ScopeIdentifier",
|
93
91
|
"State",
|
haiway/context/access.py
CHANGED
@@ -11,6 +11,7 @@ from collections.abc import (
|
|
11
11
|
Callable,
|
12
12
|
Coroutine,
|
13
13
|
Iterable,
|
14
|
+
Mapping,
|
14
15
|
)
|
15
16
|
from logging import Logger
|
16
17
|
from types import TracebackType
|
@@ -597,81 +598,69 @@ class ctx:
|
|
597
598
|
ObservabilityLevel.DEBUG, message, *args, exception=exception, **extra
|
598
599
|
)
|
599
600
|
|
601
|
+
@overload
|
600
602
|
@staticmethod
|
601
|
-
def
|
602
|
-
|
603
|
+
def record(
|
604
|
+
level: ObservabilityLevel = ObservabilityLevel.DEBUG,
|
603
605
|
/,
|
604
606
|
*,
|
605
|
-
|
606
|
-
|
607
|
-
) -> None:
|
608
|
-
"""
|
609
|
-
Record event within current scope context.
|
610
|
-
|
611
|
-
Parameters
|
612
|
-
----------
|
613
|
-
event: State
|
614
|
-
contents of event to be recorded.
|
607
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
608
|
+
) -> None: ...
|
615
609
|
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
)
|
610
|
+
@overload
|
611
|
+
@staticmethod
|
612
|
+
def record(
|
613
|
+
level: ObservabilityLevel = ObservabilityLevel.DEBUG,
|
614
|
+
/,
|
615
|
+
*,
|
616
|
+
event: str,
|
617
|
+
attributes: Mapping[str, ObservabilityAttribute] | None = None,
|
618
|
+
) -> None: ...
|
626
619
|
|
620
|
+
@overload
|
627
621
|
@staticmethod
|
628
|
-
def
|
629
|
-
|
622
|
+
def record(
|
623
|
+
level: ObservabilityLevel = ObservabilityLevel.DEBUG,
|
630
624
|
/,
|
631
625
|
*,
|
626
|
+
metric: str,
|
632
627
|
value: float | int,
|
633
628
|
unit: str | None = None,
|
634
|
-
|
635
|
-
) -> None:
|
636
|
-
"""
|
637
|
-
Record metric within current scope context.
|
638
|
-
|
639
|
-
Parameters
|
640
|
-
----------
|
641
|
-
metric: State
|
642
|
-
name of metric to be recorded.
|
643
|
-
value: float | int
|
644
|
-
value of metric to be recorded.
|
645
|
-
unit: str | None = None
|
646
|
-
unit of metric to be recorded.
|
647
|
-
|
648
|
-
Returns
|
649
|
-
-------
|
650
|
-
None
|
651
|
-
"""
|
652
|
-
|
653
|
-
ObservabilityContext.record_metric(
|
654
|
-
metric,
|
655
|
-
value=value,
|
656
|
-
unit=unit,
|
657
|
-
**extra,
|
658
|
-
)
|
629
|
+
attributes: Mapping[str, ObservabilityAttribute] | None = None,
|
630
|
+
) -> None: ...
|
659
631
|
|
660
632
|
@staticmethod
|
661
|
-
def
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
633
|
+
def record(
|
634
|
+
level: ObservabilityLevel = ObservabilityLevel.DEBUG,
|
635
|
+
/,
|
636
|
+
*,
|
637
|
+
event: str | None = None,
|
638
|
+
metric: str | None = None,
|
639
|
+
value: float | int | None = None,
|
640
|
+
unit: str | None = None,
|
641
|
+
attributes: Mapping[str, ObservabilityAttribute] | None = None,
|
642
|
+
) -> None:
|
643
|
+
if event is not None:
|
644
|
+
assert metric is None # nosec: B101
|
645
|
+
ObservabilityContext.record_event(
|
646
|
+
level,
|
647
|
+
event,
|
648
|
+
attributes=attributes or {},
|
649
|
+
)
|
669
650
|
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
651
|
+
elif metric is not None:
|
652
|
+
assert event is None # nosec: B101
|
653
|
+
assert value is not None # nosec: B101
|
654
|
+
ObservabilityContext.record_metric(
|
655
|
+
level,
|
656
|
+
metric,
|
657
|
+
value=value,
|
658
|
+
unit=unit,
|
659
|
+
attributes=attributes or {},
|
660
|
+
)
|
674
661
|
|
675
|
-
|
676
|
-
|
677
|
-
|
662
|
+
else:
|
663
|
+
ObservabilityContext.record_attributes(
|
664
|
+
level,
|
665
|
+
attributes=attributes or {},
|
666
|
+
)
|
haiway/context/observability.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from collections.abc import Sequence
|
1
|
+
from collections.abc import Mapping, Sequence
|
2
2
|
from contextvars import ContextVar, Token
|
3
3
|
from enum import IntEnum
|
4
4
|
from logging import DEBUG as DEBUG_LOGGING
|
@@ -10,9 +10,9 @@ from types import TracebackType
|
|
10
10
|
from typing import Any, Final, Protocol, Self, final, runtime_checkable
|
11
11
|
|
12
12
|
from haiway.context.identifier import ScopeIdentifier
|
13
|
-
|
14
|
-
# from haiway.context.logging import LoggerContext
|
15
13
|
from haiway.state import State
|
14
|
+
from haiway.types import Missing
|
15
|
+
from haiway.utils.formatting import format_str
|
16
16
|
|
17
17
|
__all__ = (
|
18
18
|
"DEBUG",
|
@@ -46,7 +46,16 @@ INFO: Final[int] = ObservabilityLevel.INFO
|
|
46
46
|
DEBUG: Final[int] = ObservabilityLevel.DEBUG
|
47
47
|
|
48
48
|
type ObservabilityAttribute = (
|
49
|
-
Sequence[str]
|
49
|
+
Sequence[str]
|
50
|
+
| Sequence[float]
|
51
|
+
| Sequence[int]
|
52
|
+
| Sequence[bool]
|
53
|
+
| str
|
54
|
+
| float
|
55
|
+
| int
|
56
|
+
| bool
|
57
|
+
| None
|
58
|
+
| Missing
|
50
59
|
)
|
51
60
|
|
52
61
|
|
@@ -60,7 +69,6 @@ class ObservabilityLogRecording(Protocol):
|
|
60
69
|
message: str,
|
61
70
|
*args: Any,
|
62
71
|
exception: BaseException | None,
|
63
|
-
**extra: Any,
|
64
72
|
) -> None: ...
|
65
73
|
|
66
74
|
|
@@ -70,10 +78,10 @@ class ObservabilityEventRecording(Protocol):
|
|
70
78
|
self,
|
71
79
|
scope: ScopeIdentifier,
|
72
80
|
/,
|
73
|
-
*,
|
74
81
|
level: ObservabilityLevel,
|
75
|
-
|
76
|
-
|
82
|
+
*,
|
83
|
+
event: str,
|
84
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
77
85
|
) -> None: ...
|
78
86
|
|
79
87
|
|
@@ -83,11 +91,12 @@ class ObservabilityMetricRecording(Protocol):
|
|
83
91
|
self,
|
84
92
|
scope: ScopeIdentifier,
|
85
93
|
/,
|
94
|
+
level: ObservabilityLevel,
|
86
95
|
*,
|
87
96
|
metric: str,
|
88
97
|
value: float | int,
|
89
98
|
unit: str | None,
|
90
|
-
|
99
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
91
100
|
) -> None: ...
|
92
101
|
|
93
102
|
|
@@ -97,7 +106,8 @@ class ObservabilityAttributesRecording(Protocol):
|
|
97
106
|
self,
|
98
107
|
scope: ScopeIdentifier,
|
99
108
|
/,
|
100
|
-
|
109
|
+
level: ObservabilityLevel,
|
110
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
101
111
|
) -> None: ...
|
102
112
|
|
103
113
|
|
@@ -209,7 +219,6 @@ def _logger_observability(
|
|
209
219
|
message: str,
|
210
220
|
*args: Any,
|
211
221
|
exception: BaseException | None,
|
212
|
-
**extra: Any,
|
213
222
|
) -> None:
|
214
223
|
logger.log(
|
215
224
|
level,
|
@@ -221,42 +230,51 @@ def _logger_observability(
|
|
221
230
|
def event_recording(
|
222
231
|
scope: ScopeIdentifier,
|
223
232
|
/,
|
224
|
-
*,
|
225
233
|
level: ObservabilityLevel,
|
226
|
-
|
227
|
-
|
234
|
+
*,
|
235
|
+
event: str,
|
236
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
228
237
|
) -> None:
|
229
238
|
logger.log(
|
230
239
|
level,
|
231
|
-
f"{scope.unique_name} Recorded event
|
240
|
+
f"{scope.unique_name} Recorded event: {event} {format_str(attributes)}",
|
232
241
|
)
|
233
242
|
|
234
243
|
def metric_recording(
|
235
244
|
scope: ScopeIdentifier,
|
236
245
|
/,
|
246
|
+
level: ObservabilityLevel,
|
237
247
|
*,
|
238
248
|
metric: str,
|
239
249
|
value: float | int,
|
240
250
|
unit: str | None,
|
241
|
-
|
251
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
242
252
|
) -> None:
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
253
|
+
if attributes:
|
254
|
+
logger.log(
|
255
|
+
level,
|
256
|
+
f"{scope.unique_name} Recorded metric: {metric}={value}{unit or ''}"
|
257
|
+
f"\n{format_str(attributes)}",
|
258
|
+
)
|
259
|
+
|
260
|
+
else:
|
261
|
+
logger.log(
|
262
|
+
level,
|
263
|
+
f"{scope.unique_name} Recorded metric: {metric}={value}{unit or ''}",
|
264
|
+
)
|
247
265
|
|
248
266
|
def attributes_recording(
|
249
267
|
scope: ScopeIdentifier,
|
250
268
|
/,
|
251
|
-
|
269
|
+
level: ObservabilityLevel,
|
270
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
252
271
|
) -> None:
|
253
272
|
if not attributes:
|
254
273
|
return
|
255
274
|
|
256
275
|
logger.log(
|
257
|
-
|
258
|
-
f"{scope.unique_name} Recorded attributes:"
|
259
|
-
f"\n{'\n'.join([f'{k}: {v}' for k, v in attributes.items()])}",
|
276
|
+
level,
|
277
|
+
f"{scope.unique_name} Recorded attributes: {format_str(attributes)}",
|
260
278
|
)
|
261
279
|
|
262
280
|
def scope_entering[Metric: State](
|
@@ -349,7 +367,6 @@ class ObservabilityContext:
|
|
349
367
|
/,
|
350
368
|
*args: Any,
|
351
369
|
exception: BaseException | None,
|
352
|
-
**extra: Any,
|
353
370
|
) -> None:
|
354
371
|
try: # catch exceptions - we don't wan't to blow up on observability
|
355
372
|
context: Self = cls._context.get()
|
@@ -361,7 +378,6 @@ class ObservabilityContext:
|
|
361
378
|
message,
|
362
379
|
*args,
|
363
380
|
exception=exception,
|
364
|
-
**extra,
|
365
381
|
)
|
366
382
|
|
367
383
|
except LookupError:
|
@@ -375,11 +391,11 @@ class ObservabilityContext:
|
|
375
391
|
@classmethod
|
376
392
|
def record_event(
|
377
393
|
cls,
|
378
|
-
|
394
|
+
level: ObservabilityLevel,
|
395
|
+
event: str,
|
379
396
|
/,
|
380
397
|
*,
|
381
|
-
|
382
|
-
**extra: Any,
|
398
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
383
399
|
) -> None:
|
384
400
|
try: # catch exceptions - we don't wan't to blow up on observability
|
385
401
|
context: Self = cls._context.get()
|
@@ -389,7 +405,7 @@ class ObservabilityContext:
|
|
389
405
|
context._scope,
|
390
406
|
level=level,
|
391
407
|
event=event,
|
392
|
-
|
408
|
+
attributes=attributes,
|
393
409
|
)
|
394
410
|
|
395
411
|
except Exception as exc:
|
@@ -402,12 +418,13 @@ class ObservabilityContext:
|
|
402
418
|
@classmethod
|
403
419
|
def record_metric(
|
404
420
|
cls,
|
421
|
+
level: ObservabilityLevel,
|
405
422
|
metric: str,
|
406
423
|
/,
|
407
424
|
*,
|
408
425
|
value: float | int,
|
409
426
|
unit: str | None,
|
410
|
-
|
427
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
411
428
|
) -> None:
|
412
429
|
try: # catch exceptions - we don't wan't to blow up on observability
|
413
430
|
context: Self = cls._context.get()
|
@@ -415,10 +432,11 @@ class ObservabilityContext:
|
|
415
432
|
if context.observability is not None:
|
416
433
|
context.observability.metric_recording(
|
417
434
|
context._scope,
|
435
|
+
level=level,
|
418
436
|
metric=metric,
|
419
437
|
value=value,
|
420
438
|
unit=unit,
|
421
|
-
|
439
|
+
attributes=attributes,
|
422
440
|
)
|
423
441
|
|
424
442
|
except Exception as exc:
|
@@ -431,7 +449,10 @@ class ObservabilityContext:
|
|
431
449
|
@classmethod
|
432
450
|
def record_attributes(
|
433
451
|
cls,
|
434
|
-
|
452
|
+
level: ObservabilityLevel,
|
453
|
+
/,
|
454
|
+
*,
|
455
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
435
456
|
) -> None:
|
436
457
|
try: # catch exceptions - we don't wan't to blow up on observability
|
437
458
|
context: Self = cls._context.get()
|
@@ -439,13 +460,14 @@ class ObservabilityContext:
|
|
439
460
|
if context.observability is not None:
|
440
461
|
context.observability.attributes_recording(
|
441
462
|
context._scope,
|
442
|
-
|
463
|
+
level=level,
|
464
|
+
attributes=attributes,
|
443
465
|
)
|
444
466
|
|
445
467
|
except Exception as exc:
|
446
468
|
cls.record_log(
|
447
469
|
ERROR,
|
448
|
-
|
470
|
+
"Failed to record attributes",
|
449
471
|
exception=exc,
|
450
472
|
)
|
451
473
|
|
haiway/helpers/__init__.py
CHANGED
@@ -4,14 +4,13 @@ from haiway.helpers.observability import LoggerObservability
|
|
4
4
|
from haiway.helpers.retries import retry
|
5
5
|
from haiway.helpers.throttling import throttle
|
6
6
|
from haiway.helpers.timeouted import timeout
|
7
|
-
from haiway.helpers.tracing import
|
7
|
+
from haiway.helpers.tracing import traced
|
8
8
|
|
9
9
|
__all__ = (
|
10
10
|
"CacheMakeKey",
|
11
11
|
"CacheRead",
|
12
12
|
"CacheWrite",
|
13
13
|
"LoggerObservability",
|
14
|
-
"ResultTrace",
|
15
14
|
"asynchronous",
|
16
15
|
"cache",
|
17
16
|
"retry",
|
haiway/helpers/observability.py
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
from collections.abc import
|
2
|
-
from logging import Logger
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from logging import Logger, getLogger
|
3
3
|
from time import monotonic
|
4
4
|
from typing import Any
|
5
5
|
|
6
6
|
from haiway.context import Observability, ObservabilityLevel, ScopeIdentifier
|
7
|
+
from haiway.context.observability import ObservabilityAttribute
|
7
8
|
from haiway.state import State
|
9
|
+
from haiway.utils.formatting import format_str
|
8
10
|
|
9
11
|
__all__ = ("LoggerObservability",)
|
10
12
|
|
@@ -62,12 +64,13 @@ class ScopeStore:
|
|
62
64
|
|
63
65
|
|
64
66
|
def LoggerObservability( # noqa: C901, PLR0915
|
65
|
-
logger: Logger,
|
67
|
+
logger: Logger | None = None,
|
66
68
|
/,
|
67
69
|
*,
|
68
|
-
|
70
|
+
debug_context: bool = __debug__,
|
69
71
|
) -> Observability:
|
70
72
|
root_scope: ScopeIdentifier | None = None
|
73
|
+
root_logger: Logger | None = logger
|
71
74
|
scopes: dict[str, ScopeStore] = {}
|
72
75
|
|
73
76
|
def log_recording(
|
@@ -77,12 +80,12 @@ def LoggerObservability( # noqa: C901, PLR0915
|
|
77
80
|
message: str,
|
78
81
|
*args: Any,
|
79
82
|
exception: BaseException | None,
|
80
|
-
**extra: Any,
|
81
83
|
) -> None:
|
82
84
|
assert root_scope is not None # nosec: B101
|
85
|
+
assert root_logger is not None # nosec: B101
|
83
86
|
assert scope.scope_id in scopes # nosec: B101
|
84
87
|
|
85
|
-
|
88
|
+
root_logger.log(
|
86
89
|
level,
|
87
90
|
f"{scope.unique_name} {message}",
|
88
91
|
*args,
|
@@ -92,19 +95,20 @@ def LoggerObservability( # noqa: C901, PLR0915
|
|
92
95
|
def event_recording(
|
93
96
|
scope: ScopeIdentifier,
|
94
97
|
/,
|
95
|
-
*,
|
96
98
|
level: ObservabilityLevel,
|
97
|
-
|
98
|
-
|
99
|
+
*,
|
100
|
+
event: str,
|
101
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
99
102
|
) -> None:
|
100
103
|
assert root_scope is not None # nosec: B101
|
104
|
+
assert root_logger is not None # nosec: B101
|
101
105
|
assert scope.scope_id in scopes # nosec: B101
|
102
106
|
|
103
|
-
event_str: str = f"Event
|
104
|
-
if
|
107
|
+
event_str: str = f"Event: {event} {format_str(attributes)}"
|
108
|
+
if debug_context: # store only for summary
|
105
109
|
scopes[scope.scope_id].store.append(event_str)
|
106
110
|
|
107
|
-
|
111
|
+
root_logger.log(
|
108
112
|
level,
|
109
113
|
f"{scope.unique_name} {event_str}",
|
110
114
|
)
|
@@ -112,41 +116,50 @@ def LoggerObservability( # noqa: C901, PLR0915
|
|
112
116
|
def metric_recording(
|
113
117
|
scope: ScopeIdentifier,
|
114
118
|
/,
|
119
|
+
level: ObservabilityLevel,
|
115
120
|
*,
|
116
121
|
metric: str,
|
117
122
|
value: float | int,
|
118
123
|
unit: str | None,
|
119
|
-
|
124
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
120
125
|
) -> None:
|
121
126
|
assert root_scope is not None # nosec: B101
|
127
|
+
assert root_logger is not None # nosec: B101
|
122
128
|
assert scope.scope_id in scopes # nosec: B101
|
123
129
|
|
124
|
-
metric_str: str
|
125
|
-
if
|
130
|
+
metric_str: str
|
131
|
+
if attributes:
|
132
|
+
metric_str = f"Metric: {metric}={value}{unit or ''}\n{format_str(attributes)}"
|
133
|
+
|
134
|
+
else:
|
135
|
+
metric_str = f"Metric: {metric}={value}{unit or ''}"
|
136
|
+
|
137
|
+
if debug_context: # store only for summary
|
126
138
|
scopes[scope.scope_id].store.append(metric_str)
|
127
139
|
|
128
|
-
|
129
|
-
|
140
|
+
root_logger.log(
|
141
|
+
level,
|
130
142
|
f"{scope.unique_name} {metric_str}",
|
131
143
|
)
|
132
144
|
|
133
145
|
def attributes_recording(
|
134
146
|
scope: ScopeIdentifier,
|
135
147
|
/,
|
136
|
-
|
148
|
+
level: ObservabilityLevel,
|
149
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
137
150
|
) -> None:
|
151
|
+
assert root_scope is not None # nosec: B101
|
152
|
+
assert root_logger is not None # nosec: B101
|
153
|
+
|
138
154
|
if not attributes:
|
139
155
|
return
|
140
156
|
|
141
|
-
attributes_str: str = (
|
142
|
-
|
143
|
-
f"\n{'\n'.join([f'{k}: {v}' for k, v in attributes.items()])}"
|
144
|
-
)
|
145
|
-
if summarize_context: # store only for summary
|
157
|
+
attributes_str: str = f"Attributes: {format_str(attributes)}"
|
158
|
+
if debug_context: # store only for summary
|
146
159
|
scopes[scope.scope_id].store.append(attributes_str)
|
147
160
|
|
148
|
-
|
149
|
-
|
161
|
+
root_logger.log(
|
162
|
+
level,
|
150
163
|
attributes_str,
|
151
164
|
)
|
152
165
|
|
@@ -158,18 +171,21 @@ def LoggerObservability( # noqa: C901, PLR0915
|
|
158
171
|
scope_store: ScopeStore = ScopeStore(scope)
|
159
172
|
scopes[scope.scope_id] = scope_store
|
160
173
|
|
161
|
-
logger.log(
|
162
|
-
ObservabilityLevel.INFO,
|
163
|
-
f"{scope.unique_name} Entering scope: {scope.label}",
|
164
|
-
)
|
165
|
-
|
166
174
|
nonlocal root_scope
|
175
|
+
nonlocal root_logger
|
167
176
|
if root_scope is None:
|
168
177
|
root_scope = scope
|
178
|
+
root_logger = logger or getLogger(scope.label)
|
169
179
|
|
170
180
|
else:
|
171
181
|
scopes[scope.parent_id].nested.append(scope_store)
|
172
182
|
|
183
|
+
assert root_logger is not None # nosec: B101
|
184
|
+
root_logger.log(
|
185
|
+
ObservabilityLevel.INFO,
|
186
|
+
f"{scope.unique_name} Entering scope: {scope.label}",
|
187
|
+
)
|
188
|
+
|
173
189
|
def scope_exiting[Metric: State](
|
174
190
|
scope: ScopeIdentifier,
|
175
191
|
/,
|
@@ -177,8 +193,10 @@ def LoggerObservability( # noqa: C901, PLR0915
|
|
177
193
|
exception: BaseException | None,
|
178
194
|
) -> None:
|
179
195
|
nonlocal root_scope
|
196
|
+
nonlocal root_logger
|
180
197
|
nonlocal scopes
|
181
198
|
assert root_scope is not None # nosec: B101
|
199
|
+
assert root_logger is not None # nosec: B101
|
182
200
|
assert scope.scope_id in scopes # nosec: B101
|
183
201
|
|
184
202
|
scopes[scope.scope_id].exit()
|
@@ -186,15 +204,15 @@ def LoggerObservability( # noqa: C901, PLR0915
|
|
186
204
|
if not scopes[scope.scope_id].try_complete():
|
187
205
|
return # not completed yet or already completed
|
188
206
|
|
189
|
-
|
207
|
+
root_logger.log(
|
190
208
|
ObservabilityLevel.INFO,
|
191
209
|
f"{scope.unique_name} Exiting scope: {scope.label}",
|
192
210
|
)
|
193
211
|
metric_str: str = f"Metric - scope_time:{scopes[scope.scope_id].time:.3f}s"
|
194
|
-
if
|
212
|
+
if debug_context: # store only for summary
|
195
213
|
scopes[scope.scope_id].store.append(metric_str)
|
196
214
|
|
197
|
-
|
215
|
+
root_logger.log(
|
198
216
|
ObservabilityLevel.INFO,
|
199
217
|
f"{scope.unique_name} {metric_str}",
|
200
218
|
)
|
@@ -206,14 +224,15 @@ def LoggerObservability( # noqa: C901, PLR0915
|
|
206
224
|
|
207
225
|
# check for root completion
|
208
226
|
if scopes[root_scope.scope_id].completed:
|
209
|
-
if
|
210
|
-
|
227
|
+
if debug_context:
|
228
|
+
root_logger.log(
|
211
229
|
ObservabilityLevel.DEBUG,
|
212
230
|
f"Observability summary:\n{_tree_summary(scopes[root_scope.scope_id])}",
|
213
231
|
)
|
214
232
|
|
215
233
|
# finished root - cleanup state
|
216
234
|
root_scope = None
|
235
|
+
root_logger = None
|
217
236
|
scopes = {}
|
218
237
|
|
219
238
|
return Observability(
|