detectkit 0.3.9__tar.gz → 0.3.10__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.3.9/detectkit.egg-info → detectkit-0.3.10}/PKG-INFO +1 -1
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/__init__.py +1 -1
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/orchestrator.py +14 -8
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/orchestration/task_manager.py +7 -14
- {detectkit-0.3.9 → detectkit-0.3.10/detectkit.egg-info}/PKG-INFO +1 -1
- {detectkit-0.3.9 → detectkit-0.3.10}/pyproject.toml +1 -1
- {detectkit-0.3.9 → detectkit-0.3.10}/LICENSE +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/MANIFEST.in +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/README.md +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/base.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/email.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/factory.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/mattermost.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/slack.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/telegram.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/webhook.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/commands/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/commands/init.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/commands/run.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/commands/test_alert.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/main.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/metric_config.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/profile.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/project_config.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/validator.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/core/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/core/interval.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/core/models.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/clickhouse_manager.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/internal_tables.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/manager.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/tables.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/base.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/factory.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/iqr.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/mad.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/manual_bounds.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/zscore.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/loaders/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/loaders/metric_loader.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/loaders/query_template.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/orchestration/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/utils/__init__.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/utils/stats.py +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/SOURCES.txt +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/dependency_links.txt +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/entry_points.txt +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/requires.txt +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/top_level.txt +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/requirements.txt +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/setup.cfg +0 -0
- {detectkit-0.3.9 → detectkit-0.3.10}/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.3.
|
|
7
|
+
__version__ = "0.3.10"
|
|
8
8
|
|
|
9
9
|
from detectkit.core.interval import Interval
|
|
10
10
|
from detectkit.core.models import ColumnDefinition, TableModel
|
|
@@ -519,15 +519,21 @@ class AlertOrchestrator:
|
|
|
519
519
|
)
|
|
520
520
|
detection_records.append(record)
|
|
521
521
|
|
|
522
|
-
#
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
522
|
+
# Group by timestamp and sort (same format as should_alert uses)
|
|
523
|
+
detections_by_time = self._group_by_timestamp(detection_records)
|
|
524
|
+
timestamps_sorted = sorted(detections_by_time.keys(), reverse=True)
|
|
525
|
+
|
|
526
|
+
# Check that latest post-alert point is NOT anomalous
|
|
527
|
+
# (prevents false recovery when there are fewer post-alert points
|
|
528
|
+
# than consecutive_anomalies threshold)
|
|
529
|
+
latest_ts = timestamps_sorted[0]
|
|
530
|
+
latest_detections = detections_by_time[latest_ts]
|
|
531
|
+
latest_anomalies = [d for d in latest_detections if d.is_anomaly]
|
|
532
|
+
if len(latest_anomalies) >= self.conditions.min_detectors:
|
|
533
|
+
# Latest point is still anomalous — no recovery
|
|
534
|
+
return False
|
|
528
535
|
|
|
529
|
-
|
|
530
|
-
return consecutive < self.conditions.consecutive_anomalies
|
|
536
|
+
return True
|
|
531
537
|
|
|
532
538
|
def should_send_recovery(
|
|
533
539
|
self,
|
|
@@ -189,20 +189,13 @@ class TaskManager:
|
|
|
189
189
|
result["anomalies_detected"] = detect_result["anomalies_count"]
|
|
190
190
|
result["steps_completed"].append(PipelineStep.DETECT)
|
|
191
191
|
|
|
192
|
-
# Step 3: Send alerts
|
|
192
|
+
# Step 3: Send alerts (also handles recovery notifications)
|
|
193
193
|
if PipelineStep.ALERT in steps:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
result["alerts_sent"] = 0
|
|
200
|
-
else:
|
|
201
|
-
click.echo()
|
|
202
|
-
click.echo(click.style(" ┌─ ALERT", fg="cyan", bold=True))
|
|
203
|
-
alert_result = self._run_alert_step(config)
|
|
204
|
-
result["alerts_sent"] = alert_result["alerts_sent"]
|
|
205
|
-
result["steps_completed"].append(PipelineStep.ALERT)
|
|
194
|
+
click.echo()
|
|
195
|
+
click.echo(click.style(" ┌─ ALERT", fg="cyan", bold=True))
|
|
196
|
+
alert_result = self._run_alert_step(config)
|
|
197
|
+
result["alerts_sent"] = alert_result["alerts_sent"]
|
|
198
|
+
result["steps_completed"].append(PipelineStep.ALERT)
|
|
206
199
|
|
|
207
200
|
finally:
|
|
208
201
|
# Always release lock
|
|
@@ -600,7 +593,7 @@ class TaskManager:
|
|
|
600
593
|
metric_name=config.name,
|
|
601
594
|
interval=interval,
|
|
602
595
|
conditions=AlertConditions(
|
|
603
|
-
min_detectors=
|
|
596
|
+
min_detectors=alerting_config.min_detectors,
|
|
604
597
|
direction=alerting_config.direction,
|
|
605
598
|
consecutive_anomalies=alerting_config.consecutive_anomalies,
|
|
606
599
|
),
|
|
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
|