detectkit 0.3.15__tar.gz → 0.3.17__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.15/detectkit.egg-info → detectkit-0.3.17}/PKG-INFO +2 -1
- {detectkit-0.3.15 → detectkit-0.3.17}/README.md +1 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/orchestrator.py +19 -17
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/metric_config.py +5 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/orchestration/task_manager.py +19 -1
- {detectkit-0.3.15 → detectkit-0.3.17/detectkit.egg-info}/PKG-INFO +2 -1
- {detectkit-0.3.15 → detectkit-0.3.17}/pyproject.toml +1 -1
- {detectkit-0.3.15 → detectkit-0.3.17}/LICENSE +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/MANIFEST.in +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/base.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/email.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/factory.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/mattermost.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/slack.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/telegram.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/webhook.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/commands/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/commands/init.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/commands/run.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/commands/test_alert.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/main.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/profile.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/project_config.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/validator.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/core/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/core/interval.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/core/models.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/clickhouse_manager.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/internal_tables.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/manager.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/tables.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/base.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/factory.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/iqr.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/mad.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/manual_bounds.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/zscore.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/loaders/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/loaders/metric_loader.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/loaders/query_template.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/orchestration/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/utils/__init__.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/utils/datetime_utils.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/utils/stats.py +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/SOURCES.txt +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/dependency_links.txt +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/entry_points.txt +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/requires.txt +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/top_level.txt +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/requirements.txt +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/setup.cfg +0 -0
- {detectkit-0.3.15 → detectkit-0.3.17}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: detectkit
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.17
|
|
4
4
|
Summary: Metric monitoring with automatic anomaly detection
|
|
5
5
|
Author: detectkit team
|
|
6
6
|
License: MIT
|
|
@@ -138,6 +138,7 @@ alerting:
|
|
|
138
138
|
mentions: [oncall_engineer, here]
|
|
139
139
|
alert_cooldown: "30min"
|
|
140
140
|
notify_on_recovery: true
|
|
141
|
+
suppress_until: "2026-04-11 18:00:00" # Suppress alerts until this UTC time
|
|
141
142
|
```
|
|
142
143
|
|
|
143
144
|
### Python API
|
|
@@ -687,23 +687,25 @@ class AlertOrchestrator:
|
|
|
687
687
|
# detections are sorted oldest→newest by _load_recent_detections.
|
|
688
688
|
latest = detections[-1]
|
|
689
689
|
|
|
690
|
-
# Use
|
|
691
|
-
#
|
|
692
|
-
#
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
690
|
+
# Use CI from the latest point (current detection) so the recovery
|
|
691
|
+
# message shows the actual confidence interval for this timestamp.
|
|
692
|
+
# Fall back to last anomalous detection only if latest has no CI
|
|
693
|
+
# (e.g. missing_data / insufficient_data points).
|
|
694
|
+
recovery_ci_lower = latest.confidence_lower
|
|
695
|
+
recovery_ci_upper = latest.confidence_upper
|
|
696
|
+
recovery_detector_name = latest.detector_name
|
|
697
|
+
recovery_detector_params = latest.detector_params
|
|
698
|
+
|
|
699
|
+
if recovery_ci_lower is None or recovery_ci_upper is None:
|
|
700
|
+
last_anomalous = next(
|
|
701
|
+
(d for d in reversed(detections) if d.is_anomaly),
|
|
702
|
+
None,
|
|
703
|
+
)
|
|
704
|
+
if last_anomalous:
|
|
705
|
+
recovery_detector_name = last_anomalous.detector_name
|
|
706
|
+
recovery_detector_params = last_anomalous.detector_params
|
|
707
|
+
recovery_ci_lower = last_anomalous.confidence_lower
|
|
708
|
+
recovery_ci_upper = last_anomalous.confidence_upper
|
|
707
709
|
|
|
708
710
|
return AlertData(
|
|
709
711
|
metric_name=self.metric_name,
|
|
@@ -146,6 +146,11 @@ class AlertConfig(BaseModel):
|
|
|
146
146
|
"""
|
|
147
147
|
|
|
148
148
|
enabled: bool = Field(default=True, description="Enable alerting")
|
|
149
|
+
suppress_until: Optional[str] = Field(
|
|
150
|
+
default=None,
|
|
151
|
+
description="Suppress alerts until this UTC datetime (e.g., '2026-04-11 18:00:00'). "
|
|
152
|
+
"Load and detect steps still run. Alerts auto-resume after this time."
|
|
153
|
+
)
|
|
149
154
|
timezone: Optional[str] = Field(
|
|
150
155
|
default=None, description="Timezone for displaying timestamps (e.g., 'Europe/Moscow')"
|
|
151
156
|
)
|
|
@@ -606,6 +606,13 @@ class TaskManager:
|
|
|
606
606
|
if multi:
|
|
607
607
|
click.echo(f" │ [config {i + 1}/{len(active_configs)}] channels: {alerting_config.channels}")
|
|
608
608
|
|
|
609
|
+
# Check suppress_until
|
|
610
|
+
if alerting_config.suppress_until:
|
|
611
|
+
suppress_dt = datetime.strptime(alerting_config.suppress_until, "%Y-%m-%d %H:%M:%S")
|
|
612
|
+
if now_utc_naive() < suppress_dt:
|
|
613
|
+
click.echo(f" │ Alerts suppressed until {alerting_config.suppress_until} UTC")
|
|
614
|
+
continue
|
|
615
|
+
|
|
609
616
|
click.echo(f" │ Checking alert conditions...")
|
|
610
617
|
|
|
611
618
|
alert_config_id = _make_alert_config_id(alerting_config)
|
|
@@ -753,8 +760,19 @@ class TaskManager:
|
|
|
753
760
|
|
|
754
761
|
metadata_list = row.get("detection_metadata_list") or [None] * len(row["detector_ids"])
|
|
755
762
|
|
|
763
|
+
# Always read CI from the first detector so that recovery
|
|
764
|
+
# messages display the *current* confidence interval, not a
|
|
765
|
+
# stale one from the last anomalous point.
|
|
766
|
+
if row["confidence_lowers"] and row["confidence_uppers"]:
|
|
767
|
+
confidence_lower = row["confidence_lowers"][0]
|
|
768
|
+
confidence_upper = row["confidence_uppers"][0]
|
|
769
|
+
if row["detector_names"]:
|
|
770
|
+
detector_name = row["detector_names"][0]
|
|
771
|
+
detector_id = row["detector_ids"][0]
|
|
772
|
+
detector_params = row["detector_params_list"][0]
|
|
773
|
+
|
|
756
774
|
if is_anomaly and anomaly_indices:
|
|
757
|
-
#
|
|
775
|
+
# Override with data from first anomalous detector
|
|
758
776
|
first_idx = anomaly_indices[0]
|
|
759
777
|
detector_name = row["detector_names"][first_idx]
|
|
760
778
|
detector_id = row["detector_ids"][first_idx]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: detectkit
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.17
|
|
4
4
|
Summary: Metric monitoring with automatic anomaly detection
|
|
5
5
|
Author: detectkit team
|
|
6
6
|
License: MIT
|
|
@@ -138,6 +138,7 @@ alerting:
|
|
|
138
138
|
mentions: [oncall_engineer, here]
|
|
139
139
|
alert_cooldown: "30min"
|
|
140
140
|
notify_on_recovery: true
|
|
141
|
+
suppress_until: "2026-04-11 18:00:00" # Suppress alerts until this UTC time
|
|
141
142
|
```
|
|
142
143
|
|
|
143
144
|
### Python API
|
|
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
|