detectkit 0.3.14__tar.gz → 0.3.15__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.14/detectkit.egg-info → detectkit-0.3.15}/PKG-INFO +1 -1
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/channels/base.py +6 -3
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/orchestrator.py +23 -5
- {detectkit-0.3.14 → detectkit-0.3.15/detectkit.egg-info}/PKG-INFO +1 -1
- {detectkit-0.3.14 → detectkit-0.3.15}/pyproject.toml +1 -1
- {detectkit-0.3.14 → detectkit-0.3.15}/LICENSE +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/MANIFEST.in +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/README.md +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/channels/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/channels/email.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/channels/factory.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/channels/mattermost.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/channels/slack.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/channels/telegram.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/alerting/channels/webhook.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/cli/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/cli/commands/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/cli/commands/init.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/cli/commands/run.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/cli/commands/test_alert.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/cli/main.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/config/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/config/metric_config.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/config/profile.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/config/project_config.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/config/validator.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/core/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/core/interval.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/core/models.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/database/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/database/clickhouse_manager.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/database/internal_tables.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/database/manager.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/database/tables.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/detectors/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/detectors/base.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/detectors/factory.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/detectors/statistical/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/detectors/statistical/iqr.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/detectors/statistical/mad.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/detectors/statistical/manual_bounds.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/detectors/statistical/zscore.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/loaders/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/loaders/metric_loader.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/loaders/query_template.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/orchestration/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/orchestration/task_manager.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/utils/__init__.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/utils/datetime_utils.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit/utils/stats.py +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit.egg-info/SOURCES.txt +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit.egg-info/dependency_links.txt +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit.egg-info/entry_points.txt +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit.egg-info/requires.txt +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/detectkit.egg-info/top_level.txt +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/requirements.txt +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/setup.cfg +0 -0
- {detectkit-0.3.14 → detectkit-0.3.15}/setup.py +0 -0
|
@@ -144,10 +144,13 @@ class BaseAlertChannel(ABC):
|
|
|
144
144
|
if isinstance(ts, np.datetime64):
|
|
145
145
|
ts = ts.astype(datetime)
|
|
146
146
|
|
|
147
|
-
#
|
|
148
|
-
ts_str = ts.strftime("%Y-%m-%d %H:%M:%S")
|
|
147
|
+
# Convert naive UTC timestamp to target timezone if specified
|
|
149
148
|
if alert_data.timezone:
|
|
150
|
-
|
|
149
|
+
from zoneinfo import ZoneInfo
|
|
150
|
+
ts = ts.replace(tzinfo=ZoneInfo("UTC")).astimezone(ZoneInfo(alert_data.timezone))
|
|
151
|
+
ts_str = f"{ts.strftime('%Y-%m-%d %H:%M:%S')} ({alert_data.timezone})"
|
|
152
|
+
else:
|
|
153
|
+
ts_str = ts.strftime("%Y-%m-%d %H:%M:%S")
|
|
151
154
|
|
|
152
155
|
# Format confidence interval
|
|
153
156
|
if alert_data.confidence_lower is not None and alert_data.confidence_upper is not None:
|
|
@@ -683,19 +683,37 @@ class AlertOrchestrator:
|
|
|
683
683
|
if not detections:
|
|
684
684
|
return None
|
|
685
685
|
|
|
686
|
-
# Use the latest (newest) detection point for recovery
|
|
686
|
+
# Use the latest (newest) detection point for recovery timestamp/value.
|
|
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
|
|
707
|
+
|
|
690
708
|
return AlertData(
|
|
691
709
|
metric_name=self.metric_name,
|
|
692
710
|
timestamp=latest.timestamp,
|
|
693
711
|
timezone=self.timezone_display,
|
|
694
712
|
value=latest.value,
|
|
695
|
-
confidence_lower=
|
|
696
|
-
confidence_upper=
|
|
697
|
-
detector_name=
|
|
698
|
-
detector_params=
|
|
713
|
+
confidence_lower=recovery_ci_lower,
|
|
714
|
+
confidence_upper=recovery_ci_upper,
|
|
715
|
+
detector_name=recovery_detector_name,
|
|
716
|
+
detector_params=recovery_detector_params,
|
|
699
717
|
direction="none",
|
|
700
718
|
severity=0.0,
|
|
701
719
|
detection_metadata={},
|
|
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
|
|
File without changes
|
|
File without changes
|