detectkit 0.2.4__py3-none-any.whl
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/__init__.py +17 -0
- detectkit/alerting/__init__.py +13 -0
- detectkit/alerting/channels/__init__.py +21 -0
- detectkit/alerting/channels/base.py +193 -0
- detectkit/alerting/channels/email.py +146 -0
- detectkit/alerting/channels/factory.py +193 -0
- detectkit/alerting/channels/mattermost.py +53 -0
- detectkit/alerting/channels/slack.py +55 -0
- detectkit/alerting/channels/telegram.py +110 -0
- detectkit/alerting/channels/webhook.py +139 -0
- detectkit/alerting/orchestrator.py +369 -0
- detectkit/cli/__init__.py +1 -0
- detectkit/cli/commands/__init__.py +1 -0
- detectkit/cli/commands/init.py +282 -0
- detectkit/cli/commands/run.py +486 -0
- detectkit/cli/commands/test_alert.py +184 -0
- detectkit/cli/main.py +186 -0
- detectkit/config/__init__.py +30 -0
- detectkit/config/metric_config.py +499 -0
- detectkit/config/profile.py +285 -0
- detectkit/config/project_config.py +164 -0
- detectkit/config/validator.py +124 -0
- detectkit/core/__init__.py +6 -0
- detectkit/core/interval.py +132 -0
- detectkit/core/models.py +106 -0
- detectkit/database/__init__.py +27 -0
- detectkit/database/clickhouse_manager.py +393 -0
- detectkit/database/internal_tables.py +724 -0
- detectkit/database/manager.py +324 -0
- detectkit/database/tables.py +138 -0
- detectkit/detectors/__init__.py +6 -0
- detectkit/detectors/base.py +441 -0
- detectkit/detectors/factory.py +138 -0
- detectkit/detectors/statistical/__init__.py +8 -0
- detectkit/detectors/statistical/iqr.py +508 -0
- detectkit/detectors/statistical/mad.py +478 -0
- detectkit/detectors/statistical/manual_bounds.py +206 -0
- detectkit/detectors/statistical/zscore.py +491 -0
- detectkit/loaders/__init__.py +6 -0
- detectkit/loaders/metric_loader.py +470 -0
- detectkit/loaders/query_template.py +164 -0
- detectkit/orchestration/__init__.py +9 -0
- detectkit/orchestration/task_manager.py +746 -0
- detectkit/utils/__init__.py +17 -0
- detectkit/utils/stats.py +196 -0
- detectkit-0.2.4.dist-info/METADATA +237 -0
- detectkit-0.2.4.dist-info/RECORD +51 -0
- detectkit-0.2.4.dist-info/WHEEL +5 -0
- detectkit-0.2.4.dist-info/entry_points.txt +2 -0
- detectkit-0.2.4.dist-info/licenses/LICENSE +21 -0
- detectkit-0.2.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Utility functions for detectk."""
|
|
2
|
+
|
|
3
|
+
from detectkit.utils.stats import (
|
|
4
|
+
weighted_mad,
|
|
5
|
+
weighted_mean,
|
|
6
|
+
weighted_median,
|
|
7
|
+
weighted_percentile,
|
|
8
|
+
weighted_std,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"weighted_percentile",
|
|
13
|
+
"weighted_median",
|
|
14
|
+
"weighted_mad",
|
|
15
|
+
"weighted_mean",
|
|
16
|
+
"weighted_std",
|
|
17
|
+
]
|
detectkit/utils/stats.py
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Statistical utility functions for detectors.
|
|
3
|
+
|
|
4
|
+
Provides weighted statistics functions for use in detectors.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def weighted_percentile(
|
|
13
|
+
data: np.ndarray,
|
|
14
|
+
weights: np.ndarray,
|
|
15
|
+
percentile: float
|
|
16
|
+
) -> float:
|
|
17
|
+
"""
|
|
18
|
+
Compute weighted percentile.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
data: Array of values
|
|
22
|
+
weights: Array of weights (must sum to 1.0)
|
|
23
|
+
percentile: Percentile to compute (0-100)
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
Weighted percentile value
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
>>> data = np.array([1, 2, 3, 4, 5])
|
|
30
|
+
>>> weights = np.array([0.1, 0.2, 0.4, 0.2, 0.1])
|
|
31
|
+
>>> weighted_percentile(data, weights, 50) # Weighted median
|
|
32
|
+
3.0
|
|
33
|
+
|
|
34
|
+
Note:
|
|
35
|
+
Uses linear interpolation between cumulative weights.
|
|
36
|
+
"""
|
|
37
|
+
if len(data) != len(weights):
|
|
38
|
+
raise ValueError(f"data and weights must have same length: {len(data)} vs {len(weights)}")
|
|
39
|
+
|
|
40
|
+
if not np.isclose(weights.sum(), 1.0):
|
|
41
|
+
raise ValueError(f"weights must sum to 1.0, got {weights.sum()}")
|
|
42
|
+
|
|
43
|
+
if not (0 <= percentile <= 100):
|
|
44
|
+
raise ValueError(f"percentile must be in [0, 100], got {percentile}")
|
|
45
|
+
|
|
46
|
+
# Sort data and weights together
|
|
47
|
+
sorted_indices = np.argsort(data)
|
|
48
|
+
sorted_data = data[sorted_indices]
|
|
49
|
+
sorted_weights = weights[sorted_indices]
|
|
50
|
+
|
|
51
|
+
# Cumulative sum of weights
|
|
52
|
+
cumsum = np.cumsum(sorted_weights)
|
|
53
|
+
|
|
54
|
+
# Find index where cumsum >= percentile/100
|
|
55
|
+
target = percentile / 100.0
|
|
56
|
+
idx = np.searchsorted(cumsum, target)
|
|
57
|
+
|
|
58
|
+
# Handle edge cases
|
|
59
|
+
if idx >= len(sorted_data):
|
|
60
|
+
return sorted_data[-1]
|
|
61
|
+
|
|
62
|
+
if idx == 0:
|
|
63
|
+
return sorted_data[0]
|
|
64
|
+
|
|
65
|
+
# Linear interpolation between surrounding values
|
|
66
|
+
# (more accurate than just returning sorted_data[idx])
|
|
67
|
+
lower_weight = cumsum[idx - 1] if idx > 0 else 0.0
|
|
68
|
+
upper_weight = cumsum[idx]
|
|
69
|
+
|
|
70
|
+
if np.isclose(lower_weight, upper_weight):
|
|
71
|
+
# Avoid division by zero
|
|
72
|
+
return sorted_data[idx]
|
|
73
|
+
|
|
74
|
+
# Interpolate
|
|
75
|
+
fraction = (target - lower_weight) / (upper_weight - lower_weight)
|
|
76
|
+
return sorted_data[idx - 1] + fraction * (sorted_data[idx] - sorted_data[idx - 1])
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def weighted_median(data: np.ndarray, weights: np.ndarray) -> float:
|
|
80
|
+
"""
|
|
81
|
+
Compute weighted median (50th percentile).
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
data: Array of values
|
|
85
|
+
weights: Array of weights (must sum to 1.0)
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Weighted median value
|
|
89
|
+
|
|
90
|
+
Example:
|
|
91
|
+
>>> data = np.array([1, 2, 3, 4, 5])
|
|
92
|
+
>>> weights = np.array([0.1, 0.2, 0.4, 0.2, 0.1])
|
|
93
|
+
>>> weighted_median(data, weights)
|
|
94
|
+
3.0
|
|
95
|
+
"""
|
|
96
|
+
return weighted_percentile(data, weights, 50.0)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def weighted_mad(
|
|
100
|
+
data: np.ndarray,
|
|
101
|
+
weights: np.ndarray,
|
|
102
|
+
center: Optional[float] = None
|
|
103
|
+
) -> float:
|
|
104
|
+
"""
|
|
105
|
+
Compute weighted Median Absolute Deviation.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
data: Array of values
|
|
109
|
+
weights: Array of weights (must sum to 1.0)
|
|
110
|
+
center: Center value (if None, uses weighted median)
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
Weighted MAD value
|
|
114
|
+
|
|
115
|
+
Example:
|
|
116
|
+
>>> data = np.array([1, 2, 3, 4, 5])
|
|
117
|
+
>>> weights = np.array([0.1, 0.2, 0.4, 0.2, 0.1])
|
|
118
|
+
>>> weighted_mad(data, weights)
|
|
119
|
+
1.0
|
|
120
|
+
"""
|
|
121
|
+
if center is None:
|
|
122
|
+
center = weighted_median(data, weights)
|
|
123
|
+
|
|
124
|
+
deviations = np.abs(data - center)
|
|
125
|
+
return weighted_median(deviations, weights)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def weighted_mean(data: np.ndarray, weights: np.ndarray) -> float:
|
|
129
|
+
"""
|
|
130
|
+
Compute weighted mean.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
data: Array of values
|
|
134
|
+
weights: Array of weights (must sum to 1.0)
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Weighted mean value
|
|
138
|
+
|
|
139
|
+
Example:
|
|
140
|
+
>>> data = np.array([1, 2, 3, 4, 5])
|
|
141
|
+
>>> weights = np.array([0.1, 0.2, 0.4, 0.2, 0.1])
|
|
142
|
+
>>> weighted_mean(data, weights)
|
|
143
|
+
3.0
|
|
144
|
+
"""
|
|
145
|
+
if len(data) != len(weights):
|
|
146
|
+
raise ValueError(f"data and weights must have same length: {len(data)} vs {len(weights)}")
|
|
147
|
+
|
|
148
|
+
if not np.isclose(weights.sum(), 1.0):
|
|
149
|
+
raise ValueError(f"weights must sum to 1.0, got {weights.sum()}")
|
|
150
|
+
|
|
151
|
+
return np.sum(data * weights)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def weighted_std(
|
|
155
|
+
data: np.ndarray,
|
|
156
|
+
weights: np.ndarray,
|
|
157
|
+
center: Optional[float] = None,
|
|
158
|
+
ddof: int = 0
|
|
159
|
+
) -> float:
|
|
160
|
+
"""
|
|
161
|
+
Compute weighted standard deviation.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
data: Array of values
|
|
165
|
+
weights: Array of weights (must sum to 1.0)
|
|
166
|
+
center: Center value (if None, uses weighted mean)
|
|
167
|
+
ddof: Delta degrees of freedom (0 = population, 1 = sample)
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Weighted standard deviation
|
|
171
|
+
|
|
172
|
+
Example:
|
|
173
|
+
>>> data = np.array([1, 2, 3, 4, 5])
|
|
174
|
+
>>> weights = np.array([0.1, 0.2, 0.4, 0.2, 0.1])
|
|
175
|
+
>>> weighted_std(data, weights)
|
|
176
|
+
1.095445...
|
|
177
|
+
"""
|
|
178
|
+
if len(data) != len(weights):
|
|
179
|
+
raise ValueError(f"data and weights must have same length: {len(data)} vs {len(weights)}")
|
|
180
|
+
|
|
181
|
+
if not np.isclose(weights.sum(), 1.0):
|
|
182
|
+
raise ValueError(f"weights must sum to 1.0, got {weights.sum()}")
|
|
183
|
+
|
|
184
|
+
if center is None:
|
|
185
|
+
center = weighted_mean(data, weights)
|
|
186
|
+
|
|
187
|
+
# Weighted variance
|
|
188
|
+
variance = np.sum(weights * (data - center) ** 2)
|
|
189
|
+
|
|
190
|
+
# Apply Bessel's correction if ddof=1
|
|
191
|
+
if ddof == 1:
|
|
192
|
+
# For weighted data: variance / (1 - sum(weights^2))
|
|
193
|
+
sum_weights_sq = np.sum(weights ** 2)
|
|
194
|
+
variance = variance / (1 - sum_weights_sq)
|
|
195
|
+
|
|
196
|
+
return np.sqrt(variance)
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: detectkit
|
|
3
|
+
Version: 0.2.4
|
|
4
|
+
Summary: Metric monitoring with automatic anomaly detection
|
|
5
|
+
Author: detectkit team
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/alexeiveselov92/detectkit
|
|
8
|
+
Project-URL: Documentation, https://github.com/alexeiveselov92/detectkit
|
|
9
|
+
Project-URL: Repository, https://github.com/alexeiveselov92/detectkit
|
|
10
|
+
Project-URL: Issues, https://github.com/alexeiveselov92/detectkit/issues
|
|
11
|
+
Keywords: monitoring,anomaly-detection,metrics,timeseries,alerting
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Topic :: System :: Monitoring
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: numpy>=1.24.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0
|
|
28
|
+
Requires-Dist: click>=8.0
|
|
29
|
+
Requires-Dist: jinja2>=3.0
|
|
30
|
+
Requires-Dist: orjson>=3.0
|
|
31
|
+
Requires-Dist: requests>=2.25.0
|
|
32
|
+
Provides-Extra: clickhouse
|
|
33
|
+
Requires-Dist: clickhouse-driver>=0.2.0; extra == "clickhouse"
|
|
34
|
+
Provides-Extra: postgres
|
|
35
|
+
Requires-Dist: psycopg2-binary>=2.9.0; extra == "postgres"
|
|
36
|
+
Provides-Extra: mysql
|
|
37
|
+
Requires-Dist: pymysql>=1.0.0; extra == "mysql"
|
|
38
|
+
Provides-Extra: all-db
|
|
39
|
+
Requires-Dist: clickhouse-driver>=0.2.0; extra == "all-db"
|
|
40
|
+
Requires-Dist: psycopg2-binary>=2.9.0; extra == "all-db"
|
|
41
|
+
Requires-Dist: pymysql>=1.0.0; extra == "all-db"
|
|
42
|
+
Provides-Extra: prophet
|
|
43
|
+
Requires-Dist: prophet>=1.1.0; extra == "prophet"
|
|
44
|
+
Provides-Extra: timesfm
|
|
45
|
+
Requires-Dist: timesfm>=0.1.0; extra == "timesfm"
|
|
46
|
+
Provides-Extra: advanced-detectors
|
|
47
|
+
Requires-Dist: prophet>=1.1.0; extra == "advanced-detectors"
|
|
48
|
+
Requires-Dist: timesfm>=0.1.0; extra == "advanced-detectors"
|
|
49
|
+
Provides-Extra: all
|
|
50
|
+
Requires-Dist: clickhouse-driver>=0.2.0; extra == "all"
|
|
51
|
+
Requires-Dist: psycopg2-binary>=2.9.0; extra == "all"
|
|
52
|
+
Requires-Dist: pymysql>=1.0.0; extra == "all"
|
|
53
|
+
Requires-Dist: prophet>=1.1.0; extra == "all"
|
|
54
|
+
Requires-Dist: timesfm>=0.1.0; extra == "all"
|
|
55
|
+
Provides-Extra: dev
|
|
56
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
57
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
58
|
+
Requires-Dist: black>=23.0; extra == "dev"
|
|
59
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
60
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
61
|
+
Dynamic: license-file
|
|
62
|
+
|
|
63
|
+
# detectkit
|
|
64
|
+
|
|
65
|
+
**Metric monitoring with automatic anomaly detection**
|
|
66
|
+
|
|
67
|
+
`detectkit` is a Python library for data analysts and engineers to monitor time-series metrics with automatic anomaly detection and alerting.
|
|
68
|
+
|
|
69
|
+
## Status
|
|
70
|
+
|
|
71
|
+
✅ **Production Ready** - Version 0.1.2
|
|
72
|
+
|
|
73
|
+
Published to PyPI: https://pypi.org/project/detectkit/
|
|
74
|
+
|
|
75
|
+
Complete rewrite with modern architecture and full documentation (2025).
|
|
76
|
+
|
|
77
|
+
## Features
|
|
78
|
+
|
|
79
|
+
- ✅ **Pure numpy arrays** - No pandas dependency in core logic
|
|
80
|
+
- ✅ **Batch processing** - Efficient vectorized operations
|
|
81
|
+
- ✅ **Multiple detectors** - Statistical methods (Z-Score, MAD, IQR, Manual Bounds)
|
|
82
|
+
- ✅ **Alert channels** - Mattermost, Slack, Webhook support
|
|
83
|
+
- ✅ **Database agnostic** - ClickHouse, PostgreSQL, MySQL support
|
|
84
|
+
- ✅ **Idempotent operations** - Resume from interruptions
|
|
85
|
+
- 🚧 **CLI interface** - dbt-like commands (coming soon)
|
|
86
|
+
|
|
87
|
+
## Installation
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
pip install detectkit
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Or from source:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
git clone https://github.com/alexeiveselov92/detectkit
|
|
97
|
+
cd detectkit
|
|
98
|
+
pip install -e .
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Optional dependencies
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# ClickHouse support
|
|
105
|
+
pip install detectkit[clickhouse]
|
|
106
|
+
|
|
107
|
+
# All database drivers
|
|
108
|
+
pip install detectkit[all-db]
|
|
109
|
+
|
|
110
|
+
# Development dependencies
|
|
111
|
+
pip install detectkit[dev]
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Quick Start
|
|
115
|
+
|
|
116
|
+
### CLI Usage (Recommended)
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Create a new project
|
|
120
|
+
dtk init my_monitoring_project
|
|
121
|
+
cd my_monitoring_project
|
|
122
|
+
|
|
123
|
+
# Configure database in profiles.yml
|
|
124
|
+
# Then run your metrics
|
|
125
|
+
dtk run --select example_cpu_usage
|
|
126
|
+
|
|
127
|
+
# Run specific pipeline steps
|
|
128
|
+
dtk run --select cpu_usage --steps load,detect
|
|
129
|
+
|
|
130
|
+
# Run all critical metrics
|
|
131
|
+
dtk run --select tag:critical
|
|
132
|
+
|
|
133
|
+
# Reload data from specific date
|
|
134
|
+
dtk run --select cpu_usage --from 2024-01-01
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Python API Usage
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
import numpy as np
|
|
141
|
+
from detectkit.detectors.statistical import ZScoreDetector
|
|
142
|
+
|
|
143
|
+
# Your time-series data
|
|
144
|
+
timestamps = np.array([...], dtype='datetime64[ms]')
|
|
145
|
+
values = np.array([1.0, 2.0, 1.5, 10.0, 1.8]) # 10.0 is anomaly
|
|
146
|
+
|
|
147
|
+
# Create detector
|
|
148
|
+
detector = ZScoreDetector(threshold=3.0, window_size=100)
|
|
149
|
+
|
|
150
|
+
# Detect anomalies
|
|
151
|
+
data = {
|
|
152
|
+
'timestamp': timestamps,
|
|
153
|
+
'value': values
|
|
154
|
+
}
|
|
155
|
+
results = detector.detect(data)
|
|
156
|
+
|
|
157
|
+
# Check results
|
|
158
|
+
for result in results:
|
|
159
|
+
if result.is_anomaly:
|
|
160
|
+
print(f"Anomaly at {result.timestamp}: {result.value}")
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Architecture
|
|
164
|
+
|
|
165
|
+
- **Detectors** - Statistical and ML-based anomaly detection
|
|
166
|
+
- **Loaders** - Metric data loading from databases with gap filling
|
|
167
|
+
- **Alerting** - Multi-channel notifications with orchestration
|
|
168
|
+
- **Config** - YAML-based configuration (dbt-like)
|
|
169
|
+
|
|
170
|
+
## Testing
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Run tests
|
|
174
|
+
pytest tests/
|
|
175
|
+
|
|
176
|
+
# With coverage
|
|
177
|
+
pytest tests/ --cov=detectkit --cov-report=html
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Current status:** 287 tests passing, 87% coverage
|
|
181
|
+
|
|
182
|
+
## Development Status
|
|
183
|
+
|
|
184
|
+
### ✅ Completed (Phases 1-6)
|
|
185
|
+
- ✅ **Phase 1**: Core models (Interval, TableModel, ColumnDefinition)
|
|
186
|
+
- ✅ **Phase 2**: Database managers & data loading (MetricLoader, gap filling, seasonality)
|
|
187
|
+
- ✅ **Phase 3**: Statistical detectors (Z-Score, MAD, IQR, Manual Bounds)
|
|
188
|
+
- ✅ **Phase 4**: Alerting system (Channels, Orchestrator, consecutive anomalies)
|
|
189
|
+
- ✅ **Phase 5**: Task manager (Pipeline execution, locking, idempotency)
|
|
190
|
+
- ✅ **Phase 6**: CLI commands (dtk init, dtk run with selectors)
|
|
191
|
+
|
|
192
|
+
### 🔄 Integration Status
|
|
193
|
+
- ⚠️ Full end-to-end integration pending (database connection required)
|
|
194
|
+
- ⚠️ Advanced detectors (Prophet, TimesFM) - optional extras
|
|
195
|
+
- ⚠️ Additional alert channels (Telegram, Email) - optional
|
|
196
|
+
|
|
197
|
+
## Documentation
|
|
198
|
+
|
|
199
|
+
📚 **Complete documentation available at: https://github.com/alexeiveselov92/detectkit/tree/main/docs**
|
|
200
|
+
|
|
201
|
+
- [Getting Started](https://github.com/alexeiveselov92/detectkit/blob/main/docs/getting-started/quickstart.md) - 5-minute quickstart
|
|
202
|
+
- [Configuration Guide](https://github.com/alexeiveselov92/detectkit/blob/main/docs/guides/configuration.md) - All configuration options
|
|
203
|
+
- [Detectors Guide](https://github.com/alexeiveselov92/detectkit/blob/main/docs/guides/detectors.md) - Choosing the right detector
|
|
204
|
+
- [Alerting Guide](https://github.com/alexeiveselov92/detectkit/blob/main/docs/guides/alerting.md) - Setting up alerts
|
|
205
|
+
- [CLI Reference](https://github.com/alexeiveselov92/detectkit/blob/main/docs/reference/cli.md) - Command-line documentation
|
|
206
|
+
- [Examples](https://github.com/alexeiveselov92/detectkit/tree/main/docs/examples) - Real-world monitoring scenarios
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
## Requirements
|
|
210
|
+
|
|
211
|
+
- Python 3.10+
|
|
212
|
+
- numpy >= 1.24.0
|
|
213
|
+
- pydantic >= 2.0.0
|
|
214
|
+
- click >= 8.0
|
|
215
|
+
- PyYAML >= 6.0
|
|
216
|
+
- Jinja2 >= 3.0
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
MIT License - See LICENSE file for details
|
|
221
|
+
|
|
222
|
+
## Contributing
|
|
223
|
+
|
|
224
|
+
This project is currently in active development. Contributions are welcome once we reach v1.0.0.
|
|
225
|
+
|
|
226
|
+
## Changelog
|
|
227
|
+
|
|
228
|
+
### 0.1.0 (2025-11-07)
|
|
229
|
+
- Initial release with complete rewrite
|
|
230
|
+
- ✅ Core foundation: models, database, config
|
|
231
|
+
- ✅ Metric loading with gap filling and seasonality extraction
|
|
232
|
+
- ✅ Statistical detectors (Z-Score, MAD, IQR, Manual Bounds)
|
|
233
|
+
- ✅ Alert channels (Webhook, Mattermost, Slack)
|
|
234
|
+
- ✅ Alert orchestration with consecutive anomaly logic
|
|
235
|
+
- ✅ Task manager for pipeline execution
|
|
236
|
+
- ✅ CLI commands (dtk init, dtk run)
|
|
237
|
+
- 📊 287 unit tests, 87% coverage
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
detectkit/__init__.py,sha256=iGNYCub-iLiYQMY0883su3mKl-7vi-XDqTrrK2Qn8IE,387
|
|
2
|
+
detectkit/alerting/__init__.py,sha256=Qkf9zbNahUDcEIxbwMxFN0VakQmTBI0rcRjS-ggs9NU,242
|
|
3
|
+
detectkit/alerting/orchestrator.py,sha256=m9KeA9Mf4zNsG2ZfsmnveSy6sX97a-D6Rnougu_TuJY,12538
|
|
4
|
+
detectkit/alerting/channels/__init__.py,sha256=HsHcp5hcDi2mBv56F9DpX-gOJUDJwxK87cvt3vrzKbU,700
|
|
5
|
+
detectkit/alerting/channels/base.py,sha256=voh6sCHbJMXt1FrhEsXp3mbJPqn-m8JlngGxMAHnlCE,5957
|
|
6
|
+
detectkit/alerting/channels/email.py,sha256=i69n7Ub2t0dLOOy9D9f3fzFtPzv55DsnhZ7Y3CCxF4I,4839
|
|
7
|
+
detectkit/alerting/channels/factory.py,sha256=WJ7MgFseHiHwUirMBmsYoyxuZCtXTyLU6qou3d8PFXE,5913
|
|
8
|
+
detectkit/alerting/channels/mattermost.py,sha256=xBxnLOJ5TM_0iAAKBLp33laYxxQHv71o_q-vAG3w2TM,1715
|
|
9
|
+
detectkit/alerting/channels/slack.py,sha256=ahmE9tf7fI58bQ0zBzRvCdRjtBqTX-RObDO-PgEd7Ds,1774
|
|
10
|
+
detectkit/alerting/channels/telegram.py,sha256=Bd9wwm_uQwGvL1hIU_lFD0xLKdYGR2h1tS-61hkyVY0,3397
|
|
11
|
+
detectkit/alerting/channels/webhook.py,sha256=etEYaw1HzwksxKA8A1n4CPqxBygDgNyubLYNUC9zc-o,4291
|
|
12
|
+
detectkit/cli/__init__.py,sha256=dXoRC7mLWP0k_HPUrvm2myJcKv1faV0ZdpksVSLvtl8,42
|
|
13
|
+
detectkit/cli/main.py,sha256=AApQ7VfWqbo8k3tRU6kIPhLoLdWxWpO3eJ12Q5dwAtM,4555
|
|
14
|
+
detectkit/cli/commands/__init__.py,sha256=GYdoNv80KS2p7bCThuoRbhiLmIZW6ddPqPEFEx567nQ,35
|
|
15
|
+
detectkit/cli/commands/init.py,sha256=TlCyt06mAGw4UdnES9ei-hzy6vRjQrRHVmoysg0zlcI,6231
|
|
16
|
+
detectkit/cli/commands/run.py,sha256=SFZR-O7xagYotuOW3nq6MsII0XvshWnEBadOWatf32U,13381
|
|
17
|
+
detectkit/cli/commands/test_alert.py,sha256=dppixPsQUlTSdWBsiltFPHKcC0e-HiH0A5r1RW_lkrs,5986
|
|
18
|
+
detectkit/config/__init__.py,sha256=-m7IysRlbhO0w7neutUbge_Jvu0fzVKTXwVjGIx1c2g,669
|
|
19
|
+
detectkit/config/metric_config.py,sha256=Akeapg0sR-7J5e9VShR2fMM-e8MhLBOuwfL7glWFCg8,16862
|
|
20
|
+
detectkit/config/profile.py,sha256=rIpNYHmeuRIb20XeqKWvZp9a-JYqw2pWnnUIEehIPXE,9266
|
|
21
|
+
detectkit/config/project_config.py,sha256=cEVmLpTAEqAAbtl_3aKVdUaLyXyUF2PyG71lrW_73Qg,4889
|
|
22
|
+
detectkit/config/validator.py,sha256=a6TsF9BycQiCE_Tibh1EPN3BYfBxPkJJcNFz42ZrAaE,4213
|
|
23
|
+
detectkit/core/__init__.py,sha256=gVab2NTmwTlSc1lUBPsD24vL1ViZSi4Q0el-bpzj-o0,205
|
|
24
|
+
detectkit/core/interval.py,sha256=I5ASV6AX3W6bhNMNSeFKUXPbhS_lhYEawsTVaH2LJnw,3432
|
|
25
|
+
detectkit/core/models.py,sha256=ozdCMVswxjtmo0X3rq8dRwR76vXpjqv5tTuBBeKj_ic,3052
|
|
26
|
+
detectkit/database/__init__.py,sha256=oJ1smzJjdBHBZaeFgIy-1LHZeFDKq-MBgWYMfhH2PuA,748
|
|
27
|
+
detectkit/database/clickhouse_manager.py,sha256=_hvL7jKJdUtEBOkt4t4T_koAT-DJiC7b5mlHVO_ZyHU,12447
|
|
28
|
+
detectkit/database/internal_tables.py,sha256=LSfFtBXDVgc5fgtEqBcySWFSYrtO5-gmtOq3DW2U5PU,24886
|
|
29
|
+
detectkit/database/manager.py,sha256=9Gn6fmvmtQBIzD_a_djhEHF4FhBgxf-sjtnKceWCqS0,9661
|
|
30
|
+
detectkit/database/tables.py,sha256=HmmDVT8T8JkqZxqkwUZ2gHDfWX2WUjEsk1xRt4idP7E,5690
|
|
31
|
+
detectkit/detectors/__init__.py,sha256=y9Fq_7fUT59p1Pf5PRmEgxrXJdPGTxpZyhLoGac30NQ,229
|
|
32
|
+
detectkit/detectors/base.py,sha256=nZTSx9y5v-6ubvHGxiDsEAUTwN7YLTWk6dZQJhXj3A0,14851
|
|
33
|
+
detectkit/detectors/factory.py,sha256=jQthe1aQ3-Uj5ok3lDYWxZpfkyjUKabwp6Cy3YvZ7nQ,4277
|
|
34
|
+
detectkit/detectors/statistical/__init__.py,sha256=jLV3ecauLv06-mqY_uxt9PbY9FmmmzVzsetNsJOZhsw,387
|
|
35
|
+
detectkit/detectors/statistical/iqr.py,sha256=CV_Yy9Ex0LngiCElcHHvZOagWCDRi5wo5i3zTrCEk1U,19992
|
|
36
|
+
detectkit/detectors/statistical/mad.py,sha256=X4TCJuYNRHRTT7OoUZQnmGItcZNOf0gyocBjS3Gc4D4,19080
|
|
37
|
+
detectkit/detectors/statistical/manual_bounds.py,sha256=V873hGS8LPCgKJ_JIgMPUp-ZuPku2egn_BDHl27GPqQ,7441
|
|
38
|
+
detectkit/detectors/statistical/zscore.py,sha256=SdflWQHYeJU4EkZzAdtR0dEH8j9l_A4kxBmVryZATGs,19453
|
|
39
|
+
detectkit/loaders/__init__.py,sha256=huBv-9_tzoh5gAa5b8CONyGCRxFb3_fk-MMl6Mmndww,201
|
|
40
|
+
detectkit/loaders/metric_loader.py,sha256=TLURSgJfiH4fx2jUiy0Sr4P_hTALaejwl4Dr32W_PDE,16530
|
|
41
|
+
detectkit/loaders/query_template.py,sha256=uZ8IJeUv5dpRBlj5Y2ljzdRBFmVme4YPJ_3du1C9ShQ,5747
|
|
42
|
+
detectkit/orchestration/__init__.py,sha256=aPpwUJOgpGuaWAlrUiXXiQ48BU9MryiVDnmqlSdJSAM,200
|
|
43
|
+
detectkit/orchestration/task_manager.py,sha256=ofpEk4mYcbD_jXerYAZQiNWa0n8soGOuIlMks1Y8o24,29023
|
|
44
|
+
detectkit/utils/__init__.py,sha256=CxxL4XFpQswX7DUa9myyrqoPHTpoP5GdF85boJgbc48,303
|
|
45
|
+
detectkit/utils/stats.py,sha256=bvcUBG5kTHvZ9W1iV87Jd-oQtjSfgbL4GHkKx6fWXgc,5317
|
|
46
|
+
detectkit-0.2.4.dist-info/licenses/LICENSE,sha256=xRUS058GXs8iQwrhgwwRKqRcjDdnPanPeddXvPjpXC8,1071
|
|
47
|
+
detectkit-0.2.4.dist-info/METADATA,sha256=yOwcO5e-iQZ2AaNaTdCNC-696Jz2m2PxEjZ2lxByfDY,7634
|
|
48
|
+
detectkit-0.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
49
|
+
detectkit-0.2.4.dist-info/entry_points.txt,sha256=sRmLdbqjeOgExdBtiLlMNIUNufJqt38sxkfVm45tetE,47
|
|
50
|
+
detectkit-0.2.4.dist-info/top_level.txt,sha256=kPVqQdU7XatxCUboMyDT_e7e9rlhgCicT57FwmC__zI,10
|
|
51
|
+
detectkit-0.2.4.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 detectkit team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
detectkit
|