truthound-dashboard 1.3.1__py3-none-any.whl → 1.4.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.
- truthound_dashboard/api/alerts.py +258 -0
- truthound_dashboard/api/anomaly.py +1302 -0
- truthound_dashboard/api/cross_alerts.py +352 -0
- truthound_dashboard/api/deps.py +143 -0
- truthound_dashboard/api/drift_monitor.py +540 -0
- truthound_dashboard/api/lineage.py +1151 -0
- truthound_dashboard/api/maintenance.py +363 -0
- truthound_dashboard/api/middleware.py +373 -1
- truthound_dashboard/api/model_monitoring.py +805 -0
- truthound_dashboard/api/notifications_advanced.py +2452 -0
- truthound_dashboard/api/plugins.py +2096 -0
- truthound_dashboard/api/profile.py +211 -14
- truthound_dashboard/api/reports.py +853 -0
- truthound_dashboard/api/router.py +147 -0
- truthound_dashboard/api/rule_suggestions.py +310 -0
- truthound_dashboard/api/schema_evolution.py +231 -0
- truthound_dashboard/api/sources.py +47 -3
- truthound_dashboard/api/triggers.py +190 -0
- truthound_dashboard/api/validations.py +13 -0
- truthound_dashboard/api/validators.py +333 -4
- truthound_dashboard/api/versioning.py +309 -0
- truthound_dashboard/api/websocket.py +301 -0
- truthound_dashboard/core/__init__.py +27 -0
- truthound_dashboard/core/anomaly.py +1395 -0
- truthound_dashboard/core/anomaly_explainer.py +633 -0
- truthound_dashboard/core/cache.py +206 -0
- truthound_dashboard/core/cached_services.py +422 -0
- truthound_dashboard/core/charts.py +352 -0
- truthound_dashboard/core/connections.py +1069 -42
- truthound_dashboard/core/cross_alerts.py +837 -0
- truthound_dashboard/core/drift_monitor.py +1477 -0
- truthound_dashboard/core/drift_sampling.py +669 -0
- truthound_dashboard/core/i18n/__init__.py +42 -0
- truthound_dashboard/core/i18n/detector.py +173 -0
- truthound_dashboard/core/i18n/messages.py +564 -0
- truthound_dashboard/core/lineage.py +971 -0
- truthound_dashboard/core/maintenance.py +443 -5
- truthound_dashboard/core/model_monitoring.py +1043 -0
- truthound_dashboard/core/notifications/channels.py +1020 -1
- truthound_dashboard/core/notifications/deduplication/__init__.py +143 -0
- truthound_dashboard/core/notifications/deduplication/policies.py +274 -0
- truthound_dashboard/core/notifications/deduplication/service.py +400 -0
- truthound_dashboard/core/notifications/deduplication/stores.py +2365 -0
- truthound_dashboard/core/notifications/deduplication/strategies.py +422 -0
- truthound_dashboard/core/notifications/dispatcher.py +43 -0
- truthound_dashboard/core/notifications/escalation/__init__.py +149 -0
- truthound_dashboard/core/notifications/escalation/backends.py +1384 -0
- truthound_dashboard/core/notifications/escalation/engine.py +429 -0
- truthound_dashboard/core/notifications/escalation/models.py +336 -0
- truthound_dashboard/core/notifications/escalation/scheduler.py +1187 -0
- truthound_dashboard/core/notifications/escalation/state_machine.py +330 -0
- truthound_dashboard/core/notifications/escalation/stores.py +2896 -0
- truthound_dashboard/core/notifications/events.py +49 -0
- truthound_dashboard/core/notifications/metrics/__init__.py +115 -0
- truthound_dashboard/core/notifications/metrics/base.py +528 -0
- truthound_dashboard/core/notifications/metrics/collectors.py +583 -0
- truthound_dashboard/core/notifications/routing/__init__.py +169 -0
- truthound_dashboard/core/notifications/routing/combinators.py +184 -0
- truthound_dashboard/core/notifications/routing/config.py +375 -0
- truthound_dashboard/core/notifications/routing/config_parser.py +867 -0
- truthound_dashboard/core/notifications/routing/engine.py +382 -0
- truthound_dashboard/core/notifications/routing/expression_engine.py +1269 -0
- truthound_dashboard/core/notifications/routing/jinja2_engine.py +774 -0
- truthound_dashboard/core/notifications/routing/rules.py +625 -0
- truthound_dashboard/core/notifications/routing/validator.py +678 -0
- truthound_dashboard/core/notifications/service.py +2 -0
- truthound_dashboard/core/notifications/stats_aggregator.py +850 -0
- truthound_dashboard/core/notifications/throttling/__init__.py +83 -0
- truthound_dashboard/core/notifications/throttling/builder.py +311 -0
- truthound_dashboard/core/notifications/throttling/stores.py +1859 -0
- truthound_dashboard/core/notifications/throttling/throttlers.py +633 -0
- truthound_dashboard/core/openlineage.py +1028 -0
- truthound_dashboard/core/plugins/__init__.py +39 -0
- truthound_dashboard/core/plugins/docs/__init__.py +39 -0
- truthound_dashboard/core/plugins/docs/extractor.py +703 -0
- truthound_dashboard/core/plugins/docs/renderers.py +804 -0
- truthound_dashboard/core/plugins/hooks/__init__.py +63 -0
- truthound_dashboard/core/plugins/hooks/decorators.py +367 -0
- truthound_dashboard/core/plugins/hooks/manager.py +403 -0
- truthound_dashboard/core/plugins/hooks/protocols.py +265 -0
- truthound_dashboard/core/plugins/lifecycle/__init__.py +41 -0
- truthound_dashboard/core/plugins/lifecycle/hot_reload.py +584 -0
- truthound_dashboard/core/plugins/lifecycle/machine.py +419 -0
- truthound_dashboard/core/plugins/lifecycle/states.py +266 -0
- truthound_dashboard/core/plugins/loader.py +504 -0
- truthound_dashboard/core/plugins/registry.py +810 -0
- truthound_dashboard/core/plugins/reporter_executor.py +588 -0
- truthound_dashboard/core/plugins/sandbox/__init__.py +59 -0
- truthound_dashboard/core/plugins/sandbox/code_validator.py +243 -0
- truthound_dashboard/core/plugins/sandbox/engines.py +770 -0
- truthound_dashboard/core/plugins/sandbox/protocols.py +194 -0
- truthound_dashboard/core/plugins/sandbox.py +617 -0
- truthound_dashboard/core/plugins/security/__init__.py +68 -0
- truthound_dashboard/core/plugins/security/analyzer.py +535 -0
- truthound_dashboard/core/plugins/security/policies.py +311 -0
- truthound_dashboard/core/plugins/security/protocols.py +296 -0
- truthound_dashboard/core/plugins/security/signing.py +842 -0
- truthound_dashboard/core/plugins/security.py +446 -0
- truthound_dashboard/core/plugins/validator_executor.py +401 -0
- truthound_dashboard/core/plugins/versioning/__init__.py +51 -0
- truthound_dashboard/core/plugins/versioning/constraints.py +377 -0
- truthound_dashboard/core/plugins/versioning/dependencies.py +541 -0
- truthound_dashboard/core/plugins/versioning/semver.py +266 -0
- truthound_dashboard/core/profile_comparison.py +601 -0
- truthound_dashboard/core/report_history.py +570 -0
- truthound_dashboard/core/reporters/__init__.py +57 -0
- truthound_dashboard/core/reporters/base.py +296 -0
- truthound_dashboard/core/reporters/csv_reporter.py +155 -0
- truthound_dashboard/core/reporters/html_reporter.py +598 -0
- truthound_dashboard/core/reporters/i18n/__init__.py +65 -0
- truthound_dashboard/core/reporters/i18n/base.py +494 -0
- truthound_dashboard/core/reporters/i18n/catalogs.py +930 -0
- truthound_dashboard/core/reporters/json_reporter.py +160 -0
- truthound_dashboard/core/reporters/junit_reporter.py +233 -0
- truthound_dashboard/core/reporters/markdown_reporter.py +207 -0
- truthound_dashboard/core/reporters/pdf_reporter.py +209 -0
- truthound_dashboard/core/reporters/registry.py +272 -0
- truthound_dashboard/core/rule_generator.py +2088 -0
- truthound_dashboard/core/scheduler.py +822 -12
- truthound_dashboard/core/schema_evolution.py +858 -0
- truthound_dashboard/core/services.py +152 -9
- truthound_dashboard/core/statistics.py +718 -0
- truthound_dashboard/core/streaming_anomaly.py +883 -0
- truthound_dashboard/core/triggers/__init__.py +45 -0
- truthound_dashboard/core/triggers/base.py +226 -0
- truthound_dashboard/core/triggers/evaluators.py +609 -0
- truthound_dashboard/core/triggers/factory.py +363 -0
- truthound_dashboard/core/unified_alerts.py +870 -0
- truthound_dashboard/core/validation_limits.py +509 -0
- truthound_dashboard/core/versioning.py +709 -0
- truthound_dashboard/core/websocket/__init__.py +59 -0
- truthound_dashboard/core/websocket/manager.py +512 -0
- truthound_dashboard/core/websocket/messages.py +130 -0
- truthound_dashboard/db/__init__.py +30 -0
- truthound_dashboard/db/models.py +3375 -3
- truthound_dashboard/main.py +22 -0
- truthound_dashboard/schemas/__init__.py +396 -1
- truthound_dashboard/schemas/anomaly.py +1258 -0
- truthound_dashboard/schemas/base.py +4 -0
- truthound_dashboard/schemas/cross_alerts.py +334 -0
- truthound_dashboard/schemas/drift_monitor.py +890 -0
- truthound_dashboard/schemas/lineage.py +428 -0
- truthound_dashboard/schemas/maintenance.py +154 -0
- truthound_dashboard/schemas/model_monitoring.py +374 -0
- truthound_dashboard/schemas/notifications_advanced.py +1363 -0
- truthound_dashboard/schemas/openlineage.py +704 -0
- truthound_dashboard/schemas/plugins.py +1293 -0
- truthound_dashboard/schemas/profile.py +420 -34
- truthound_dashboard/schemas/profile_comparison.py +242 -0
- truthound_dashboard/schemas/reports.py +285 -0
- truthound_dashboard/schemas/rule_suggestion.py +434 -0
- truthound_dashboard/schemas/schema_evolution.py +164 -0
- truthound_dashboard/schemas/source.py +117 -2
- truthound_dashboard/schemas/triggers.py +511 -0
- truthound_dashboard/schemas/unified_alerts.py +223 -0
- truthound_dashboard/schemas/validation.py +25 -1
- truthound_dashboard/schemas/validators/__init__.py +11 -0
- truthound_dashboard/schemas/validators/base.py +151 -0
- truthound_dashboard/schemas/versioning.py +152 -0
- truthound_dashboard/static/index.html +2 -2
- {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.1.dist-info}/METADATA +147 -23
- truthound_dashboard-1.4.1.dist-info/RECORD +239 -0
- truthound_dashboard/static/assets/index-BZG20KuF.js +0 -586
- truthound_dashboard/static/assets/index-D_HyZ3pb.css +0 -1
- truthound_dashboard/static/assets/unmerged_dictionaries-CtpqQBm0.js +0 -1
- truthound_dashboard-1.3.1.dist-info/RECORD +0 -110
- {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.1.dist-info}/WHEEL +0 -0
- {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.1.dist-info}/entry_points.txt +0 -0
- {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Trigger system for advanced scheduling.
|
|
2
|
+
|
|
3
|
+
This module provides a flexible trigger system that supports:
|
|
4
|
+
- Cron-based triggers (traditional scheduling)
|
|
5
|
+
- Interval triggers (fixed time intervals)
|
|
6
|
+
- Data change triggers (profile-based change detection)
|
|
7
|
+
- Composite triggers (combine multiple triggers with AND/OR logic)
|
|
8
|
+
- Event triggers (respond to system events)
|
|
9
|
+
- Manual triggers (API-only execution)
|
|
10
|
+
|
|
11
|
+
Architecture follows the Strategy pattern for extensibility.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .base import (
|
|
15
|
+
BaseTrigger,
|
|
16
|
+
TriggerContext,
|
|
17
|
+
TriggerEvaluation,
|
|
18
|
+
TriggerRegistry,
|
|
19
|
+
)
|
|
20
|
+
from .factory import TriggerFactory
|
|
21
|
+
from .evaluators import (
|
|
22
|
+
CronTrigger,
|
|
23
|
+
IntervalTrigger,
|
|
24
|
+
DataChangeTrigger,
|
|
25
|
+
CompositeTrigger,
|
|
26
|
+
EventTrigger,
|
|
27
|
+
ManualTrigger,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
# Base classes
|
|
32
|
+
"BaseTrigger",
|
|
33
|
+
"TriggerContext",
|
|
34
|
+
"TriggerEvaluation",
|
|
35
|
+
"TriggerRegistry",
|
|
36
|
+
# Factory
|
|
37
|
+
"TriggerFactory",
|
|
38
|
+
# Trigger implementations
|
|
39
|
+
"CronTrigger",
|
|
40
|
+
"IntervalTrigger",
|
|
41
|
+
"DataChangeTrigger",
|
|
42
|
+
"CompositeTrigger",
|
|
43
|
+
"EventTrigger",
|
|
44
|
+
"ManualTrigger",
|
|
45
|
+
]
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""Base classes for the trigger system.
|
|
2
|
+
|
|
3
|
+
Provides abstract base classes and common utilities for trigger implementations.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from typing import Any, ClassVar
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class TriggerContext:
|
|
19
|
+
"""Context information passed to trigger evaluators.
|
|
20
|
+
|
|
21
|
+
Contains all information needed to evaluate whether a trigger should fire.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
schedule_id: ID of the schedule being evaluated.
|
|
25
|
+
source_id: ID of the source to validate.
|
|
26
|
+
last_run_at: Timestamp of last successful run.
|
|
27
|
+
trigger_count: Number of times this schedule has triggered.
|
|
28
|
+
current_time: Current evaluation time.
|
|
29
|
+
profile_data: Latest profile data (for data change triggers).
|
|
30
|
+
baseline_profile: Baseline profile for comparison.
|
|
31
|
+
event_data: Event data (for event triggers).
|
|
32
|
+
custom_data: Additional context data.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
schedule_id: str
|
|
36
|
+
source_id: str
|
|
37
|
+
last_run_at: datetime | None = None
|
|
38
|
+
trigger_count: int = 0
|
|
39
|
+
current_time: datetime = field(default_factory=datetime.utcnow)
|
|
40
|
+
profile_data: dict[str, Any] | None = None
|
|
41
|
+
baseline_profile: dict[str, Any] | None = None
|
|
42
|
+
event_data: dict[str, Any] | None = None
|
|
43
|
+
custom_data: dict[str, Any] = field(default_factory=dict)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class TriggerEvaluation:
|
|
48
|
+
"""Result of evaluating a trigger condition.
|
|
49
|
+
|
|
50
|
+
Attributes:
|
|
51
|
+
should_trigger: Whether the trigger condition is met.
|
|
52
|
+
reason: Human-readable explanation of the result.
|
|
53
|
+
next_evaluation_at: Suggested time for next evaluation.
|
|
54
|
+
details: Additional details about the evaluation.
|
|
55
|
+
confidence: Confidence level (0.0-1.0) for ML-based triggers.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
should_trigger: bool
|
|
59
|
+
reason: str
|
|
60
|
+
next_evaluation_at: datetime | None = None
|
|
61
|
+
details: dict[str, Any] = field(default_factory=dict)
|
|
62
|
+
confidence: float = 1.0
|
|
63
|
+
|
|
64
|
+
def to_dict(self) -> dict[str, Any]:
|
|
65
|
+
"""Convert to dictionary for storage."""
|
|
66
|
+
return {
|
|
67
|
+
"should_trigger": self.should_trigger,
|
|
68
|
+
"reason": self.reason,
|
|
69
|
+
"next_evaluation_at": (
|
|
70
|
+
self.next_evaluation_at.isoformat()
|
|
71
|
+
if self.next_evaluation_at
|
|
72
|
+
else None
|
|
73
|
+
),
|
|
74
|
+
"details": self.details,
|
|
75
|
+
"confidence": self.confidence,
|
|
76
|
+
"evaluated_at": datetime.utcnow().isoformat(),
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class BaseTrigger(ABC):
|
|
81
|
+
"""Abstract base class for all trigger types.
|
|
82
|
+
|
|
83
|
+
Implements the Strategy pattern for trigger evaluation.
|
|
84
|
+
Subclasses must implement the evaluate() method.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
# Class-level trigger type identifier
|
|
88
|
+
trigger_type: ClassVar[str] = "base"
|
|
89
|
+
|
|
90
|
+
def __init__(self, config: dict[str, Any]) -> None:
|
|
91
|
+
"""Initialize the trigger with configuration.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
config: Trigger-specific configuration dictionary.
|
|
95
|
+
"""
|
|
96
|
+
self.config = config
|
|
97
|
+
self._validate_config()
|
|
98
|
+
|
|
99
|
+
@abstractmethod
|
|
100
|
+
def _validate_config(self) -> None:
|
|
101
|
+
"""Validate the trigger configuration.
|
|
102
|
+
|
|
103
|
+
Raises:
|
|
104
|
+
ValueError: If configuration is invalid.
|
|
105
|
+
"""
|
|
106
|
+
pass
|
|
107
|
+
|
|
108
|
+
@abstractmethod
|
|
109
|
+
async def evaluate(self, context: TriggerContext) -> TriggerEvaluation:
|
|
110
|
+
"""Evaluate whether the trigger should fire.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
context: Evaluation context with all necessary data.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
TriggerEvaluation with the result.
|
|
117
|
+
"""
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
def get_next_evaluation_time(
|
|
121
|
+
self, context: TriggerContext
|
|
122
|
+
) -> datetime | None:
|
|
123
|
+
"""Calculate the next time this trigger should be evaluated.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
context: Current context.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Next evaluation datetime or None if not applicable.
|
|
130
|
+
"""
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
def get_description(self) -> str:
|
|
134
|
+
"""Get a human-readable description of this trigger.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Description string.
|
|
138
|
+
"""
|
|
139
|
+
return f"{self.trigger_type} trigger"
|
|
140
|
+
|
|
141
|
+
def to_dict(self) -> dict[str, Any]:
|
|
142
|
+
"""Convert trigger to dictionary representation.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
Dictionary with trigger type and config.
|
|
146
|
+
"""
|
|
147
|
+
return {
|
|
148
|
+
"type": self.trigger_type,
|
|
149
|
+
"config": self.config,
|
|
150
|
+
"description": self.get_description(),
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class TriggerRegistry:
|
|
155
|
+
"""Registry for trigger type implementations.
|
|
156
|
+
|
|
157
|
+
Allows dynamic registration and lookup of trigger classes.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
_triggers: ClassVar[dict[str, type[BaseTrigger]]] = {}
|
|
161
|
+
|
|
162
|
+
@classmethod
|
|
163
|
+
def register(cls, trigger_type: str):
|
|
164
|
+
"""Decorator to register a trigger implementation.
|
|
165
|
+
|
|
166
|
+
Usage:
|
|
167
|
+
@TriggerRegistry.register("my_trigger")
|
|
168
|
+
class MyTrigger(BaseTrigger):
|
|
169
|
+
...
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
def decorator(trigger_class: type[BaseTrigger]):
|
|
173
|
+
cls._triggers[trigger_type] = trigger_class
|
|
174
|
+
trigger_class.trigger_type = trigger_type
|
|
175
|
+
return trigger_class
|
|
176
|
+
|
|
177
|
+
return decorator
|
|
178
|
+
|
|
179
|
+
@classmethod
|
|
180
|
+
def get(cls, trigger_type: str) -> type[BaseTrigger] | None:
|
|
181
|
+
"""Get a trigger class by type.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
trigger_type: Type identifier.
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Trigger class or None if not found.
|
|
188
|
+
"""
|
|
189
|
+
return cls._triggers.get(trigger_type)
|
|
190
|
+
|
|
191
|
+
@classmethod
|
|
192
|
+
def create(
|
|
193
|
+
cls, trigger_type: str, config: dict[str, Any]
|
|
194
|
+
) -> BaseTrigger | None:
|
|
195
|
+
"""Create a trigger instance.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
trigger_type: Type identifier.
|
|
199
|
+
config: Trigger configuration.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
Trigger instance or None if type not found.
|
|
203
|
+
"""
|
|
204
|
+
trigger_class = cls.get(trigger_type)
|
|
205
|
+
if trigger_class is None:
|
|
206
|
+
logger.warning(f"Unknown trigger type: {trigger_type}")
|
|
207
|
+
return None
|
|
208
|
+
return trigger_class(config)
|
|
209
|
+
|
|
210
|
+
@classmethod
|
|
211
|
+
def list_types(cls) -> list[str]:
|
|
212
|
+
"""List all registered trigger types.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
List of type identifiers.
|
|
216
|
+
"""
|
|
217
|
+
return list(cls._triggers.keys())
|
|
218
|
+
|
|
219
|
+
@classmethod
|
|
220
|
+
def get_all(cls) -> dict[str, type[BaseTrigger]]:
|
|
221
|
+
"""Get all registered trigger classes.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Dictionary of type -> class.
|
|
225
|
+
"""
|
|
226
|
+
return dict(cls._triggers)
|