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.
Files changed (59) hide show
  1. {detectkit-0.3.9/detectkit.egg-info → detectkit-0.3.10}/PKG-INFO +1 -1
  2. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/__init__.py +1 -1
  3. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/orchestrator.py +14 -8
  4. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/orchestration/task_manager.py +7 -14
  5. {detectkit-0.3.9 → detectkit-0.3.10/detectkit.egg-info}/PKG-INFO +1 -1
  6. {detectkit-0.3.9 → detectkit-0.3.10}/pyproject.toml +1 -1
  7. {detectkit-0.3.9 → detectkit-0.3.10}/LICENSE +0 -0
  8. {detectkit-0.3.9 → detectkit-0.3.10}/MANIFEST.in +0 -0
  9. {detectkit-0.3.9 → detectkit-0.3.10}/README.md +0 -0
  10. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/__init__.py +0 -0
  11. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/__init__.py +0 -0
  12. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/base.py +0 -0
  13. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/email.py +0 -0
  14. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/factory.py +0 -0
  15. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/mattermost.py +0 -0
  16. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/slack.py +0 -0
  17. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/telegram.py +0 -0
  18. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/alerting/channels/webhook.py +0 -0
  19. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/__init__.py +0 -0
  20. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/commands/__init__.py +0 -0
  21. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/commands/init.py +0 -0
  22. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/commands/run.py +0 -0
  23. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/commands/test_alert.py +0 -0
  24. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/cli/main.py +0 -0
  25. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/__init__.py +0 -0
  26. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/metric_config.py +0 -0
  27. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/profile.py +0 -0
  28. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/project_config.py +0 -0
  29. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/config/validator.py +0 -0
  30. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/core/__init__.py +0 -0
  31. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/core/interval.py +0 -0
  32. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/core/models.py +0 -0
  33. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/__init__.py +0 -0
  34. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/clickhouse_manager.py +0 -0
  35. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/internal_tables.py +0 -0
  36. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/manager.py +0 -0
  37. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/database/tables.py +0 -0
  38. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/__init__.py +0 -0
  39. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/base.py +0 -0
  40. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/factory.py +0 -0
  41. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/__init__.py +0 -0
  42. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/iqr.py +0 -0
  43. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/mad.py +0 -0
  44. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/manual_bounds.py +0 -0
  45. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/detectors/statistical/zscore.py +0 -0
  46. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/loaders/__init__.py +0 -0
  47. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/loaders/metric_loader.py +0 -0
  48. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/loaders/query_template.py +0 -0
  49. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/orchestration/__init__.py +0 -0
  50. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/utils/__init__.py +0 -0
  51. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit/utils/stats.py +0 -0
  52. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/SOURCES.txt +0 -0
  53. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/dependency_links.txt +0 -0
  54. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/entry_points.txt +0 -0
  55. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/requires.txt +0 -0
  56. {detectkit-0.3.9 → detectkit-0.3.10}/detectkit.egg-info/top_level.txt +0 -0
  57. {detectkit-0.3.9 → detectkit-0.3.10}/requirements.txt +0 -0
  58. {detectkit-0.3.9 → detectkit-0.3.10}/setup.cfg +0 -0
  59. {detectkit-0.3.9 → detectkit-0.3.10}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: detectkit
3
- Version: 0.3.9
3
+ Version: 0.3.10
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.3.9"
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
- # Count consecutive anomalies (same logic as should_alert)
523
- consecutive = self._count_consecutive_anomalies(
524
- detections=detection_records,
525
- min_detectors=self.conditions.min_detectors,
526
- direction=self.conditions.direction
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
- # Recovery = consecutive dropped below threshold
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
- # Skip alert if no anomalies detected in current run
195
- if result.get("anomalies_detected", 0) == 0:
196
- click.echo()
197
- click.echo(click.style(" ┌─ ALERT", fg="cyan", bold=True))
198
- click.echo(" │ No anomalies detected in current run, skipping alerts")
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=1, # At least one detector must flag anomaly
596
+ min_detectors=alerting_config.min_detectors,
604
597
  direction=alerting_config.direction,
605
598
  consecutive_anomalies=alerting_config.consecutive_anomalies,
606
599
  ),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: detectkit
3
- Version: 0.3.9
3
+ Version: 0.3.10
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.9"
7
+ version = "0.3.10"
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