ddeutil-workflow 0.0.73__py3-none-any.whl → 0.0.75__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.
- ddeutil/workflow/__about__.py +1 -1
- ddeutil/workflow/__cron.py +20 -12
- ddeutil/workflow/__init__.py +119 -10
- ddeutil/workflow/__types.py +53 -41
- ddeutil/workflow/api/__init__.py +74 -3
- ddeutil/workflow/api/routes/job.py +15 -29
- ddeutil/workflow/api/routes/logs.py +9 -9
- ddeutil/workflow/api/routes/workflows.py +3 -3
- ddeutil/workflow/audits.py +70 -55
- ddeutil/workflow/cli.py +1 -15
- ddeutil/workflow/conf.py +71 -26
- ddeutil/workflow/errors.py +86 -19
- ddeutil/workflow/event.py +268 -169
- ddeutil/workflow/job.py +331 -192
- ddeutil/workflow/params.py +43 -11
- ddeutil/workflow/result.py +96 -70
- ddeutil/workflow/reusables.py +56 -6
- ddeutil/workflow/stages.py +1059 -572
- ddeutil/workflow/traces.py +205 -124
- ddeutil/workflow/utils.py +58 -19
- ddeutil/workflow/workflow.py +435 -296
- {ddeutil_workflow-0.0.73.dist-info → ddeutil_workflow-0.0.75.dist-info}/METADATA +27 -17
- ddeutil_workflow-0.0.75.dist-info/RECORD +30 -0
- ddeutil_workflow-0.0.73.dist-info/RECORD +0 -30
- {ddeutil_workflow-0.0.73.dist-info → ddeutil_workflow-0.0.75.dist-info}/WHEEL +0 -0
- {ddeutil_workflow-0.0.73.dist-info → ddeutil_workflow-0.0.75.dist-info}/entry_points.txt +0 -0
- {ddeutil_workflow-0.0.73.dist-info → ddeutil_workflow-0.0.75.dist-info}/licenses/LICENSE +0 -0
- {ddeutil_workflow-0.0.73.dist-info → ddeutil_workflow-0.0.75.dist-info}/top_level.txt +0 -0
ddeutil/workflow/traces.py
CHANGED
@@ -3,7 +3,36 @@
|
|
3
3
|
# Licensed under the MIT License. See LICENSE in the project root for
|
4
4
|
# license information.
|
5
5
|
# ------------------------------------------------------------------------------
|
6
|
-
|
6
|
+
"""Tracing and Logging Module for Workflow Execution.
|
7
|
+
|
8
|
+
This module provides comprehensive tracing and logging capabilities for workflow
|
9
|
+
execution monitoring. It supports multiple trace backends including console output,
|
10
|
+
file-based logging, and SQLite database storage.
|
11
|
+
|
12
|
+
The tracing system captures detailed execution metadata including process IDs,
|
13
|
+
thread identifiers, timestamps, and contextual information for debugging and
|
14
|
+
monitoring workflow executions.
|
15
|
+
|
16
|
+
Classes:
|
17
|
+
Message: Log message model with prefix parsing
|
18
|
+
TraceMeta: Metadata model for execution context
|
19
|
+
TraceData: Container for trace information
|
20
|
+
BaseTrace: Abstract base class for trace implementations
|
21
|
+
ConsoleTrace: Console-based trace output
|
22
|
+
FileTrace: File-based trace storage
|
23
|
+
SQLiteTrace: Database-based trace storage
|
24
|
+
|
25
|
+
Functions:
|
26
|
+
set_logging: Configure logger with custom formatting
|
27
|
+
get_trace: Factory function for trace instances
|
28
|
+
|
29
|
+
Example:
|
30
|
+
>>> from ddeutil.workflow.traces import get_trace
|
31
|
+
>>> # Create file-based trace
|
32
|
+
>>> trace = get_trace("running-id-101", parent_run_id="workflow-001")
|
33
|
+
>>> trace.info("Workflow execution started")
|
34
|
+
>>> trace.debug("Processing stage 1")
|
35
|
+
"""
|
7
36
|
from __future__ import annotations
|
8
37
|
|
9
38
|
import json
|
@@ -17,9 +46,12 @@ from inspect import Traceback, currentframe, getframeinfo
|
|
17
46
|
from pathlib import Path
|
18
47
|
from threading import get_ident
|
19
48
|
from types import FrameType
|
20
|
-
from typing import ClassVar, Final, Literal, Optional,
|
49
|
+
from typing import ClassVar, Final, Literal, Optional, Union
|
50
|
+
from urllib.parse import ParseResult, unquote_plus, urlparse
|
21
51
|
|
22
52
|
from pydantic import BaseModel, ConfigDict, Field
|
53
|
+
from pydantic.functional_serializers import field_serializer
|
54
|
+
from pydantic.functional_validators import field_validator
|
23
55
|
from typing_extensions import Self
|
24
56
|
|
25
57
|
from .__types import DictData
|
@@ -32,12 +64,23 @@ logger = logging.getLogger("ddeutil.workflow")
|
|
32
64
|
|
33
65
|
@lru_cache
|
34
66
|
def set_logging(name: str) -> logging.Logger:
|
35
|
-
"""
|
36
|
-
custom handler and formatter from this package config.
|
67
|
+
"""Configure logger with custom formatting and handlers.
|
37
68
|
|
38
|
-
|
69
|
+
Creates and configures a logger instance with the custom formatter and
|
70
|
+
handlers defined in the package configuration. The logger includes both
|
71
|
+
console output and proper formatting for workflow execution tracking.
|
39
72
|
|
40
|
-
:
|
73
|
+
Args:
|
74
|
+
name: Module name to create logger for
|
75
|
+
|
76
|
+
Returns:
|
77
|
+
logging.Logger: Configured logger instance with custom formatting
|
78
|
+
|
79
|
+
Example:
|
80
|
+
```python
|
81
|
+
logger = set_logging("ddeutil.workflow.stages")
|
82
|
+
logger.info("Stage execution started")
|
83
|
+
```
|
41
84
|
"""
|
42
85
|
_logger = logging.getLogger(name)
|
43
86
|
|
@@ -101,10 +144,12 @@ class Message(BaseModel):
|
|
101
144
|
def prepare(self, extras: Optional[DictData] = None) -> str:
|
102
145
|
"""Prepare message with force add prefix before writing trace log.
|
103
146
|
|
104
|
-
:
|
105
|
-
|
147
|
+
Args:
|
148
|
+
extras: An extra parameter that want to get the
|
149
|
+
`log_add_emoji` flag.
|
106
150
|
|
107
|
-
:
|
151
|
+
Returns:
|
152
|
+
str: The prepared message with prefix and optional emoji.
|
108
153
|
"""
|
109
154
|
name: str = self.name or PREFIX_DEFAULT
|
110
155
|
emoji: str = (
|
@@ -122,7 +167,9 @@ class TraceMeta(BaseModel): # pragma: no cov
|
|
122
167
|
|
123
168
|
mode: Literal["stdout", "stderr"] = Field(description="A meta mode.")
|
124
169
|
level: str = Field(description="A log level.")
|
125
|
-
datetime: str = Field(
|
170
|
+
datetime: str = Field(
|
171
|
+
description="A datetime string with the specific config format."
|
172
|
+
)
|
126
173
|
process: int = Field(description="A process ID.")
|
127
174
|
thread: int = Field(description="A thread ID.")
|
128
175
|
message: str = Field(description="A message log.")
|
@@ -139,9 +186,13 @@ class TraceMeta(BaseModel): # pragma: no cov
|
|
139
186
|
"""Dynamic Frame information base on the `logs_trace_frame_layer` config
|
140
187
|
value that was set from the extra parameter.
|
141
188
|
|
142
|
-
:
|
143
|
-
|
144
|
-
|
189
|
+
Args:
|
190
|
+
frame: The current frame that want to dynamic.
|
191
|
+
extras: An extra parameter that want to get the
|
192
|
+
`logs_trace_frame_layer` config value.
|
193
|
+
|
194
|
+
Returns:
|
195
|
+
Traceback: The frame information at the specified layer.
|
145
196
|
"""
|
146
197
|
extras: DictData = extras or {}
|
147
198
|
layer: int = extras.get("logs_trace_frame_layer", 4)
|
@@ -167,14 +218,16 @@ class TraceMeta(BaseModel): # pragma: no cov
|
|
167
218
|
"""Make the current metric for contract this TraceMeta model instance
|
168
219
|
that will catch local states like PID, thread identity.
|
169
220
|
|
170
|
-
:
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
221
|
+
Args:
|
222
|
+
mode: A metadata mode.
|
223
|
+
message: A message.
|
224
|
+
level: A log level.
|
225
|
+
cutting_id: A cutting ID string.
|
226
|
+
extras: An extra parameter that want to override core
|
227
|
+
config values.
|
176
228
|
|
177
|
-
:
|
229
|
+
Returns:
|
230
|
+
Self: The constructed TraceMeta instance.
|
178
231
|
"""
|
179
232
|
frame: FrameType = currentframe()
|
180
233
|
frame_info: Traceback = cls.dynamic_frame(frame, extras=extras)
|
@@ -183,9 +236,9 @@ class TraceMeta(BaseModel): # pragma: no cov
|
|
183
236
|
mode=mode,
|
184
237
|
level=level,
|
185
238
|
datetime=(
|
186
|
-
get_dt_now(
|
187
|
-
|
188
|
-
)
|
239
|
+
get_dt_now()
|
240
|
+
.astimezone(dynamic("log_tz", extras=extras))
|
241
|
+
.strftime(dynamic("log_datetime_format", extras=extras))
|
189
242
|
),
|
190
243
|
process=os.getpid(),
|
191
244
|
thread=get_ident(),
|
@@ -252,43 +305,6 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
252
305
|
description="A parent running ID",
|
253
306
|
)
|
254
307
|
|
255
|
-
@classmethod
|
256
|
-
@abstractmethod
|
257
|
-
def find_traces(
|
258
|
-
cls,
|
259
|
-
path: Optional[Path] = None,
|
260
|
-
extras: Optional[DictData] = None,
|
261
|
-
) -> Iterator[TraceData]: # pragma: no cov
|
262
|
-
"""Return iterator of TraceData models from the target pointer.
|
263
|
-
|
264
|
-
Args:
|
265
|
-
path (:obj:`Path`, optional): A pointer path that want to override.
|
266
|
-
extras (:obj:`DictData`, optional): An extras parameter that want to
|
267
|
-
override default engine config.
|
268
|
-
|
269
|
-
Returns:
|
270
|
-
Iterator[TracData]: An iterator object that generate a TracData
|
271
|
-
model.
|
272
|
-
"""
|
273
|
-
raise NotImplementedError(
|
274
|
-
"Trace dataclass should implement `find_traces` class-method."
|
275
|
-
)
|
276
|
-
|
277
|
-
@classmethod
|
278
|
-
@abstractmethod
|
279
|
-
def find_trace_with_id(
|
280
|
-
cls,
|
281
|
-
run_id: str,
|
282
|
-
force_raise: bool = True,
|
283
|
-
*,
|
284
|
-
path: Optional[Path] = None,
|
285
|
-
extras: Optional[DictData] = None,
|
286
|
-
) -> TraceData:
|
287
|
-
raise NotImplementedError(
|
288
|
-
"Trace dataclass should implement `find_trace_with_id` "
|
289
|
-
"class-method."
|
290
|
-
)
|
291
|
-
|
292
308
|
@abstractmethod
|
293
309
|
def writer(
|
294
310
|
self,
|
@@ -340,7 +356,7 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
340
356
|
)
|
341
357
|
|
342
358
|
@abstractmethod
|
343
|
-
def
|
359
|
+
def emit(
|
344
360
|
self,
|
345
361
|
message: str,
|
346
362
|
mode: str,
|
@@ -364,7 +380,7 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
364
380
|
|
365
381
|
:param message: (str) A message that want to log.
|
366
382
|
"""
|
367
|
-
self.
|
383
|
+
self.emit(message, mode="debug")
|
368
384
|
|
369
385
|
def info(self, message: str) -> None:
|
370
386
|
"""Write trace log with append mode and logging this message with the
|
@@ -372,7 +388,7 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
372
388
|
|
373
389
|
:param message: (str) A message that want to log.
|
374
390
|
"""
|
375
|
-
self.
|
391
|
+
self.emit(message, mode="info")
|
376
392
|
|
377
393
|
def warning(self, message: str) -> None:
|
378
394
|
"""Write trace log with append mode and logging this message with the
|
@@ -380,7 +396,7 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
380
396
|
|
381
397
|
:param message: (str) A message that want to log.
|
382
398
|
"""
|
383
|
-
self.
|
399
|
+
self.emit(message, mode="warning")
|
384
400
|
|
385
401
|
def error(self, message: str) -> None:
|
386
402
|
"""Write trace log with append mode and logging this message with the
|
@@ -388,7 +404,7 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
388
404
|
|
389
405
|
:param message: (str) A message that want to log.
|
390
406
|
"""
|
391
|
-
self.
|
407
|
+
self.emit(message, mode="error", is_err=True)
|
392
408
|
|
393
409
|
def exception(self, message: str) -> None:
|
394
410
|
"""Write trace log with append mode and logging this message with the
|
@@ -396,10 +412,10 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
396
412
|
|
397
413
|
:param message: (str) A message that want to log.
|
398
414
|
"""
|
399
|
-
self.
|
415
|
+
self.emit(message, mode="exception", is_err=True)
|
400
416
|
|
401
417
|
@abstractmethod
|
402
|
-
async def
|
418
|
+
async def amit(
|
403
419
|
self,
|
404
420
|
message: str,
|
405
421
|
mode: str,
|
@@ -423,7 +439,7 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
423
439
|
|
424
440
|
:param message: (str) A message that want to log.
|
425
441
|
"""
|
426
|
-
await self.
|
442
|
+
await self.amit(message, mode="debug")
|
427
443
|
|
428
444
|
async def ainfo(self, message: str) -> None: # pragma: no cov
|
429
445
|
"""Async write trace log with append mode and logging this message with
|
@@ -431,7 +447,7 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
431
447
|
|
432
448
|
:param message: (str) A message that want to log.
|
433
449
|
"""
|
434
|
-
await self.
|
450
|
+
await self.amit(message, mode="info")
|
435
451
|
|
436
452
|
async def awarning(self, message: str) -> None: # pragma: no cov
|
437
453
|
"""Async write trace log with append mode and logging this message with
|
@@ -439,7 +455,7 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
439
455
|
|
440
456
|
:param message: (str) A message that want to log.
|
441
457
|
"""
|
442
|
-
await self.
|
458
|
+
await self.amit(message, mode="warning")
|
443
459
|
|
444
460
|
async def aerror(self, message: str) -> None: # pragma: no cov
|
445
461
|
"""Async write trace log with append mode and logging this message with
|
@@ -447,7 +463,7 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
447
463
|
|
448
464
|
:param message: (str) A message that want to log.
|
449
465
|
"""
|
450
|
-
await self.
|
466
|
+
await self.amit(message, mode="error", is_err=True)
|
451
467
|
|
452
468
|
async def aexception(self, message: str) -> None: # pragma: no cov
|
453
469
|
"""Async write trace log with append mode and logging this message with
|
@@ -455,36 +471,12 @@ class BaseTrace(BaseModel, ABC): # pragma: no cov
|
|
455
471
|
|
456
472
|
:param message: (str) A message that want to log.
|
457
473
|
"""
|
458
|
-
await self.
|
474
|
+
await self.amit(message, mode="exception", is_err=True)
|
459
475
|
|
460
476
|
|
461
477
|
class ConsoleTrace(BaseTrace): # pragma: no cov
|
462
478
|
"""Console Trace log model."""
|
463
479
|
|
464
|
-
@classmethod
|
465
|
-
def find_traces(
|
466
|
-
cls,
|
467
|
-
path: Optional[Path] = None,
|
468
|
-
extras: Optional[DictData] = None,
|
469
|
-
) -> Iterator[TraceData]: # pragma: no cov
|
470
|
-
raise NotImplementedError(
|
471
|
-
"Console Trace does not support to find history traces data."
|
472
|
-
)
|
473
|
-
|
474
|
-
@classmethod
|
475
|
-
def find_trace_with_id(
|
476
|
-
cls,
|
477
|
-
run_id: str,
|
478
|
-
force_raise: bool = True,
|
479
|
-
*,
|
480
|
-
path: Optional[Path] = None,
|
481
|
-
extras: Optional[DictData] = None,
|
482
|
-
) -> TraceData:
|
483
|
-
raise NotImplementedError(
|
484
|
-
"Console Trace does not support to find history traces data with "
|
485
|
-
"the specific running ID."
|
486
|
-
)
|
487
|
-
|
488
480
|
def writer(
|
489
481
|
self,
|
490
482
|
message: str,
|
@@ -537,13 +529,13 @@ class ConsoleTrace(BaseTrace): # pragma: no cov
|
|
537
529
|
"""
|
538
530
|
return prepare_newline(Message.from_str(message).prepare(self.extras))
|
539
531
|
|
540
|
-
def
|
541
|
-
self, message: str, mode: str, *, is_err: bool = False
|
542
|
-
) -> None:
|
532
|
+
def emit(self, message: str, mode: str, *, is_err: bool = False) -> None:
|
543
533
|
"""Write trace log with append mode and logging this message with any
|
544
534
|
logging level.
|
545
535
|
|
546
536
|
:param message: (str) A message that want to log.
|
537
|
+
:param mode: (str)
|
538
|
+
:param is_err: (bool)
|
547
539
|
"""
|
548
540
|
msg: str = self.make_message(message)
|
549
541
|
|
@@ -554,13 +546,15 @@ class ConsoleTrace(BaseTrace): # pragma: no cov
|
|
554
546
|
|
555
547
|
getattr(logger, mode)(msg, stacklevel=3, extra={"cut_id": self.cut_id})
|
556
548
|
|
557
|
-
async def
|
549
|
+
async def amit(
|
558
550
|
self, message: str, mode: str, *, is_err: bool = False
|
559
551
|
) -> None:
|
560
552
|
"""Write trace log with append mode and logging this message with any
|
561
553
|
logging level.
|
562
554
|
|
563
555
|
:param message: (str) A message that want to log.
|
556
|
+
:param mode: (str)
|
557
|
+
:param is_err: (bool)
|
564
558
|
"""
|
565
559
|
msg: str = self.make_message(message)
|
566
560
|
|
@@ -572,7 +566,62 @@ class ConsoleTrace(BaseTrace): # pragma: no cov
|
|
572
566
|
getattr(logger, mode)(msg, stacklevel=3, extra={"cut_id": self.cut_id})
|
573
567
|
|
574
568
|
|
575
|
-
class
|
569
|
+
class OutsideTrace(ConsoleTrace, ABC):
|
570
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
571
|
+
|
572
|
+
url: ParseResult = Field(description="An URL for create pointer.")
|
573
|
+
|
574
|
+
@field_validator(
|
575
|
+
"url", mode="before", json_schema_input_type=Union[ParseResult, str]
|
576
|
+
)
|
577
|
+
def __parse_url(cls, value: Union[ParseResult, str]) -> ParseResult:
|
578
|
+
if isinstance(value, str):
|
579
|
+
return urlparse(value)
|
580
|
+
return value
|
581
|
+
|
582
|
+
@field_serializer("url")
|
583
|
+
def __serialize_url(self, value: ParseResult) -> str:
|
584
|
+
return value.geturl()
|
585
|
+
|
586
|
+
@classmethod
|
587
|
+
@abstractmethod
|
588
|
+
def find_traces(
|
589
|
+
cls,
|
590
|
+
path: Optional[Path] = None,
|
591
|
+
extras: Optional[DictData] = None,
|
592
|
+
) -> Iterator[TraceData]: # pragma: no cov
|
593
|
+
"""Return iterator of TraceData models from the target pointer.
|
594
|
+
|
595
|
+
Args:
|
596
|
+
path (:obj:`Path`, optional): A pointer path that want to override.
|
597
|
+
extras (:obj:`DictData`, optional): An extras parameter that want to
|
598
|
+
override default engine config.
|
599
|
+
|
600
|
+
Returns:
|
601
|
+
Iterator[TracData]: An iterator object that generate a TracData
|
602
|
+
model.
|
603
|
+
"""
|
604
|
+
raise NotImplementedError(
|
605
|
+
"Trace dataclass should implement `find_traces` class-method."
|
606
|
+
)
|
607
|
+
|
608
|
+
@classmethod
|
609
|
+
@abstractmethod
|
610
|
+
def find_trace_with_id(
|
611
|
+
cls,
|
612
|
+
run_id: str,
|
613
|
+
force_raise: bool = True,
|
614
|
+
*,
|
615
|
+
path: Optional[Path] = None,
|
616
|
+
extras: Optional[DictData] = None,
|
617
|
+
) -> TraceData:
|
618
|
+
raise NotImplementedError(
|
619
|
+
"Trace dataclass should implement `find_trace_with_id` "
|
620
|
+
"class-method."
|
621
|
+
)
|
622
|
+
|
623
|
+
|
624
|
+
class FileTrace(OutsideTrace): # pragma: no cov
|
576
625
|
"""File Trace dataclass that write file to the local storage."""
|
577
626
|
|
578
627
|
@classmethod
|
@@ -587,7 +636,9 @@ class FileTrace(ConsoleTrace): # pragma: no cov
|
|
587
636
|
:param extras: An extra parameter that want to override core config.
|
588
637
|
"""
|
589
638
|
for file in sorted(
|
590
|
-
(path or dynamic("
|
639
|
+
(path or Path(dynamic("trace_url", extras=extras).path)).glob(
|
640
|
+
"./run_id=*"
|
641
|
+
),
|
591
642
|
key=lambda f: f.lstat().st_mtime,
|
592
643
|
):
|
593
644
|
yield TraceData.from_path(file)
|
@@ -608,7 +659,7 @@ class FileTrace(ConsoleTrace): # pragma: no cov
|
|
608
659
|
:param path: (Path)
|
609
660
|
:param extras: An extra parameter that want to override core config.
|
610
661
|
"""
|
611
|
-
base_path: Path = path or dynamic("
|
662
|
+
base_path: Path = path or Path(dynamic("trace_url", extras=extras).path)
|
612
663
|
file: Path = base_path / f"run_id={run_id}"
|
613
664
|
if file.exists():
|
614
665
|
return TraceData.from_path(file)
|
@@ -624,10 +675,14 @@ class FileTrace(ConsoleTrace): # pragma: no cov
|
|
624
675
|
"""Pointer of the target path that use to writing trace log or searching
|
625
676
|
trace log.
|
626
677
|
|
678
|
+
This running ID folder that use to keeping trace log data will use
|
679
|
+
a parent running ID first. If it does not set, it will use running ID
|
680
|
+
instead.
|
681
|
+
|
627
682
|
:rtype: Path
|
628
683
|
"""
|
629
684
|
log_file: Path = (
|
630
|
-
|
685
|
+
Path(unquote_plus(self.url.path))
|
631
686
|
/ f"run_id={self.parent_run_id or self.run_id}"
|
632
687
|
)
|
633
688
|
if not log_file.exists():
|
@@ -710,17 +765,20 @@ class FileTrace(ConsoleTrace): # pragma: no cov
|
|
710
765
|
await f.write(trace_meta.model_dump_json() + "\n")
|
711
766
|
|
712
767
|
|
713
|
-
class SQLiteTrace(
|
768
|
+
class SQLiteTrace(OutsideTrace): # pragma: no cov
|
714
769
|
"""SQLite Trace dataclass that write trace log to the SQLite database file."""
|
715
770
|
|
716
771
|
table_name: ClassVar[str] = "audits"
|
717
772
|
schemas: ClassVar[
|
718
773
|
str
|
719
774
|
] = """
|
720
|
-
run_id
|
721
|
-
|
722
|
-
|
723
|
-
|
775
|
+
run_id str
|
776
|
+
, parent_run_id str
|
777
|
+
, type str
|
778
|
+
, text str
|
779
|
+
, metadata JSON
|
780
|
+
, created_at datetime
|
781
|
+
, updated_at datetime
|
724
782
|
primary key ( run_id )
|
725
783
|
"""
|
726
784
|
|
@@ -729,7 +787,8 @@ class SQLiteTrace(ConsoleTrace): # pragma: no cov
|
|
729
787
|
cls,
|
730
788
|
path: Optional[Path] = None,
|
731
789
|
extras: Optional[DictData] = None,
|
732
|
-
) -> Iterator[TraceData]:
|
790
|
+
) -> Iterator[TraceData]:
|
791
|
+
raise NotImplementedError("SQLiteTrace does not implement yet.")
|
733
792
|
|
734
793
|
@classmethod
|
735
794
|
def find_trace_with_id(
|
@@ -739,30 +798,33 @@ class SQLiteTrace(ConsoleTrace): # pragma: no cov
|
|
739
798
|
*,
|
740
799
|
path: Optional[Path] = None,
|
741
800
|
extras: Optional[DictData] = None,
|
742
|
-
) -> TraceData:
|
801
|
+
) -> TraceData:
|
802
|
+
raise NotImplementedError("SQLiteTrace does not implement yet.")
|
743
803
|
|
744
|
-
def make_message(self, message: str) -> str:
|
804
|
+
def make_message(self, message: str) -> str:
|
805
|
+
raise NotImplementedError("SQLiteTrace does not implement yet.")
|
745
806
|
|
746
807
|
def writer(
|
747
808
|
self,
|
748
809
|
message: str,
|
749
810
|
level: str,
|
750
811
|
is_err: bool = False,
|
751
|
-
) -> None:
|
812
|
+
) -> None:
|
813
|
+
raise NotImplementedError("SQLiteTrace does not implement yet.")
|
752
814
|
|
753
815
|
def awriter(
|
754
816
|
self,
|
755
817
|
message: str,
|
756
818
|
level: str,
|
757
819
|
is_err: bool = False,
|
758
|
-
) -> None:
|
820
|
+
) -> None:
|
821
|
+
raise NotImplementedError("SQLiteTrace does not implement yet.")
|
759
822
|
|
760
823
|
|
761
|
-
Trace =
|
762
|
-
TraceModel = Union[
|
763
|
-
ConsoleTrace,
|
824
|
+
Trace = Union[
|
764
825
|
FileTrace,
|
765
826
|
SQLiteTrace,
|
827
|
+
OutsideTrace,
|
766
828
|
]
|
767
829
|
|
768
830
|
|
@@ -771,7 +833,7 @@ def get_trace(
|
|
771
833
|
*,
|
772
834
|
parent_run_id: Optional[str] = None,
|
773
835
|
extras: Optional[DictData] = None,
|
774
|
-
) ->
|
836
|
+
) -> Trace: # pragma: no cov
|
775
837
|
"""Get dynamic Trace instance from the core config (it can override by an
|
776
838
|
extras argument) that passing running ID and parent running ID.
|
777
839
|
|
@@ -780,12 +842,31 @@ def get_trace(
|
|
780
842
|
:param extras: (DictData) An extra parameter that want to override the core
|
781
843
|
config values.
|
782
844
|
|
783
|
-
:rtype:
|
845
|
+
:rtype: Trace
|
784
846
|
"""
|
785
|
-
|
786
|
-
|
787
|
-
|
847
|
+
# NOTE: Allow you to override trace model by the extra parameter.
|
848
|
+
map_trace_models: dict[str, type[Trace]] = extras.get(
|
849
|
+
"trace_model_mapping", {}
|
850
|
+
)
|
851
|
+
url: ParseResult
|
852
|
+
if (url := dynamic("trace_url", extras=extras)).scheme and (
|
853
|
+
url.scheme == "sqlite"
|
854
|
+
or (url.scheme == "file" and Path(url.path).is_file())
|
855
|
+
):
|
856
|
+
return map_trace_models.get("sqlite", SQLiteTrace)(
|
857
|
+
url=url,
|
858
|
+
run_id=run_id,
|
859
|
+
parent_run_id=parent_run_id,
|
860
|
+
extras=(extras or {}),
|
861
|
+
)
|
862
|
+
elif url.scheme and url.scheme != "file":
|
863
|
+
raise NotImplementedError(
|
864
|
+
f"Does not implement the outside trace model support for URL: {url}"
|
788
865
|
)
|
789
|
-
|
790
|
-
|
866
|
+
|
867
|
+
return map_trace_models.get("file", FileTrace)(
|
868
|
+
url=url,
|
869
|
+
run_id=run_id,
|
870
|
+
parent_run_id=parent_run_id,
|
871
|
+
extras=(extras or {}),
|
791
872
|
)
|