haiway 0.24.3__py3-none-any.whl → 0.25.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 +4 -1
- haiway/context/__init__.py +4 -0
- haiway/context/access.py +214 -63
- haiway/context/disposables.py +5 -119
- haiway/context/identifier.py +19 -44
- haiway/context/observability.py +22 -142
- haiway/context/presets.py +337 -0
- haiway/context/state.py +38 -84
- haiway/context/tasks.py +7 -10
- haiway/helpers/observability.py +4 -6
- haiway/opentelemetry/observability.py +5 -5
- haiway/state/__init__.py +2 -0
- haiway/state/immutable.py +127 -0
- haiway/state/structure.py +63 -117
- haiway/state/validation.py +95 -60
- {haiway-0.24.3.dist-info → haiway-0.25.0.dist-info}/METADATA +1 -1
- {haiway-0.24.3.dist-info → haiway-0.25.0.dist-info}/RECORD +19 -17
- {haiway-0.24.3.dist-info → haiway-0.25.0.dist-info}/WHEEL +0 -0
- {haiway-0.24.3.dist-info → haiway-0.25.0.dist-info}/licenses/LICENSE +0 -0
haiway/context/identifier.py
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
from contextvars import ContextVar, Token
|
2
2
|
from types import TracebackType
|
3
|
-
from typing import Any,
|
3
|
+
from typing import Any, ClassVar, Self
|
4
4
|
from uuid import UUID, uuid4
|
5
5
|
|
6
|
+
from haiway.state import Immutable
|
7
|
+
|
6
8
|
__all__ = ("ScopeIdentifier",)
|
7
9
|
|
8
10
|
|
9
|
-
|
10
|
-
class ScopeIdentifier:
|
11
|
+
class ScopeIdentifier(Immutable):
|
11
12
|
"""
|
12
13
|
Identifies and manages scope context identities.
|
13
14
|
|
@@ -18,7 +19,7 @@ class ScopeIdentifier:
|
|
18
19
|
This class is immutable after instantiation.
|
19
20
|
"""
|
20
21
|
|
21
|
-
_context = ContextVar[Self]("ScopeIdentifier")
|
22
|
+
_context: ClassVar[ContextVar[Self]] = ContextVar[Self]("ScopeIdentifier")
|
22
23
|
|
23
24
|
@classmethod
|
24
25
|
def current(
|
@@ -30,7 +31,7 @@ class ScopeIdentifier:
|
|
30
31
|
@classmethod
|
31
32
|
def scope(
|
32
33
|
cls,
|
33
|
-
|
34
|
+
name: str,
|
34
35
|
/,
|
35
36
|
) -> Self:
|
36
37
|
"""
|
@@ -41,7 +42,7 @@ class ScopeIdentifier:
|
|
41
42
|
|
42
43
|
Parameters
|
43
44
|
----------
|
44
|
-
|
45
|
+
name: str
|
45
46
|
The name of the scope
|
46
47
|
|
47
48
|
Returns
|
@@ -58,82 +59,56 @@ class ScopeIdentifier:
|
|
58
59
|
|
59
60
|
scope_id: UUID = uuid4()
|
60
61
|
return cls(
|
61
|
-
|
62
|
+
name=name,
|
62
63
|
scope_id=scope_id,
|
63
64
|
parent_id=scope_id, # own id is parent_id for root
|
64
65
|
)
|
65
66
|
|
66
67
|
# create nested scope otherwise
|
67
68
|
return cls(
|
68
|
-
|
69
|
+
name=name,
|
69
70
|
scope_id=uuid4(),
|
70
71
|
parent_id=current.scope_id,
|
71
72
|
)
|
72
73
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
"unique_name",
|
79
|
-
)
|
74
|
+
parent_id: UUID
|
75
|
+
scope_id: UUID
|
76
|
+
name: str
|
77
|
+
unique_name: str
|
78
|
+
_token: Token[Self] | None = None
|
80
79
|
|
81
80
|
def __init__(
|
82
81
|
self,
|
83
82
|
parent_id: UUID,
|
84
83
|
scope_id: UUID,
|
85
|
-
|
84
|
+
name: str,
|
86
85
|
) -> None:
|
87
|
-
self.parent_id: UUID
|
88
86
|
object.__setattr__(
|
89
87
|
self,
|
90
88
|
"parent_id",
|
91
89
|
parent_id,
|
92
90
|
)
|
93
|
-
self.scope_id: UUID
|
94
91
|
object.__setattr__(
|
95
92
|
self,
|
96
93
|
"scope_id",
|
97
94
|
scope_id,
|
98
95
|
)
|
99
|
-
self.label: str
|
100
96
|
object.__setattr__(
|
101
97
|
self,
|
102
|
-
"
|
103
|
-
|
98
|
+
"name",
|
99
|
+
name,
|
104
100
|
)
|
105
|
-
self.unique_name: str
|
106
101
|
object.__setattr__(
|
107
102
|
self,
|
108
103
|
"unique_name",
|
109
|
-
f"[{
|
104
|
+
f"[{name}] [{scope_id}]",
|
110
105
|
)
|
111
|
-
self._token: Token[ScopeIdentifier] | None
|
112
106
|
object.__setattr__(
|
113
107
|
self,
|
114
108
|
"_token",
|
115
109
|
None,
|
116
110
|
)
|
117
111
|
|
118
|
-
def __setattr__(
|
119
|
-
self,
|
120
|
-
name: str,
|
121
|
-
value: Any,
|
122
|
-
) -> Any:
|
123
|
-
raise AttributeError(
|
124
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
125
|
-
f" attribute - '{name}' cannot be modified"
|
126
|
-
)
|
127
|
-
|
128
|
-
def __delattr__(
|
129
|
-
self,
|
130
|
-
name: str,
|
131
|
-
) -> None:
|
132
|
-
raise AttributeError(
|
133
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
134
|
-
f" attribute - '{name}' cannot be deleted"
|
135
|
-
)
|
136
|
-
|
137
112
|
@property
|
138
113
|
def is_root(self) -> bool:
|
139
114
|
"""
|
@@ -204,7 +179,7 @@ class ScopeIdentifier:
|
|
204
179
|
If this context is not active
|
205
180
|
"""
|
206
181
|
assert self._token is not None, "Unbalanced context enter/exit" # nosec: B101
|
207
|
-
ScopeIdentifier._context.reset(self._token)
|
182
|
+
ScopeIdentifier._context.reset(self._token) # pyright: ignore[reportArgumentType]
|
208
183
|
object.__setattr__(
|
209
184
|
self,
|
210
185
|
"_token",
|
haiway/context/observability.py
CHANGED
@@ -7,10 +7,11 @@ from logging import INFO as INFO_LOGGING
|
|
7
7
|
from logging import WARNING as WARNING_LOGGING
|
8
8
|
from logging import Logger, getLogger
|
9
9
|
from types import TracebackType
|
10
|
-
from typing import Any, Protocol, Self,
|
10
|
+
from typing import Any, ClassVar, Protocol, Self, runtime_checkable
|
11
11
|
from uuid import UUID, uuid4
|
12
12
|
|
13
13
|
from haiway.context.identifier import ScopeIdentifier
|
14
|
+
from haiway.state import Immutable
|
14
15
|
from haiway.types import Missing
|
15
16
|
from haiway.utils.formatting import format_str
|
16
17
|
|
@@ -190,7 +191,7 @@ class ObservabilityScopeExiting(Protocol):
|
|
190
191
|
) -> None: ...
|
191
192
|
|
192
193
|
|
193
|
-
class Observability: # avoiding State inheritance to prevent propagation as scope state
|
194
|
+
class Observability(Immutable): # avoiding State inheritance to prevent propagation as scope state
|
194
195
|
"""
|
195
196
|
Container for observability recording functions.
|
196
197
|
|
@@ -201,107 +202,13 @@ class Observability: # avoiding State inheritance to prevent propagation as sco
|
|
201
202
|
This class is immutable after initialization.
|
202
203
|
"""
|
203
204
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
"trace_identifying",
|
212
|
-
)
|
213
|
-
|
214
|
-
def __init__(
|
215
|
-
self,
|
216
|
-
trace_identifying: ObservabilityTraceIdentifying,
|
217
|
-
log_recording: ObservabilityLogRecording,
|
218
|
-
metric_recording: ObservabilityMetricRecording,
|
219
|
-
event_recording: ObservabilityEventRecording,
|
220
|
-
attributes_recording: ObservabilityAttributesRecording,
|
221
|
-
scope_entering: ObservabilityScopeEntering,
|
222
|
-
scope_exiting: ObservabilityScopeExiting,
|
223
|
-
) -> None:
|
224
|
-
"""
|
225
|
-
Initialize an Observability container with recording functions.
|
226
|
-
|
227
|
-
Parameters
|
228
|
-
----------
|
229
|
-
trace_identifying: ObservabilityTraceIdentifying
|
230
|
-
Function for identifying traces
|
231
|
-
log_recording: ObservabilityLogRecording
|
232
|
-
Function for recording log messages
|
233
|
-
metric_recording: ObservabilityMetricRecording
|
234
|
-
Function for recording metrics
|
235
|
-
event_recording: ObservabilityEventRecording
|
236
|
-
Function for recording events
|
237
|
-
attributes_recording: ObservabilityAttributesRecording
|
238
|
-
Function for recording attributes
|
239
|
-
scope_entering: ObservabilityScopeEntering
|
240
|
-
Function called when a scope is entered
|
241
|
-
scope_exiting: ObservabilityScopeExiting
|
242
|
-
Function called when a scope is exited
|
243
|
-
"""
|
244
|
-
self.trace_identifying: ObservabilityTraceIdentifying
|
245
|
-
object.__setattr__(
|
246
|
-
self,
|
247
|
-
"trace_identifying",
|
248
|
-
trace_identifying,
|
249
|
-
)
|
250
|
-
self.log_recording: ObservabilityLogRecording
|
251
|
-
object.__setattr__(
|
252
|
-
self,
|
253
|
-
"log_recording",
|
254
|
-
log_recording,
|
255
|
-
)
|
256
|
-
self.metric_recording: ObservabilityMetricRecording
|
257
|
-
object.__setattr__(
|
258
|
-
self,
|
259
|
-
"metric_recording",
|
260
|
-
metric_recording,
|
261
|
-
)
|
262
|
-
self.event_recording: ObservabilityEventRecording
|
263
|
-
object.__setattr__(
|
264
|
-
self,
|
265
|
-
"event_recording",
|
266
|
-
event_recording,
|
267
|
-
)
|
268
|
-
self.attributes_recording: ObservabilityAttributesRecording
|
269
|
-
object.__setattr__(
|
270
|
-
self,
|
271
|
-
"attributes_recording",
|
272
|
-
attributes_recording,
|
273
|
-
)
|
274
|
-
self.scope_entering: ObservabilityScopeEntering
|
275
|
-
object.__setattr__(
|
276
|
-
self,
|
277
|
-
"scope_entering",
|
278
|
-
scope_entering,
|
279
|
-
)
|
280
|
-
self.scope_exiting: ObservabilityScopeExiting
|
281
|
-
object.__setattr__(
|
282
|
-
self,
|
283
|
-
"scope_exiting",
|
284
|
-
scope_exiting,
|
285
|
-
)
|
286
|
-
|
287
|
-
def __setattr__(
|
288
|
-
self,
|
289
|
-
name: str,
|
290
|
-
value: Any,
|
291
|
-
) -> Any:
|
292
|
-
raise AttributeError(
|
293
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
294
|
-
f" attribute - '{name}' cannot be modified"
|
295
|
-
)
|
296
|
-
|
297
|
-
def __delattr__(
|
298
|
-
self,
|
299
|
-
name: str,
|
300
|
-
) -> None:
|
301
|
-
raise AttributeError(
|
302
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
303
|
-
f" attribute - '{name}' cannot be deleted"
|
304
|
-
)
|
205
|
+
trace_identifying: ObservabilityTraceIdentifying
|
206
|
+
log_recording: ObservabilityLogRecording
|
207
|
+
metric_recording: ObservabilityMetricRecording
|
208
|
+
event_recording: ObservabilityEventRecording
|
209
|
+
attributes_recording: ObservabilityAttributesRecording
|
210
|
+
scope_entering: ObservabilityScopeEntering
|
211
|
+
scope_exiting: ObservabilityScopeExiting
|
305
212
|
|
306
213
|
|
307
214
|
def _logger_observability(
|
@@ -408,7 +315,7 @@ def _logger_observability(
|
|
408
315
|
) -> None:
|
409
316
|
logger.log(
|
410
317
|
ObservabilityLevel.DEBUG,
|
411
|
-
f"[{trace_id_hex}] {scope.unique_name} Entering scope: {scope.
|
318
|
+
f"[{trace_id_hex}] {scope.unique_name} Entering scope: {scope.name}",
|
412
319
|
)
|
413
320
|
|
414
321
|
def scope_exiting(
|
@@ -419,7 +326,7 @@ def _logger_observability(
|
|
419
326
|
) -> None:
|
420
327
|
logger.log(
|
421
328
|
ObservabilityLevel.DEBUG,
|
422
|
-
f"{scope.unique_name} Exiting scope: {scope.
|
329
|
+
f"{scope.unique_name} Exiting scope: {scope.name}",
|
423
330
|
exc_info=exception,
|
424
331
|
)
|
425
332
|
|
@@ -434,8 +341,7 @@ def _logger_observability(
|
|
434
341
|
)
|
435
342
|
|
436
343
|
|
437
|
-
|
438
|
-
class ObservabilityContext:
|
344
|
+
class ObservabilityContext(Immutable):
|
439
345
|
"""
|
440
346
|
Context manager for observability within a scope.
|
441
347
|
|
@@ -446,7 +352,7 @@ class ObservabilityContext:
|
|
446
352
|
This class is immutable after initialization.
|
447
353
|
"""
|
448
354
|
|
449
|
-
_context = ContextVar[Self]("ObservabilityContext")
|
355
|
+
_context: ClassVar[ContextVar[Self]] = ContextVar[Self]("ObservabilityContext")
|
450
356
|
|
451
357
|
@classmethod
|
452
358
|
def scope(
|
@@ -486,7 +392,7 @@ class ObservabilityContext:
|
|
486
392
|
resolved_observability = observability
|
487
393
|
|
488
394
|
case None:
|
489
|
-
resolved_observability = _logger_observability(getLogger(scope.
|
395
|
+
resolved_observability = _logger_observability(getLogger(scope.name))
|
490
396
|
|
491
397
|
case Logger() as logger:
|
492
398
|
resolved_observability = _logger_observability(logger)
|
@@ -534,7 +440,7 @@ class ObservabilityContext:
|
|
534
440
|
Returns
|
535
441
|
-------
|
536
442
|
str
|
537
|
-
The
|
443
|
+
The string representation of the trace ID
|
538
444
|
|
539
445
|
Raises
|
540
446
|
------
|
@@ -542,12 +448,10 @@ class ObservabilityContext:
|
|
542
448
|
If called outside of any scope context
|
543
449
|
"""
|
544
450
|
try:
|
545
|
-
return (
|
546
|
-
cls._context.get()
|
547
|
-
.observability.trace_identifying(
|
451
|
+
return str(
|
452
|
+
cls._context.get().observability.trace_identifying(
|
548
453
|
scope_identifier if scope_identifier is not None else ScopeIdentifier.current()
|
549
454
|
)
|
550
|
-
.hex
|
551
455
|
)
|
552
456
|
|
553
457
|
except LookupError as exc:
|
@@ -728,55 +632,31 @@ class ObservabilityContext:
|
|
728
632
|
exception=exc,
|
729
633
|
)
|
730
634
|
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
"observability",
|
735
|
-
)
|
635
|
+
_scope: ScopeIdentifier
|
636
|
+
observability: Observability
|
637
|
+
_token: Token[Self] | None = None
|
736
638
|
|
737
639
|
def __init__(
|
738
640
|
self,
|
739
641
|
scope: ScopeIdentifier,
|
740
642
|
observability: Observability | None,
|
741
643
|
) -> None:
|
742
|
-
self._scope: ScopeIdentifier
|
743
644
|
object.__setattr__(
|
744
645
|
self,
|
745
646
|
"_scope",
|
746
647
|
scope,
|
747
648
|
)
|
748
|
-
self.observability: Observability
|
749
649
|
object.__setattr__(
|
750
650
|
self,
|
751
651
|
"observability",
|
752
652
|
observability,
|
753
653
|
)
|
754
|
-
self._token: Token[ObservabilityContext] | None
|
755
654
|
object.__setattr__(
|
756
655
|
self,
|
757
656
|
"_token",
|
758
657
|
None,
|
759
658
|
)
|
760
659
|
|
761
|
-
def __setattr__(
|
762
|
-
self,
|
763
|
-
name: str,
|
764
|
-
value: Any,
|
765
|
-
) -> Any:
|
766
|
-
raise AttributeError(
|
767
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
768
|
-
f" attribute - '{name}' cannot be modified"
|
769
|
-
)
|
770
|
-
|
771
|
-
def __delattr__(
|
772
|
-
self,
|
773
|
-
name: str,
|
774
|
-
) -> None:
|
775
|
-
raise AttributeError(
|
776
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
777
|
-
f" attribute - '{name}' cannot be deleted"
|
778
|
-
)
|
779
|
-
|
780
660
|
def __enter__(self) -> None:
|
781
661
|
"""
|
782
662
|
Enter this observability context.
|
@@ -822,7 +702,7 @@ class ObservabilityContext:
|
|
822
702
|
If the context is not active
|
823
703
|
"""
|
824
704
|
assert self._token is not None, "Unbalanced context enter/exit" # nosec: B101
|
825
|
-
ObservabilityContext._context.reset(self._token)
|
705
|
+
ObservabilityContext._context.reset(self._token) # pyright: ignore[reportArgumentType]
|
826
706
|
object.__setattr__(
|
827
707
|
self,
|
828
708
|
"_token",
|