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.
Files changed (60) hide show
  1. {detectkit-0.3.15/detectkit.egg-info → detectkit-0.3.17}/PKG-INFO +2 -1
  2. {detectkit-0.3.15 → detectkit-0.3.17}/README.md +1 -0
  3. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/orchestrator.py +19 -17
  4. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/metric_config.py +5 -0
  5. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/orchestration/task_manager.py +19 -1
  6. {detectkit-0.3.15 → detectkit-0.3.17/detectkit.egg-info}/PKG-INFO +2 -1
  7. {detectkit-0.3.15 → detectkit-0.3.17}/pyproject.toml +1 -1
  8. {detectkit-0.3.15 → detectkit-0.3.17}/LICENSE +0 -0
  9. {detectkit-0.3.15 → detectkit-0.3.17}/MANIFEST.in +0 -0
  10. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/__init__.py +0 -0
  11. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/__init__.py +0 -0
  12. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/__init__.py +0 -0
  13. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/base.py +0 -0
  14. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/email.py +0 -0
  15. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/factory.py +0 -0
  16. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/mattermost.py +0 -0
  17. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/slack.py +0 -0
  18. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/telegram.py +0 -0
  19. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/alerting/channels/webhook.py +0 -0
  20. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/__init__.py +0 -0
  21. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/commands/__init__.py +0 -0
  22. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/commands/init.py +0 -0
  23. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/commands/run.py +0 -0
  24. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/commands/test_alert.py +0 -0
  25. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/cli/main.py +0 -0
  26. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/__init__.py +0 -0
  27. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/profile.py +0 -0
  28. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/project_config.py +0 -0
  29. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/config/validator.py +0 -0
  30. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/core/__init__.py +0 -0
  31. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/core/interval.py +0 -0
  32. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/core/models.py +0 -0
  33. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/__init__.py +0 -0
  34. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/clickhouse_manager.py +0 -0
  35. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/internal_tables.py +0 -0
  36. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/manager.py +0 -0
  37. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/database/tables.py +0 -0
  38. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/__init__.py +0 -0
  39. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/base.py +0 -0
  40. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/factory.py +0 -0
  41. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/__init__.py +0 -0
  42. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/iqr.py +0 -0
  43. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/mad.py +0 -0
  44. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/manual_bounds.py +0 -0
  45. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/detectors/statistical/zscore.py +0 -0
  46. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/loaders/__init__.py +0 -0
  47. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/loaders/metric_loader.py +0 -0
  48. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/loaders/query_template.py +0 -0
  49. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/orchestration/__init__.py +0 -0
  50. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/utils/__init__.py +0 -0
  51. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/utils/datetime_utils.py +0 -0
  52. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit/utils/stats.py +0 -0
  53. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/SOURCES.txt +0 -0
  54. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/dependency_links.txt +0 -0
  55. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/entry_points.txt +0 -0
  56. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/requires.txt +0 -0
  57. {detectkit-0.3.15 → detectkit-0.3.17}/detectkit.egg-info/top_level.txt +0 -0
  58. {detectkit-0.3.15 → detectkit-0.3.17}/requirements.txt +0 -0
  59. {detectkit-0.3.15 → detectkit-0.3.17}/setup.cfg +0 -0
  60. {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.15
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
@@ -76,6 +76,7 @@ alerting:
76
76
  mentions: [oncall_engineer, here]
77
77
  alert_cooldown: "30min"
78
78
  notify_on_recovery: true
79
+ suppress_until: "2026-04-11 18:00:00" # Suppress alerts until this UTC time
79
80
  ```
80
81
 
81
82
  ### 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 detector info and CI from the last anomalous detection
691
- # (the one that triggered the alert), since normal points have
692
- # detector_name="unknown" and confidence=None.
693
- last_anomalous = next(
694
- (d for d in reversed(detections) if d.is_anomaly),
695
- None,
696
- )
697
- if last_anomalous:
698
- recovery_detector_name = last_anomalous.detector_name
699
- recovery_detector_params = last_anomalous.detector_params
700
- recovery_ci_lower = last_anomalous.confidence_lower
701
- recovery_ci_upper = last_anomalous.confidence_upper
702
- else:
703
- recovery_detector_name = latest.detector_name
704
- recovery_detector_params = latest.detector_params
705
- recovery_ci_lower = latest.confidence_lower
706
- recovery_ci_upper = latest.confidence_upper
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
- # Get data from first anomalous detector
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.15
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "detectkit"
7
- version = "0.3.15"
7
+ version = "0.3.17"
8
8
  description = "Metric monitoring with automatic anomaly detection"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes
File without changes
File without changes
File without changes
File without changes