haiway 0.17.0__py3-none-any.whl → 0.18.1__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 +24 -18
- haiway/context/__init__.py +23 -13
- haiway/context/access.py +127 -91
- haiway/context/disposables.py +2 -2
- haiway/context/identifier.py +4 -5
- haiway/context/observability.py +526 -0
- haiway/context/state.py +2 -2
- haiway/context/tasks.py +1 -3
- haiway/context/types.py +2 -2
- haiway/helpers/__init__.py +5 -7
- haiway/helpers/asynchrony.py +2 -2
- haiway/helpers/caching.py +2 -2
- haiway/helpers/observability.py +244 -0
- haiway/helpers/retries.py +1 -3
- haiway/helpers/throttling.py +1 -3
- haiway/helpers/timeouted.py +1 -3
- haiway/helpers/tracing.py +21 -35
- haiway/opentelemetry/__init__.py +3 -0
- haiway/opentelemetry/observability.py +452 -0
- haiway/state/__init__.py +2 -2
- haiway/state/attributes.py +2 -2
- haiway/state/path.py +1 -3
- haiway/state/requirement.py +1 -3
- haiway/state/structure.py +161 -30
- haiway/state/validation.py +2 -2
- haiway/types/__init__.py +2 -2
- haiway/types/default.py +2 -2
- haiway/types/frozen.py +1 -3
- haiway/types/missing.py +2 -2
- haiway/utils/__init__.py +2 -2
- haiway/utils/always.py +2 -2
- haiway/utils/collections.py +2 -2
- haiway/utils/env.py +2 -2
- haiway/utils/freezing.py +1 -3
- haiway/utils/logs.py +1 -3
- haiway/utils/mimic.py +1 -3
- haiway/utils/noop.py +2 -2
- haiway/utils/queue.py +1 -3
- haiway/utils/stream.py +1 -3
- {haiway-0.17.0.dist-info → haiway-0.18.1.dist-info}/METADATA +9 -5
- haiway-0.18.1.dist-info/RECORD +44 -0
- haiway/context/logging.py +0 -242
- haiway/context/metrics.py +0 -176
- haiway/helpers/metrics.py +0 -465
- haiway-0.17.0.dist-info/RECORD +0 -43
- {haiway-0.17.0.dist-info → haiway-0.18.1.dist-info}/WHEEL +0 -0
- {haiway-0.17.0.dist-info → haiway-0.18.1.dist-info}/licenses/LICENSE +0 -0
haiway/__init__.py
CHANGED
@@ -1,22 +1,25 @@
|
|
1
1
|
from haiway.context import (
|
2
2
|
Disposable,
|
3
3
|
Disposables,
|
4
|
-
MetricsContext,
|
5
|
-
MetricsHandler,
|
6
|
-
MetricsRecording,
|
7
|
-
MetricsScopeEntering,
|
8
|
-
MetricsScopeExiting,
|
9
4
|
MissingContext,
|
10
5
|
MissingState,
|
6
|
+
Observability,
|
7
|
+
ObservabilityAttribute,
|
8
|
+
ObservabilityAttributesRecording,
|
9
|
+
ObservabilityContext,
|
10
|
+
ObservabilityEventRecording,
|
11
|
+
ObservabilityLevel,
|
12
|
+
ObservabilityLogRecording,
|
13
|
+
ObservabilityMetricRecording,
|
14
|
+
ObservabilityScopeEntering,
|
15
|
+
ObservabilityScopeExiting,
|
11
16
|
ScopeContext,
|
12
17
|
ScopeIdentifier,
|
13
18
|
StateContext,
|
14
19
|
ctx,
|
15
20
|
)
|
16
21
|
from haiway.helpers import (
|
17
|
-
|
18
|
-
MetricsHolder,
|
19
|
-
MetricsLogger,
|
22
|
+
LoggerObservability,
|
20
23
|
ResultTrace,
|
21
24
|
asynchronous,
|
22
25
|
cache,
|
@@ -60,9 +63,8 @@ from haiway.utils import (
|
|
60
63
|
without_missing,
|
61
64
|
)
|
62
65
|
|
63
|
-
__all__ =
|
66
|
+
__all__ = (
|
64
67
|
"MISSING",
|
65
|
-
"ArgumentsTrace",
|
66
68
|
"AsyncQueue",
|
67
69
|
"AsyncStream",
|
68
70
|
"AttributePath",
|
@@ -71,16 +73,20 @@ __all__ = [
|
|
71
73
|
"DefaultValue",
|
72
74
|
"Disposable",
|
73
75
|
"Disposables",
|
74
|
-
"
|
75
|
-
"MetricsHandler",
|
76
|
-
"MetricsHolder",
|
77
|
-
"MetricsLogger",
|
78
|
-
"MetricsRecording",
|
79
|
-
"MetricsScopeEntering",
|
80
|
-
"MetricsScopeExiting",
|
76
|
+
"LoggerObservability",
|
81
77
|
"Missing",
|
82
78
|
"MissingContext",
|
83
79
|
"MissingState",
|
80
|
+
"Observability",
|
81
|
+
"ObservabilityAttribute",
|
82
|
+
"ObservabilityAttributesRecording",
|
83
|
+
"ObservabilityContext",
|
84
|
+
"ObservabilityEventRecording",
|
85
|
+
"ObservabilityLevel",
|
86
|
+
"ObservabilityLogRecording",
|
87
|
+
"ObservabilityMetricRecording",
|
88
|
+
"ObservabilityScopeEntering",
|
89
|
+
"ObservabilityScopeExiting",
|
84
90
|
"ResultTrace",
|
85
91
|
"ScopeContext",
|
86
92
|
"ScopeIdentifier",
|
@@ -116,4 +122,4 @@ __all__ = [
|
|
116
122
|
"when_missing",
|
117
123
|
"without_missing",
|
118
124
|
"wrap_async",
|
119
|
-
|
125
|
+
)
|
haiway/context/__init__.py
CHANGED
@@ -1,28 +1,38 @@
|
|
1
1
|
from haiway.context.access import ScopeContext, ctx
|
2
2
|
from haiway.context.disposables import Disposable, Disposables
|
3
3
|
from haiway.context.identifier import ScopeIdentifier
|
4
|
-
from haiway.context.
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
from haiway.context.observability import (
|
5
|
+
Observability,
|
6
|
+
ObservabilityAttribute,
|
7
|
+
ObservabilityAttributesRecording,
|
8
|
+
ObservabilityContext,
|
9
|
+
ObservabilityEventRecording,
|
10
|
+
ObservabilityLevel,
|
11
|
+
ObservabilityLogRecording,
|
12
|
+
ObservabilityMetricRecording,
|
13
|
+
ObservabilityScopeEntering,
|
14
|
+
ObservabilityScopeExiting,
|
10
15
|
)
|
11
16
|
from haiway.context.state import StateContext
|
12
17
|
from haiway.context.types import MissingContext, MissingState
|
13
18
|
|
14
|
-
__all__ =
|
19
|
+
__all__ = (
|
15
20
|
"Disposable",
|
16
21
|
"Disposables",
|
17
|
-
"MetricsContext",
|
18
|
-
"MetricsHandler",
|
19
|
-
"MetricsRecording",
|
20
|
-
"MetricsScopeEntering",
|
21
|
-
"MetricsScopeExiting",
|
22
22
|
"MissingContext",
|
23
23
|
"MissingState",
|
24
|
+
"Observability",
|
25
|
+
"ObservabilityAttribute",
|
26
|
+
"ObservabilityAttributesRecording",
|
27
|
+
"ObservabilityContext",
|
28
|
+
"ObservabilityEventRecording",
|
29
|
+
"ObservabilityLevel",
|
30
|
+
"ObservabilityLogRecording",
|
31
|
+
"ObservabilityMetricRecording",
|
32
|
+
"ObservabilityScopeEntering",
|
33
|
+
"ObservabilityScopeExiting",
|
24
34
|
"ScopeContext",
|
25
35
|
"ScopeIdentifier",
|
26
36
|
"StateContext",
|
27
37
|
"ctx",
|
28
|
-
|
38
|
+
)
|
haiway/context/access.py
CHANGED
@@ -18,17 +18,19 @@ from typing import Any, final, overload
|
|
18
18
|
|
19
19
|
from haiway.context.disposables import Disposable, Disposables
|
20
20
|
from haiway.context.identifier import ScopeIdentifier
|
21
|
-
from haiway.context.
|
22
|
-
|
21
|
+
from haiway.context.observability import (
|
22
|
+
Observability,
|
23
|
+
ObservabilityAttribute,
|
24
|
+
ObservabilityContext,
|
25
|
+
ObservabilityLevel,
|
26
|
+
)
|
23
27
|
from haiway.context.state import ScopeState, StateContext
|
24
28
|
from haiway.context.tasks import TaskGroupContext
|
25
29
|
from haiway.state import State
|
26
30
|
from haiway.utils import mimic_function
|
27
31
|
from haiway.utils.stream import AsyncStream
|
28
32
|
|
29
|
-
__all__ =
|
30
|
-
"ctx",
|
31
|
-
]
|
33
|
+
__all__ = ("ctx",)
|
32
34
|
|
33
35
|
|
34
36
|
@final
|
@@ -36,8 +38,7 @@ class ScopeContext:
|
|
36
38
|
__slots__ = (
|
37
39
|
"_disposables",
|
38
40
|
"_identifier",
|
39
|
-
"
|
40
|
-
"_metrics_context",
|
41
|
+
"_observability_context",
|
41
42
|
"_state_context",
|
42
43
|
"_task_group_context",
|
43
44
|
)
|
@@ -45,11 +46,10 @@ class ScopeContext:
|
|
45
46
|
def __init__(
|
46
47
|
self,
|
47
48
|
label: str,
|
48
|
-
logger: Logger | None,
|
49
49
|
task_group: TaskGroup | None,
|
50
50
|
state: tuple[State, ...],
|
51
51
|
disposables: Disposables | None,
|
52
|
-
|
52
|
+
observability: Observability | Logger | None,
|
53
53
|
) -> None:
|
54
54
|
self._identifier: ScopeIdentifier
|
55
55
|
object.__setattr__(
|
@@ -57,23 +57,6 @@ class ScopeContext:
|
|
57
57
|
"_identifier",
|
58
58
|
ScopeIdentifier.scope(label),
|
59
59
|
)
|
60
|
-
self._logger_context: LoggerContext
|
61
|
-
object.__setattr__(
|
62
|
-
self,
|
63
|
-
"_logger_context",
|
64
|
-
LoggerContext(
|
65
|
-
self._identifier,
|
66
|
-
logger=logger,
|
67
|
-
),
|
68
|
-
)
|
69
|
-
self._task_group_context: TaskGroupContext | None
|
70
|
-
object.__setattr__(
|
71
|
-
self,
|
72
|
-
"_task_group_context",
|
73
|
-
TaskGroupContext(task_group=task_group)
|
74
|
-
if task_group is not None or self._identifier.is_root
|
75
|
-
else None,
|
76
|
-
)
|
77
60
|
# prepare state context to capture current state
|
78
61
|
self._state_context: StateContext
|
79
62
|
object.__setattr__(
|
@@ -87,16 +70,24 @@ class ScopeContext:
|
|
87
70
|
"_disposables",
|
88
71
|
disposables,
|
89
72
|
)
|
90
|
-
self.
|
73
|
+
self._observability_context: ObservabilityContext
|
91
74
|
object.__setattr__(
|
92
75
|
self,
|
93
|
-
"
|
94
|
-
# pre-building
|
95
|
-
|
76
|
+
"_observability_context",
|
77
|
+
# pre-building observability context to ensure nested context registering
|
78
|
+
ObservabilityContext.scope(
|
96
79
|
self._identifier,
|
97
|
-
|
80
|
+
observability=observability,
|
98
81
|
),
|
99
82
|
)
|
83
|
+
self._task_group_context: TaskGroupContext | None
|
84
|
+
object.__setattr__(
|
85
|
+
self,
|
86
|
+
"_task_group_context",
|
87
|
+
TaskGroupContext(task_group=task_group)
|
88
|
+
if task_group is not None or self._identifier.is_root
|
89
|
+
else None,
|
90
|
+
)
|
100
91
|
|
101
92
|
def __setattr__(
|
102
93
|
self,
|
@@ -123,9 +114,8 @@ class ScopeContext:
|
|
123
114
|
), "Can't enter synchronous context with task group"
|
124
115
|
assert self._disposables is None, "Can't enter synchronous context with disposables" # nosec: B101
|
125
116
|
self._identifier.__enter__()
|
126
|
-
self.
|
117
|
+
self._observability_context.__enter__()
|
127
118
|
self._state_context.__enter__()
|
128
|
-
self._metrics_context.__enter__()
|
129
119
|
|
130
120
|
return self._identifier.trace_id
|
131
121
|
|
@@ -135,24 +125,16 @@ class ScopeContext:
|
|
135
125
|
exc_val: BaseException | None,
|
136
126
|
exc_tb: TracebackType | None,
|
137
127
|
) -> None:
|
138
|
-
self._metrics_context.__exit__(
|
139
|
-
exc_type=exc_type,
|
140
|
-
exc_val=exc_val,
|
141
|
-
exc_tb=exc_tb,
|
142
|
-
)
|
143
|
-
|
144
128
|
self._state_context.__exit__(
|
145
129
|
exc_type=exc_type,
|
146
130
|
exc_val=exc_val,
|
147
131
|
exc_tb=exc_tb,
|
148
132
|
)
|
149
|
-
|
150
|
-
self._logger_context.__exit__(
|
133
|
+
self._observability_context.__exit__(
|
151
134
|
exc_type=exc_type,
|
152
135
|
exc_val=exc_val,
|
153
136
|
exc_tb=exc_tb,
|
154
137
|
)
|
155
|
-
|
156
138
|
self._identifier.__exit__(
|
157
139
|
exc_type=exc_type,
|
158
140
|
exc_val=exc_val,
|
@@ -161,7 +143,7 @@ class ScopeContext:
|
|
161
143
|
|
162
144
|
async def __aenter__(self) -> str:
|
163
145
|
self._identifier.__enter__()
|
164
|
-
self.
|
146
|
+
self._observability_context.__enter__()
|
165
147
|
|
166
148
|
if task_group := self._task_group_context:
|
167
149
|
await task_group.__aenter__()
|
@@ -183,7 +165,6 @@ class ScopeContext:
|
|
183
165
|
)
|
184
166
|
|
185
167
|
self._state_context.__enter__()
|
186
|
-
self._metrics_context.__enter__()
|
187
168
|
|
188
169
|
return self._identifier.trace_id
|
189
170
|
|
@@ -207,19 +188,13 @@ class ScopeContext:
|
|
207
188
|
exc_tb=exc_tb,
|
208
189
|
)
|
209
190
|
|
210
|
-
self._metrics_context.__exit__(
|
211
|
-
exc_type=exc_type,
|
212
|
-
exc_val=exc_val,
|
213
|
-
exc_tb=exc_tb,
|
214
|
-
)
|
215
|
-
|
216
191
|
self._state_context.__exit__(
|
217
192
|
exc_type=exc_type,
|
218
193
|
exc_val=exc_val,
|
219
194
|
exc_tb=exc_tb,
|
220
195
|
)
|
221
196
|
|
222
|
-
self.
|
197
|
+
self._observability_context.__exit__(
|
223
198
|
exc_type=exc_type,
|
224
199
|
exc_val=exc_val,
|
225
200
|
exc_tb=exc_tb,
|
@@ -288,9 +263,8 @@ class ctx:
|
|
288
263
|
/,
|
289
264
|
*state: State,
|
290
265
|
disposables: Disposables | Iterable[Disposable] | None = None,
|
291
|
-
logger: Logger | None = None,
|
292
266
|
task_group: TaskGroup | None = None,
|
293
|
-
|
267
|
+
observability: Observability | Logger | None = None,
|
294
268
|
) -> ScopeContext:
|
295
269
|
"""
|
296
270
|
Prepare scope context with given parameters. When called within an existing context\
|
@@ -310,18 +284,14 @@ class ctx:
|
|
310
284
|
be added to the scope state. Using asynchronous context is required if any disposables\
|
311
285
|
were provided.
|
312
286
|
|
313
|
-
logger: Logger | None
|
314
|
-
logger used within the scope context, when not provided current logger will be used\
|
315
|
-
if any, otherwise the logger with the scope name will be requested.
|
316
|
-
|
317
287
|
task_group: TaskGroup | None
|
318
288
|
task group used for spawning and joining tasks within the context. Root scope will
|
319
289
|
always have task group created even when not set.
|
320
290
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
291
|
+
observability: Observability | Logger | None = None
|
292
|
+
observability solution responsible for recording and storing metrics, logs and events.\
|
293
|
+
Assigning observability within existing context will result in an error.
|
294
|
+
When not provided, logger with the scope name will be requested and used.
|
325
295
|
|
326
296
|
Returns
|
327
297
|
-------
|
@@ -343,11 +313,10 @@ class ctx:
|
|
343
313
|
|
344
314
|
return ScopeContext(
|
345
315
|
label=label,
|
346
|
-
logger=logger,
|
347
316
|
task_group=task_group,
|
348
317
|
state=state,
|
349
318
|
disposables=resolved_disposables,
|
350
|
-
|
319
|
+
observability=observability,
|
351
320
|
)
|
352
321
|
|
353
322
|
@staticmethod
|
@@ -492,33 +461,13 @@ class ctx:
|
|
492
461
|
default=default,
|
493
462
|
)
|
494
463
|
|
495
|
-
@staticmethod
|
496
|
-
def record(
|
497
|
-
metric: State,
|
498
|
-
/,
|
499
|
-
) -> None:
|
500
|
-
"""
|
501
|
-
Record metric within current scope context.
|
502
|
-
|
503
|
-
Parameters
|
504
|
-
----------
|
505
|
-
metric: State
|
506
|
-
value of metric to be recorded. When a metric implements __add__ it will be added to\
|
507
|
-
current value if any, otherwise subsequent calls may replace existing value.
|
508
|
-
|
509
|
-
Returns
|
510
|
-
-------
|
511
|
-
None
|
512
|
-
"""
|
513
|
-
|
514
|
-
MetricsContext.record(metric)
|
515
|
-
|
516
464
|
@staticmethod
|
517
465
|
def log_error(
|
518
466
|
message: str,
|
519
467
|
/,
|
520
468
|
*args: Any,
|
521
469
|
exception: BaseException | None = None,
|
470
|
+
**extra: Any,
|
522
471
|
) -> None:
|
523
472
|
"""
|
524
473
|
Log using ERROR level within current scope context. When there is no current scope\
|
@@ -540,10 +489,12 @@ class ctx:
|
|
540
489
|
None
|
541
490
|
"""
|
542
491
|
|
543
|
-
|
492
|
+
ObservabilityContext.record_log(
|
493
|
+
ObservabilityLevel.ERROR,
|
544
494
|
message,
|
545
495
|
*args,
|
546
496
|
exception=exception,
|
497
|
+
**extra,
|
547
498
|
)
|
548
499
|
|
549
500
|
@staticmethod
|
@@ -552,6 +503,7 @@ class ctx:
|
|
552
503
|
/,
|
553
504
|
*args: Any,
|
554
505
|
exception: Exception | None = None,
|
506
|
+
**extra: Any,
|
555
507
|
) -> None:
|
556
508
|
"""
|
557
509
|
Log using WARNING level within current scope context. When there is no current scope\
|
@@ -573,10 +525,12 @@ class ctx:
|
|
573
525
|
None
|
574
526
|
"""
|
575
527
|
|
576
|
-
|
528
|
+
ObservabilityContext.record_log(
|
529
|
+
ObservabilityLevel.WARNING,
|
577
530
|
message,
|
578
531
|
*args,
|
579
532
|
exception=exception,
|
533
|
+
**extra,
|
580
534
|
)
|
581
535
|
|
582
536
|
@staticmethod
|
@@ -584,6 +538,7 @@ class ctx:
|
|
584
538
|
message: str,
|
585
539
|
/,
|
586
540
|
*args: Any,
|
541
|
+
**extra: Any,
|
587
542
|
) -> None:
|
588
543
|
"""
|
589
544
|
Log using INFO level within current scope context. When there is no current scope\
|
@@ -602,9 +557,12 @@ class ctx:
|
|
602
557
|
None
|
603
558
|
"""
|
604
559
|
|
605
|
-
|
560
|
+
ObservabilityContext.record_log(
|
561
|
+
ObservabilityLevel.INFO,
|
606
562
|
message,
|
607
563
|
*args,
|
564
|
+
exception=None,
|
565
|
+
**extra,
|
608
566
|
)
|
609
567
|
|
610
568
|
@staticmethod
|
@@ -613,6 +571,7 @@ class ctx:
|
|
613
571
|
/,
|
614
572
|
*args: Any,
|
615
573
|
exception: Exception | None = None,
|
574
|
+
**extra: Any,
|
616
575
|
) -> None:
|
617
576
|
"""
|
618
577
|
Log using DEBUG level within current scope context. When there is no current scope\
|
@@ -634,8 +593,85 @@ class ctx:
|
|
634
593
|
None
|
635
594
|
"""
|
636
595
|
|
637
|
-
|
638
|
-
message,
|
639
|
-
|
640
|
-
|
596
|
+
ObservabilityContext.record_log(
|
597
|
+
ObservabilityLevel.DEBUG, message, *args, exception=exception, **extra
|
598
|
+
)
|
599
|
+
|
600
|
+
@staticmethod
|
601
|
+
def event(
|
602
|
+
event: State,
|
603
|
+
/,
|
604
|
+
*,
|
605
|
+
level: ObservabilityLevel = ObservabilityLevel.INFO,
|
606
|
+
**extra: Any,
|
607
|
+
) -> None:
|
608
|
+
"""
|
609
|
+
Record event within current scope context.
|
610
|
+
|
611
|
+
Parameters
|
612
|
+
----------
|
613
|
+
event: State
|
614
|
+
contents of event to be recorded.
|
615
|
+
|
616
|
+
Returns
|
617
|
+
-------
|
618
|
+
None
|
619
|
+
"""
|
620
|
+
|
621
|
+
ObservabilityContext.record_event(
|
622
|
+
event,
|
623
|
+
level=level,
|
624
|
+
**extra,
|
625
|
+
)
|
626
|
+
|
627
|
+
@staticmethod
|
628
|
+
def metric(
|
629
|
+
metric: str,
|
630
|
+
/,
|
631
|
+
*,
|
632
|
+
value: float | int,
|
633
|
+
unit: str | None = None,
|
634
|
+
**extra: Any,
|
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
|
+
)
|
659
|
+
|
660
|
+
@staticmethod
|
661
|
+
def attributes(**attributes: ObservabilityAttribute) -> None:
|
662
|
+
"""
|
663
|
+
Record attributes within current scope context.
|
664
|
+
|
665
|
+
Parameters
|
666
|
+
----------
|
667
|
+
**attributes: ObservabilityAttribute,
|
668
|
+
attributes to be recorded within current context.
|
669
|
+
|
670
|
+
Returns
|
671
|
+
-------
|
672
|
+
None
|
673
|
+
"""
|
674
|
+
|
675
|
+
ObservabilityContext.record_attributes(
|
676
|
+
**attributes,
|
641
677
|
)
|
haiway/context/disposables.py
CHANGED
haiway/context/identifier.py
CHANGED
@@ -3,9 +3,7 @@ from types import TracebackType
|
|
3
3
|
from typing import Any, Self, final
|
4
4
|
from uuid import uuid4
|
5
5
|
|
6
|
-
__all__ =
|
7
|
-
"ScopeIdentifier",
|
8
|
-
]
|
6
|
+
__all__ = ("ScopeIdentifier",)
|
9
7
|
|
10
8
|
|
11
9
|
@final
|
@@ -33,10 +31,11 @@ class ScopeIdentifier:
|
|
33
31
|
except LookupError:
|
34
32
|
# create root scope when missing
|
35
33
|
trace_id: str = uuid4().hex
|
34
|
+
scope_id: str = uuid4().hex
|
36
35
|
return cls(
|
37
36
|
label=label,
|
38
|
-
scope_id=
|
39
|
-
parent_id=
|
37
|
+
scope_id=scope_id,
|
38
|
+
parent_id=scope_id, # own id is parent_id for root
|
40
39
|
trace_id=trace_id,
|
41
40
|
)
|
42
41
|
|