truthound-dashboard 1.3.1__py3-none-any.whl → 1.4.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.
Files changed (169) hide show
  1. truthound_dashboard/api/alerts.py +258 -0
  2. truthound_dashboard/api/anomaly.py +1302 -0
  3. truthound_dashboard/api/cross_alerts.py +352 -0
  4. truthound_dashboard/api/deps.py +143 -0
  5. truthound_dashboard/api/drift_monitor.py +540 -0
  6. truthound_dashboard/api/lineage.py +1151 -0
  7. truthound_dashboard/api/maintenance.py +363 -0
  8. truthound_dashboard/api/middleware.py +373 -1
  9. truthound_dashboard/api/model_monitoring.py +805 -0
  10. truthound_dashboard/api/notifications_advanced.py +2452 -0
  11. truthound_dashboard/api/plugins.py +2096 -0
  12. truthound_dashboard/api/profile.py +211 -14
  13. truthound_dashboard/api/reports.py +853 -0
  14. truthound_dashboard/api/router.py +147 -0
  15. truthound_dashboard/api/rule_suggestions.py +310 -0
  16. truthound_dashboard/api/schema_evolution.py +231 -0
  17. truthound_dashboard/api/sources.py +47 -3
  18. truthound_dashboard/api/triggers.py +190 -0
  19. truthound_dashboard/api/validations.py +13 -0
  20. truthound_dashboard/api/validators.py +333 -4
  21. truthound_dashboard/api/versioning.py +309 -0
  22. truthound_dashboard/api/websocket.py +301 -0
  23. truthound_dashboard/core/__init__.py +27 -0
  24. truthound_dashboard/core/anomaly.py +1395 -0
  25. truthound_dashboard/core/anomaly_explainer.py +633 -0
  26. truthound_dashboard/core/cache.py +206 -0
  27. truthound_dashboard/core/cached_services.py +422 -0
  28. truthound_dashboard/core/charts.py +352 -0
  29. truthound_dashboard/core/connections.py +1069 -42
  30. truthound_dashboard/core/cross_alerts.py +837 -0
  31. truthound_dashboard/core/drift_monitor.py +1477 -0
  32. truthound_dashboard/core/drift_sampling.py +669 -0
  33. truthound_dashboard/core/i18n/__init__.py +42 -0
  34. truthound_dashboard/core/i18n/detector.py +173 -0
  35. truthound_dashboard/core/i18n/messages.py +564 -0
  36. truthound_dashboard/core/lineage.py +971 -0
  37. truthound_dashboard/core/maintenance.py +443 -5
  38. truthound_dashboard/core/model_monitoring.py +1043 -0
  39. truthound_dashboard/core/notifications/channels.py +1020 -1
  40. truthound_dashboard/core/notifications/deduplication/__init__.py +143 -0
  41. truthound_dashboard/core/notifications/deduplication/policies.py +274 -0
  42. truthound_dashboard/core/notifications/deduplication/service.py +400 -0
  43. truthound_dashboard/core/notifications/deduplication/stores.py +2365 -0
  44. truthound_dashboard/core/notifications/deduplication/strategies.py +422 -0
  45. truthound_dashboard/core/notifications/dispatcher.py +43 -0
  46. truthound_dashboard/core/notifications/escalation/__init__.py +149 -0
  47. truthound_dashboard/core/notifications/escalation/backends.py +1384 -0
  48. truthound_dashboard/core/notifications/escalation/engine.py +429 -0
  49. truthound_dashboard/core/notifications/escalation/models.py +336 -0
  50. truthound_dashboard/core/notifications/escalation/scheduler.py +1187 -0
  51. truthound_dashboard/core/notifications/escalation/state_machine.py +330 -0
  52. truthound_dashboard/core/notifications/escalation/stores.py +2896 -0
  53. truthound_dashboard/core/notifications/events.py +49 -0
  54. truthound_dashboard/core/notifications/metrics/__init__.py +115 -0
  55. truthound_dashboard/core/notifications/metrics/base.py +528 -0
  56. truthound_dashboard/core/notifications/metrics/collectors.py +583 -0
  57. truthound_dashboard/core/notifications/routing/__init__.py +169 -0
  58. truthound_dashboard/core/notifications/routing/combinators.py +184 -0
  59. truthound_dashboard/core/notifications/routing/config.py +375 -0
  60. truthound_dashboard/core/notifications/routing/config_parser.py +867 -0
  61. truthound_dashboard/core/notifications/routing/engine.py +382 -0
  62. truthound_dashboard/core/notifications/routing/expression_engine.py +1269 -0
  63. truthound_dashboard/core/notifications/routing/jinja2_engine.py +774 -0
  64. truthound_dashboard/core/notifications/routing/rules.py +625 -0
  65. truthound_dashboard/core/notifications/routing/validator.py +678 -0
  66. truthound_dashboard/core/notifications/service.py +2 -0
  67. truthound_dashboard/core/notifications/stats_aggregator.py +850 -0
  68. truthound_dashboard/core/notifications/throttling/__init__.py +83 -0
  69. truthound_dashboard/core/notifications/throttling/builder.py +311 -0
  70. truthound_dashboard/core/notifications/throttling/stores.py +1859 -0
  71. truthound_dashboard/core/notifications/throttling/throttlers.py +633 -0
  72. truthound_dashboard/core/openlineage.py +1028 -0
  73. truthound_dashboard/core/plugins/__init__.py +39 -0
  74. truthound_dashboard/core/plugins/docs/__init__.py +39 -0
  75. truthound_dashboard/core/plugins/docs/extractor.py +703 -0
  76. truthound_dashboard/core/plugins/docs/renderers.py +804 -0
  77. truthound_dashboard/core/plugins/hooks/__init__.py +63 -0
  78. truthound_dashboard/core/plugins/hooks/decorators.py +367 -0
  79. truthound_dashboard/core/plugins/hooks/manager.py +403 -0
  80. truthound_dashboard/core/plugins/hooks/protocols.py +265 -0
  81. truthound_dashboard/core/plugins/lifecycle/__init__.py +41 -0
  82. truthound_dashboard/core/plugins/lifecycle/hot_reload.py +584 -0
  83. truthound_dashboard/core/plugins/lifecycle/machine.py +419 -0
  84. truthound_dashboard/core/plugins/lifecycle/states.py +266 -0
  85. truthound_dashboard/core/plugins/loader.py +504 -0
  86. truthound_dashboard/core/plugins/registry.py +810 -0
  87. truthound_dashboard/core/plugins/reporter_executor.py +588 -0
  88. truthound_dashboard/core/plugins/sandbox/__init__.py +59 -0
  89. truthound_dashboard/core/plugins/sandbox/code_validator.py +243 -0
  90. truthound_dashboard/core/plugins/sandbox/engines.py +770 -0
  91. truthound_dashboard/core/plugins/sandbox/protocols.py +194 -0
  92. truthound_dashboard/core/plugins/sandbox.py +617 -0
  93. truthound_dashboard/core/plugins/security/__init__.py +68 -0
  94. truthound_dashboard/core/plugins/security/analyzer.py +535 -0
  95. truthound_dashboard/core/plugins/security/policies.py +311 -0
  96. truthound_dashboard/core/plugins/security/protocols.py +296 -0
  97. truthound_dashboard/core/plugins/security/signing.py +842 -0
  98. truthound_dashboard/core/plugins/security.py +446 -0
  99. truthound_dashboard/core/plugins/validator_executor.py +401 -0
  100. truthound_dashboard/core/plugins/versioning/__init__.py +51 -0
  101. truthound_dashboard/core/plugins/versioning/constraints.py +377 -0
  102. truthound_dashboard/core/plugins/versioning/dependencies.py +541 -0
  103. truthound_dashboard/core/plugins/versioning/semver.py +266 -0
  104. truthound_dashboard/core/profile_comparison.py +601 -0
  105. truthound_dashboard/core/report_history.py +570 -0
  106. truthound_dashboard/core/reporters/__init__.py +57 -0
  107. truthound_dashboard/core/reporters/base.py +296 -0
  108. truthound_dashboard/core/reporters/csv_reporter.py +155 -0
  109. truthound_dashboard/core/reporters/html_reporter.py +598 -0
  110. truthound_dashboard/core/reporters/i18n/__init__.py +65 -0
  111. truthound_dashboard/core/reporters/i18n/base.py +494 -0
  112. truthound_dashboard/core/reporters/i18n/catalogs.py +930 -0
  113. truthound_dashboard/core/reporters/json_reporter.py +160 -0
  114. truthound_dashboard/core/reporters/junit_reporter.py +233 -0
  115. truthound_dashboard/core/reporters/markdown_reporter.py +207 -0
  116. truthound_dashboard/core/reporters/pdf_reporter.py +209 -0
  117. truthound_dashboard/core/reporters/registry.py +272 -0
  118. truthound_dashboard/core/rule_generator.py +2088 -0
  119. truthound_dashboard/core/scheduler.py +822 -12
  120. truthound_dashboard/core/schema_evolution.py +858 -0
  121. truthound_dashboard/core/services.py +152 -9
  122. truthound_dashboard/core/statistics.py +718 -0
  123. truthound_dashboard/core/streaming_anomaly.py +883 -0
  124. truthound_dashboard/core/triggers/__init__.py +45 -0
  125. truthound_dashboard/core/triggers/base.py +226 -0
  126. truthound_dashboard/core/triggers/evaluators.py +609 -0
  127. truthound_dashboard/core/triggers/factory.py +363 -0
  128. truthound_dashboard/core/unified_alerts.py +870 -0
  129. truthound_dashboard/core/validation_limits.py +509 -0
  130. truthound_dashboard/core/versioning.py +709 -0
  131. truthound_dashboard/core/websocket/__init__.py +59 -0
  132. truthound_dashboard/core/websocket/manager.py +512 -0
  133. truthound_dashboard/core/websocket/messages.py +130 -0
  134. truthound_dashboard/db/__init__.py +30 -0
  135. truthound_dashboard/db/models.py +3375 -3
  136. truthound_dashboard/main.py +22 -0
  137. truthound_dashboard/schemas/__init__.py +396 -1
  138. truthound_dashboard/schemas/anomaly.py +1258 -0
  139. truthound_dashboard/schemas/base.py +4 -0
  140. truthound_dashboard/schemas/cross_alerts.py +334 -0
  141. truthound_dashboard/schemas/drift_monitor.py +890 -0
  142. truthound_dashboard/schemas/lineage.py +428 -0
  143. truthound_dashboard/schemas/maintenance.py +154 -0
  144. truthound_dashboard/schemas/model_monitoring.py +374 -0
  145. truthound_dashboard/schemas/notifications_advanced.py +1363 -0
  146. truthound_dashboard/schemas/openlineage.py +704 -0
  147. truthound_dashboard/schemas/plugins.py +1293 -0
  148. truthound_dashboard/schemas/profile.py +420 -34
  149. truthound_dashboard/schemas/profile_comparison.py +242 -0
  150. truthound_dashboard/schemas/reports.py +285 -0
  151. truthound_dashboard/schemas/rule_suggestion.py +434 -0
  152. truthound_dashboard/schemas/schema_evolution.py +164 -0
  153. truthound_dashboard/schemas/source.py +117 -2
  154. truthound_dashboard/schemas/triggers.py +511 -0
  155. truthound_dashboard/schemas/unified_alerts.py +223 -0
  156. truthound_dashboard/schemas/validation.py +25 -1
  157. truthound_dashboard/schemas/validators/__init__.py +11 -0
  158. truthound_dashboard/schemas/validators/base.py +151 -0
  159. truthound_dashboard/schemas/versioning.py +152 -0
  160. truthound_dashboard/static/index.html +2 -2
  161. {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.0.dist-info}/METADATA +142 -22
  162. truthound_dashboard-1.4.0.dist-info/RECORD +239 -0
  163. truthound_dashboard/static/assets/index-BZG20KuF.js +0 -586
  164. truthound_dashboard/static/assets/index-D_HyZ3pb.css +0 -1
  165. truthound_dashboard/static/assets/unmerged_dictionaries-CtpqQBm0.js +0 -1
  166. truthound_dashboard-1.3.1.dist-info/RECORD +0 -110
  167. {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.0.dist-info}/WHEEL +0 -0
  168. {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.0.dist-info}/entry_points.txt +0 -0
  169. {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.0.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)