detectkit 0.4.0__tar.gz → 0.4.1__tar.gz
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.
- {detectkit-0.4.0/detectkit.egg-info → detectkit-0.4.1}/PKG-INFO +1 -1
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/__init__.py +1 -1
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_base.py +29 -53
- {detectkit-0.4.0 → detectkit-0.4.1/detectkit.egg-info}/PKG-INFO +1 -1
- {detectkit-0.4.0 → detectkit-0.4.1}/pyproject.toml +1 -1
- {detectkit-0.4.0 → detectkit-0.4.1}/LICENSE +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/MANIFEST.in +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/README.md +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/base.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/email.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/factory.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/mattermost.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/slack.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/telegram.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/webhook.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_base.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_cooldown.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_decision.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_dispatch.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_recovery.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_types.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/orchestrator.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/commands/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/commands/init.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/commands/run.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/commands/test_alert.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/main.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/metric_config.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/profile.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/project_config.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/validator.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/core/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/core/interval.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/core/models.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/clickhouse_manager.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_alert_states.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_base.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_datapoints.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_detections.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_metrics.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_schema.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_tasks.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/manager.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/manager.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/tables.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/base.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/factory.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/seasonality.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/iqr.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/mad.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/manual_bounds.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/zscore.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/loaders/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/loaders/metric_loader.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/loaders/query_template.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_alert_step.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_detect_step.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_load_step.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_types.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/manager.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/__init__.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/datetime_utils.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/env_interpolation.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/json_utils.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/stats.py +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/SOURCES.txt +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/dependency_links.txt +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/entry_points.txt +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/requires.txt +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/top_level.txt +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/requirements.txt +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/setup.cfg +0 -0
- {detectkit-0.4.0 → detectkit-0.4.1}/setup.py +0 -0
|
@@ -4,7 +4,7 @@ detectk - Anomaly Detection for Time-Series Metrics
|
|
|
4
4
|
A Python library for data analysts and engineers to monitor metrics with automatic anomaly detection.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "0.4.
|
|
7
|
+
__version__ = "0.4.1"
|
|
8
8
|
|
|
9
9
|
from detectkit.core.interval import Interval
|
|
10
10
|
from detectkit.core.models import ColumnDefinition, TableModel
|
|
@@ -36,7 +36,13 @@ class _TaskManagerBase:
|
|
|
36
36
|
last_point: datetime,
|
|
37
37
|
num_points: int,
|
|
38
38
|
) -> List[DetectionRecord]:
|
|
39
|
-
"""Build :class:`DetectionRecord` rows for the last *num_points* timestamps.
|
|
39
|
+
"""Build :class:`DetectionRecord` rows for the last *num_points* timestamps.
|
|
40
|
+
|
|
41
|
+
Emits one record *per detector per timestamp* so the orchestrator can
|
|
42
|
+
evaluate multi-detector consensus (``min_detectors``). Collapsing
|
|
43
|
+
detectors into a single record breaks ``min_detectors >= 2`` because
|
|
44
|
+
``should_alert`` counts records, not flags.
|
|
45
|
+
"""
|
|
40
46
|
results = self.internal.get_recent_detections(
|
|
41
47
|
metric_name=metric_name,
|
|
42
48
|
last_point=last_point,
|
|
@@ -46,69 +52,39 @@ class _TaskManagerBase:
|
|
|
46
52
|
return []
|
|
47
53
|
|
|
48
54
|
records: List[DetectionRecord] = []
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
i for i, flag in enumerate(row["is_anomaly_flags"]) if flag
|
|
53
|
-
]
|
|
54
|
-
|
|
55
|
-
direction = "none"
|
|
56
|
-
severity = 0.0
|
|
57
|
-
confidence_lower = None
|
|
58
|
-
confidence_upper = None
|
|
59
|
-
detector_name = "unknown"
|
|
60
|
-
detector_id = "unknown"
|
|
61
|
-
detector_params = "{}"
|
|
62
|
-
metadata: dict = {}
|
|
63
|
-
|
|
55
|
+
# SQL returns timestamps DESC; iterate reversed so output is oldest→newest
|
|
56
|
+
# (recovery code reads ``detections[-1]`` to find the latest point).
|
|
57
|
+
for row in reversed(results):
|
|
64
58
|
metadata_list = (
|
|
65
59
|
row.get("detection_metadata_list")
|
|
66
60
|
or [None] * len(row["detector_ids"])
|
|
67
61
|
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
confidence_lower = row["confidence_lowers"][0]
|
|
73
|
-
confidence_upper = row["confidence_uppers"][0]
|
|
74
|
-
if row["detector_names"]:
|
|
75
|
-
detector_name = row["detector_names"][0]
|
|
76
|
-
detector_id = row["detector_ids"][0]
|
|
77
|
-
detector_params = row["detector_params_list"][0]
|
|
78
|
-
|
|
79
|
-
if is_anomaly and anomaly_indices:
|
|
80
|
-
first_idx = anomaly_indices[0]
|
|
81
|
-
detector_name = row["detector_names"][first_idx]
|
|
82
|
-
detector_id = row["detector_ids"][first_idx]
|
|
83
|
-
detector_params = row["detector_params_list"][first_idx]
|
|
84
|
-
confidence_lower = row["confidence_lowers"][first_idx]
|
|
85
|
-
confidence_upper = row["confidence_uppers"][first_idx]
|
|
86
|
-
|
|
87
|
-
metadata = _parse_detection_metadata(metadata_list[first_idx])
|
|
88
|
-
direction = _direction_from_metadata(metadata, True)
|
|
62
|
+
for i in range(len(row["detector_ids"])):
|
|
63
|
+
is_anomaly = bool(row["is_anomaly_flags"][i])
|
|
64
|
+
metadata = _parse_detection_metadata(metadata_list[i])
|
|
65
|
+
direction = _direction_from_metadata(metadata, is_anomaly)
|
|
89
66
|
try:
|
|
90
67
|
severity = float(metadata.get("severity", 0.0) or 0.0)
|
|
91
68
|
except (TypeError, ValueError):
|
|
92
69
|
severity = 0.0
|
|
93
70
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
71
|
+
records.append(
|
|
72
|
+
DetectionRecord(
|
|
73
|
+
timestamp=row["timestamp"],
|
|
74
|
+
detector_name=row["detector_names"][i],
|
|
75
|
+
detector_id=row["detector_ids"][i],
|
|
76
|
+
detector_params=row["detector_params_list"][i],
|
|
77
|
+
value=row["value"],
|
|
78
|
+
is_anomaly=is_anomaly,
|
|
79
|
+
confidence_lower=row["confidence_lowers"][i],
|
|
80
|
+
confidence_upper=row["confidence_uppers"][i],
|
|
81
|
+
direction=direction,
|
|
82
|
+
severity=severity,
|
|
83
|
+
detection_metadata=metadata,
|
|
84
|
+
)
|
|
107
85
|
)
|
|
108
|
-
)
|
|
109
86
|
|
|
110
|
-
|
|
111
|
-
return list(reversed(records))
|
|
87
|
+
return records
|
|
112
88
|
|
|
113
89
|
def _create_alert_channels(
|
|
114
90
|
self, channel_names: List[str]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|