detectkit 0.3.16__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.16/detectkit.egg-info → detectkit-0.3.17}/PKG-INFO +1 -1
  2. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/orchestrator.py +19 -17
  3. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/orchestration/task_manager.py +12 -1
  4. {detectkit-0.3.16 → detectkit-0.3.17/detectkit.egg-info}/PKG-INFO +1 -1
  5. {detectkit-0.3.16 → detectkit-0.3.17}/pyproject.toml +1 -1
  6. {detectkit-0.3.16 → detectkit-0.3.17}/LICENSE +0 -0
  7. {detectkit-0.3.16 → detectkit-0.3.17}/MANIFEST.in +0 -0
  8. {detectkit-0.3.16 → detectkit-0.3.17}/README.md +0 -0
  9. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/__init__.py +0 -0
  10. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/__init__.py +0 -0
  11. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/channels/__init__.py +0 -0
  12. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/channels/base.py +0 -0
  13. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/channels/email.py +0 -0
  14. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/channels/factory.py +0 -0
  15. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/channels/mattermost.py +0 -0
  16. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/channels/slack.py +0 -0
  17. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/channels/telegram.py +0 -0
  18. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/alerting/channels/webhook.py +0 -0
  19. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/cli/__init__.py +0 -0
  20. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/cli/commands/__init__.py +0 -0
  21. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/cli/commands/init.py +0 -0
  22. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/cli/commands/run.py +0 -0
  23. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/cli/commands/test_alert.py +0 -0
  24. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/cli/main.py +0 -0
  25. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/config/__init__.py +0 -0
  26. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/config/metric_config.py +0 -0
  27. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/config/profile.py +0 -0
  28. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/config/project_config.py +0 -0
  29. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/config/validator.py +0 -0
  30. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/core/__init__.py +0 -0
  31. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/core/interval.py +0 -0
  32. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/core/models.py +0 -0
  33. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/database/__init__.py +0 -0
  34. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/database/clickhouse_manager.py +0 -0
  35. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/database/internal_tables.py +0 -0
  36. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/database/manager.py +0 -0
  37. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/database/tables.py +0 -0
  38. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/detectors/__init__.py +0 -0
  39. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/detectors/base.py +0 -0
  40. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/detectors/factory.py +0 -0
  41. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/detectors/statistical/__init__.py +0 -0
  42. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/detectors/statistical/iqr.py +0 -0
  43. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/detectors/statistical/mad.py +0 -0
  44. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/detectors/statistical/manual_bounds.py +0 -0
  45. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/detectors/statistical/zscore.py +0 -0
  46. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/loaders/__init__.py +0 -0
  47. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/loaders/metric_loader.py +0 -0
  48. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/loaders/query_template.py +0 -0
  49. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/orchestration/__init__.py +0 -0
  50. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/utils/__init__.py +0 -0
  51. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/utils/datetime_utils.py +0 -0
  52. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit/utils/stats.py +0 -0
  53. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit.egg-info/SOURCES.txt +0 -0
  54. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit.egg-info/dependency_links.txt +0 -0
  55. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit.egg-info/entry_points.txt +0 -0
  56. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit.egg-info/requires.txt +0 -0
  57. {detectkit-0.3.16 → detectkit-0.3.17}/detectkit.egg-info/top_level.txt +0 -0
  58. {detectkit-0.3.16 → detectkit-0.3.17}/requirements.txt +0 -0
  59. {detectkit-0.3.16 → detectkit-0.3.17}/setup.cfg +0 -0
  60. {detectkit-0.3.16 → 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.16
3
+ Version: 0.3.17
4
4
  Summary: Metric monitoring with automatic anomaly detection
5
5
  Author: detectkit team
6
6
  License: MIT
@@ -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,
@@ -760,8 +760,19 @@ class TaskManager:
760
760
 
761
761
  metadata_list = row.get("detection_metadata_list") or [None] * len(row["detector_ids"])
762
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
+
763
774
  if is_anomaly and anomaly_indices:
764
- # Get data from first anomalous detector
775
+ # Override with data from first anomalous detector
765
776
  first_idx = anomaly_indices[0]
766
777
  detector_name = row["detector_names"][first_idx]
767
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.16
3
+ Version: 0.3.17
4
4
  Summary: Metric monitoring with automatic anomaly detection
5
5
  Author: detectkit team
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "detectkit"
7
- version = "0.3.16"
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
File without changes