detectkit 0.5.1__tar.gz → 0.5.3__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 (85) hide show
  1. {detectkit-0.5.1/detectkit.egg-info → detectkit-0.5.3}/PKG-INFO +1 -1
  2. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/__init__.py +1 -1
  3. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/channels/base.py +29 -3
  4. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/cli/commands/test_alert.py +9 -3
  5. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/orchestration/error_dispatch.py +1 -0
  6. {detectkit-0.5.1 → detectkit-0.5.3/detectkit.egg-info}/PKG-INFO +1 -1
  7. {detectkit-0.5.1 → detectkit-0.5.3}/pyproject.toml +1 -1
  8. {detectkit-0.5.1 → detectkit-0.5.3}/LICENSE +0 -0
  9. {detectkit-0.5.1 → detectkit-0.5.3}/MANIFEST.in +0 -0
  10. {detectkit-0.5.1 → detectkit-0.5.3}/README.md +0 -0
  11. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/__init__.py +0 -0
  12. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/channels/__init__.py +0 -0
  13. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/channels/email.py +0 -0
  14. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/channels/factory.py +0 -0
  15. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/channels/mattermost.py +0 -0
  16. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/channels/slack.py +0 -0
  17. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/channels/telegram.py +0 -0
  18. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/channels/webhook.py +0 -0
  19. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/orchestrator/__init__.py +0 -0
  20. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/orchestrator/_base.py +0 -0
  21. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/orchestrator/_cooldown.py +0 -0
  22. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/orchestrator/_decision.py +0 -0
  23. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/orchestrator/_dispatch.py +0 -0
  24. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/orchestrator/_recovery.py +0 -0
  25. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/orchestrator/_types.py +0 -0
  26. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/alerting/orchestrator/orchestrator.py +0 -0
  27. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/cli/__init__.py +0 -0
  28. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/cli/commands/__init__.py +0 -0
  29. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/cli/commands/init.py +0 -0
  30. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/cli/commands/run.py +0 -0
  31. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/cli/main.py +0 -0
  32. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/config/__init__.py +0 -0
  33. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/config/metric_config.py +0 -0
  34. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/config/profile.py +0 -0
  35. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/config/project_config.py +0 -0
  36. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/config/validator.py +0 -0
  37. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/core/__init__.py +0 -0
  38. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/core/interval.py +0 -0
  39. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/core/models.py +0 -0
  40. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/__init__.py +0 -0
  41. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/clickhouse_manager.py +0 -0
  42. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/internal_tables/__init__.py +0 -0
  43. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/internal_tables/_alert_states.py +0 -0
  44. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/internal_tables/_base.py +0 -0
  45. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/internal_tables/_datapoints.py +0 -0
  46. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/internal_tables/_detections.py +0 -0
  47. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/internal_tables/_metrics.py +0 -0
  48. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/internal_tables/_schema.py +0 -0
  49. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/internal_tables/_tasks.py +0 -0
  50. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/internal_tables/manager.py +0 -0
  51. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/manager.py +0 -0
  52. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/database/tables.py +0 -0
  53. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/detectors/__init__.py +0 -0
  54. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/detectors/base.py +0 -0
  55. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/detectors/factory.py +0 -0
  56. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/detectors/seasonality.py +0 -0
  57. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/detectors/statistical/__init__.py +0 -0
  58. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/detectors/statistical/iqr.py +0 -0
  59. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/detectors/statistical/mad.py +0 -0
  60. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/detectors/statistical/manual_bounds.py +0 -0
  61. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/detectors/statistical/zscore.py +0 -0
  62. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/loaders/__init__.py +0 -0
  63. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/loaders/metric_loader.py +0 -0
  64. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/loaders/query_template.py +0 -0
  65. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/orchestration/__init__.py +0 -0
  66. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/orchestration/task_manager/__init__.py +0 -0
  67. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/orchestration/task_manager/_alert_step.py +0 -0
  68. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/orchestration/task_manager/_base.py +0 -0
  69. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/orchestration/task_manager/_detect_step.py +0 -0
  70. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/orchestration/task_manager/_load_step.py +0 -0
  71. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/orchestration/task_manager/_types.py +0 -0
  72. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/orchestration/task_manager/manager.py +0 -0
  73. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/utils/__init__.py +0 -0
  74. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/utils/datetime_utils.py +0 -0
  75. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/utils/env_interpolation.py +0 -0
  76. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/utils/json_utils.py +0 -0
  77. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit/utils/stats.py +0 -0
  78. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit.egg-info/SOURCES.txt +0 -0
  79. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit.egg-info/dependency_links.txt +0 -0
  80. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit.egg-info/entry_points.txt +0 -0
  81. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit.egg-info/requires.txt +0 -0
  82. {detectkit-0.5.1 → detectkit-0.5.3}/detectkit.egg-info/top_level.txt +0 -0
  83. {detectkit-0.5.1 → detectkit-0.5.3}/requirements.txt +0 -0
  84. {detectkit-0.5.1 → detectkit-0.5.3}/setup.cfg +0 -0
  85. {detectkit-0.5.1 → detectkit-0.5.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: detectkit
3
- Version: 0.5.1
3
+ Version: 0.5.3
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.5.1"
7
+ __version__ = "0.5.3"
8
8
 
9
9
  from detectkit.core.interval import Interval
10
10
  from detectkit.core.models import ColumnDefinition, TableModel
@@ -32,6 +32,10 @@ class AlertData:
32
32
  consecutive_count: Number of consecutive anomalies
33
33
  is_recovery: True for recovery notifications
34
34
  is_no_data: True for missing-data alerts (no_data_alert)
35
+ project_name: Optional ``detectkit_project.yml`` name. Surfaces
36
+ as ``{project_name}`` in templates and as a ``[name] `` prefix
37
+ in the default error title. Lets multiple projects share the
38
+ same alert channel without ambiguity.
35
39
  """
36
40
 
37
41
  metric_name: str
@@ -53,6 +57,7 @@ class AlertData:
53
57
  error_message: str | None = None
54
58
  description: str | None = None
55
59
  mentions: list[str] = field(default_factory=list)
60
+ project_name: str | None = None
56
61
 
57
62
 
58
63
  class BaseAlertChannel(ABC):
@@ -188,6 +193,12 @@ class BaseAlertChannel(ABC):
188
193
  mentions_str = self.format_mentions(alert_data.mentions)
189
194
  mentions_line = f"\n{mentions_str}" if mentions_str else ""
190
195
 
196
+ # Project name + synth prefix for templates. Prefix is empty when
197
+ # project_name is None so default templates render cleanly for
198
+ # callers that don't set it.
199
+ project_name = alert_data.project_name or ""
200
+ project_name_prefix = f"[{alert_data.project_name}] " if alert_data.project_name else ""
201
+
191
202
  # Format message
192
203
  if alert_data.is_error:
193
204
  status = "ERROR"
@@ -201,6 +212,8 @@ class BaseAlertChannel(ABC):
201
212
  try:
202
213
  message = template.format(
203
214
  metric_name=alert_data.metric_name,
215
+ project_name=project_name,
216
+ project_name_prefix=project_name_prefix,
204
217
  timestamp=ts_str,
205
218
  timezone=alert_data.timezone,
206
219
  value=value_for_template,
@@ -282,7 +295,14 @@ class BaseAlertChannel(ABC):
282
295
  else:
283
296
  title_template = self.get_default_title_template()
284
297
 
285
- return title_template.format(metric_name=alert_data.metric_name)
298
+ project_name = alert_data.project_name or ""
299
+ project_name_prefix = f"[{alert_data.project_name}] " if alert_data.project_name else ""
300
+
301
+ return title_template.format(
302
+ metric_name=alert_data.metric_name,
303
+ project_name=project_name,
304
+ project_name_prefix=project_name_prefix,
305
+ )
286
306
 
287
307
  def get_default_template(self) -> str:
288
308
  """
@@ -369,8 +389,14 @@ class BaseAlertChannel(ABC):
369
389
  )
370
390
 
371
391
  def get_default_error_title_template(self) -> str:
372
- """Default title template for project-level error alerts."""
373
- return "Pipeline error: {metric_name}"
392
+ """Default title template for project-level error alerts.
393
+
394
+ Includes the project name as a ``[name] `` prefix when set so
395
+ multiple detectkit projects routed to the same alert channel
396
+ stay distinguishable. The prefix collapses to an empty string
397
+ when ``AlertData.project_name`` is None.
398
+ """
399
+ return "{project_name_prefix}Pipeline error: {metric_name}"
374
400
 
375
401
  def __repr__(self) -> str:
376
402
  """String representation of channel."""
@@ -20,6 +20,7 @@ from detectkit.utils.datetime_utils import now_utc
20
20
 
21
21
  def create_mock_alert_data(
22
22
  metric_config: MetricConfig,
23
+ alerting_config,
23
24
  timezone_display: str = "UTC",
24
25
  ) -> AlertData:
25
26
  """
@@ -27,6 +28,10 @@ def create_mock_alert_data(
27
28
 
28
29
  Args:
29
30
  metric_config: Metric configuration
31
+ alerting_config: Single ``AlertingConfig`` from
32
+ ``metric_config.alerting`` to source mentions/timezone from.
33
+ ``metric_config.alerting`` is a list — the test command
34
+ iterates it and passes one entry at a time.
30
35
  timezone_display: Timezone for display
31
36
 
32
37
  Returns:
@@ -35,8 +40,9 @@ def create_mock_alert_data(
35
40
  # Use current time
36
41
  now = now_utc()
37
42
 
38
- # Get mentions from alerting config
39
- mentions = metric_config.alerting.mentions if metric_config.alerting else []
43
+ # Mentions are per-AlertingConfig (different alert routes can mention
44
+ # different teams). Pull them from the specific config we're testing.
45
+ mentions = list(alerting_config.mentions) if alerting_config else []
40
46
 
41
47
  # Create realistic mock data
42
48
  return AlertData(
@@ -147,7 +153,7 @@ def run_test_alert(metric_name: str, profile: str | None = None):
147
153
  print(f" Timezone: {timezone_display}")
148
154
  print(f" Channels: {', '.join(alerting_config.channels)}\n")
149
155
 
150
- alert_data = create_mock_alert_data(metric_config, timezone_display)
156
+ alert_data = create_mock_alert_data(metric_config, alerting_config, timezone_display)
151
157
 
152
158
  success_count = 0
153
159
  for channel_name in alerting_config.channels:
@@ -92,6 +92,7 @@ def dispatch_project_error_alert(
92
92
  error_message=str(exc),
93
93
  description=None,
94
94
  mentions=cfg.mentions,
95
+ project_name=getattr(project_config, "name", None),
95
96
  )
96
97
 
97
98
  click.echo(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: detectkit
3
- Version: 0.5.1
3
+ Version: 0.5.3
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.5.1"
7
+ version = "0.5.3"
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