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.
Files changed (84) hide show
  1. {detectkit-0.4.0/detectkit.egg-info → detectkit-0.4.1}/PKG-INFO +1 -1
  2. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/__init__.py +1 -1
  3. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_base.py +29 -53
  4. {detectkit-0.4.0 → detectkit-0.4.1/detectkit.egg-info}/PKG-INFO +1 -1
  5. {detectkit-0.4.0 → detectkit-0.4.1}/pyproject.toml +1 -1
  6. {detectkit-0.4.0 → detectkit-0.4.1}/LICENSE +0 -0
  7. {detectkit-0.4.0 → detectkit-0.4.1}/MANIFEST.in +0 -0
  8. {detectkit-0.4.0 → detectkit-0.4.1}/README.md +0 -0
  9. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/__init__.py +0 -0
  10. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/__init__.py +0 -0
  11. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/base.py +0 -0
  12. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/email.py +0 -0
  13. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/factory.py +0 -0
  14. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/mattermost.py +0 -0
  15. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/slack.py +0 -0
  16. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/telegram.py +0 -0
  17. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/channels/webhook.py +0 -0
  18. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/__init__.py +0 -0
  19. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_base.py +0 -0
  20. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_cooldown.py +0 -0
  21. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_decision.py +0 -0
  22. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_dispatch.py +0 -0
  23. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_recovery.py +0 -0
  24. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/_types.py +0 -0
  25. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/alerting/orchestrator/orchestrator.py +0 -0
  26. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/__init__.py +0 -0
  27. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/commands/__init__.py +0 -0
  28. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/commands/init.py +0 -0
  29. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/commands/run.py +0 -0
  30. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/commands/test_alert.py +0 -0
  31. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/cli/main.py +0 -0
  32. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/__init__.py +0 -0
  33. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/metric_config.py +0 -0
  34. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/profile.py +0 -0
  35. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/project_config.py +0 -0
  36. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/config/validator.py +0 -0
  37. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/core/__init__.py +0 -0
  38. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/core/interval.py +0 -0
  39. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/core/models.py +0 -0
  40. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/__init__.py +0 -0
  41. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/clickhouse_manager.py +0 -0
  42. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/__init__.py +0 -0
  43. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_alert_states.py +0 -0
  44. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_base.py +0 -0
  45. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_datapoints.py +0 -0
  46. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_detections.py +0 -0
  47. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_metrics.py +0 -0
  48. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_schema.py +0 -0
  49. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/_tasks.py +0 -0
  50. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/internal_tables/manager.py +0 -0
  51. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/manager.py +0 -0
  52. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/database/tables.py +0 -0
  53. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/__init__.py +0 -0
  54. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/base.py +0 -0
  55. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/factory.py +0 -0
  56. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/seasonality.py +0 -0
  57. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/__init__.py +0 -0
  58. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/iqr.py +0 -0
  59. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/mad.py +0 -0
  60. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/manual_bounds.py +0 -0
  61. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/detectors/statistical/zscore.py +0 -0
  62. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/loaders/__init__.py +0 -0
  63. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/loaders/metric_loader.py +0 -0
  64. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/loaders/query_template.py +0 -0
  65. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/__init__.py +0 -0
  66. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/__init__.py +0 -0
  67. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_alert_step.py +0 -0
  68. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_detect_step.py +0 -0
  69. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_load_step.py +0 -0
  70. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/_types.py +0 -0
  71. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/orchestration/task_manager/manager.py +0 -0
  72. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/__init__.py +0 -0
  73. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/datetime_utils.py +0 -0
  74. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/env_interpolation.py +0 -0
  75. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/json_utils.py +0 -0
  76. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit/utils/stats.py +0 -0
  77. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/SOURCES.txt +0 -0
  78. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/dependency_links.txt +0 -0
  79. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/entry_points.txt +0 -0
  80. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/requires.txt +0 -0
  81. {detectkit-0.4.0 → detectkit-0.4.1}/detectkit.egg-info/top_level.txt +0 -0
  82. {detectkit-0.4.0 → detectkit-0.4.1}/requirements.txt +0 -0
  83. {detectkit-0.4.0 → detectkit-0.4.1}/setup.cfg +0 -0
  84. {detectkit-0.4.0 → detectkit-0.4.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: detectkit
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Metric monitoring with automatic anomaly detection
5
5
  Author: detectkit team
6
6
  License: MIT
@@ -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.0"
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
- for row in results:
50
- is_anomaly = any(row["is_anomaly_flags"])
51
- anomaly_indices = [
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
- # Always read the first detector's CI so recovery messages
70
- # display the *current* confidence interval, not a stale one.
71
- if row["confidence_lowers"] and row["confidence_uppers"]:
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
- records.append(
95
- DetectionRecord(
96
- timestamp=row["timestamp"],
97
- detector_name=detector_name,
98
- detector_id=detector_id,
99
- detector_params=detector_params,
100
- value=row["value"],
101
- is_anomaly=is_anomaly,
102
- confidence_lower=confidence_lower,
103
- confidence_upper=confidence_upper,
104
- direction=direction,
105
- severity=severity,
106
- detection_metadata=metadata,
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
- # Caller wants chronological order; the SQL returns DESC.
111
- return list(reversed(records))
87
+ return records
112
88
 
113
89
  def _create_alert_channels(
114
90
  self, channel_names: List[str]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: detectkit
3
- Version: 0.4.0
3
+ Version: 0.4.1
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.4.0"
7
+ version = "0.4.1"
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