detectkit 0.23.1__tar.gz → 0.23.2__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 (126) hide show
  1. {detectkit-0.23.1/detectkit.egg-info → detectkit-0.23.2}/PKG-INFO +1 -1
  2. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/__init__.py +1 -1
  3. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/html_labeler.py +27 -3
  4. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/label_server.py +4 -1
  5. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/commands/autotune.py +1 -1
  6. {detectkit-0.23.1 → detectkit-0.23.2/detectkit.egg-info}/PKG-INFO +1 -1
  7. {detectkit-0.23.1 → detectkit-0.23.2}/LICENSE +0 -0
  8. {detectkit-0.23.1 → detectkit-0.23.2}/MANIFEST.in +0 -0
  9. {detectkit-0.23.1 → detectkit-0.23.2}/README.md +0 -0
  10. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/__init__.py +0 -0
  11. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/channels/__init__.py +0 -0
  12. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/channels/base.py +0 -0
  13. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/channels/branding.py +0 -0
  14. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/channels/email.py +0 -0
  15. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/channels/factory.py +0 -0
  16. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/channels/mattermost.py +0 -0
  17. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/channels/slack.py +0 -0
  18. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/channels/telegram.py +0 -0
  19. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/channels/webhook.py +0 -0
  20. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/orchestrator/__init__.py +0 -0
  21. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/orchestrator/_base.py +0 -0
  22. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/orchestrator/_cooldown.py +0 -0
  23. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/orchestrator/_decision.py +0 -0
  24. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/orchestrator/_dispatch.py +0 -0
  25. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/orchestrator/_recovery.py +0 -0
  26. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/orchestrator/_types.py +0 -0
  27. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/alerting/orchestrator/orchestrator.py +0 -0
  28. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/__init__.py +0 -0
  29. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/_base.py +0 -0
  30. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/_types.py +0 -0
  31. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/autotuner.py +0 -0
  32. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/config_emitter.py +0 -0
  33. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/crossval.py +0 -0
  34. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/detector_select.py +0 -0
  35. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/distribution.py +0 -0
  36. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/grid_search.py +0 -0
  37. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/labels.py +0 -0
  38. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/result.py +0 -0
  39. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/scoring.py +0 -0
  40. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/seasonality_search.py +0 -0
  41. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/settings.py +0 -0
  42. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/autotune/window_select.py +0 -0
  43. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/__init__.py +0 -0
  44. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/_output.py +0 -0
  45. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/CLAUDE.section.md +0 -0
  46. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/rules/alerting.md +0 -0
  47. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/rules/autotune.md +0 -0
  48. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/rules/cli.md +0 -0
  49. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/rules/detectors.md +0 -0
  50. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/rules/metrics.md +0 -0
  51. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/rules/overview.md +0 -0
  52. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/rules/project.md +0 -0
  53. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md +0 -0
  54. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/skills/dtk-feedback/SKILL.md +0 -0
  55. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md +0 -0
  56. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/assets/claude/skills/dtk-setup-project/SKILL.md +0 -0
  57. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/commands/__init__.py +0 -0
  58. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/commands/clean.py +0 -0
  59. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/commands/init.py +0 -0
  60. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/commands/init_claude.py +0 -0
  61. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/commands/run.py +0 -0
  62. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/commands/test_alert.py +0 -0
  63. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/commands/unlock.py +0 -0
  64. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/cli/main.py +0 -0
  65. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/config/__init__.py +0 -0
  66. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/config/metric_config.py +0 -0
  67. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/config/profile.py +0 -0
  68. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/config/project_config.py +0 -0
  69. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/config/validator.py +0 -0
  70. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/core/__init__.py +0 -0
  71. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/core/interval.py +0 -0
  72. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/core/models.py +0 -0
  73. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/__init__.py +0 -0
  74. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/_sql_manager.py +0 -0
  75. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/clickhouse_manager.py +0 -0
  76. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/__init__.py +0 -0
  77. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/_alert_states.py +0 -0
  78. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/_autotune_runs.py +0 -0
  79. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/_base.py +0 -0
  80. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/_datapoints.py +0 -0
  81. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/_detections.py +0 -0
  82. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/_maintenance.py +0 -0
  83. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/_metrics.py +0 -0
  84. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/_schema.py +0 -0
  85. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/_tasks.py +0 -0
  86. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/internal_tables/manager.py +0 -0
  87. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/manager.py +0 -0
  88. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/mysql_manager.py +0 -0
  89. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/postgres_manager.py +0 -0
  90. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/database/tables.py +0 -0
  91. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/__init__.py +0 -0
  92. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/base.py +0 -0
  93. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/factory.py +0 -0
  94. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/seasonality.py +0 -0
  95. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/statistical/__init__.py +0 -0
  96. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/statistical/_windowed.py +0 -0
  97. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/statistical/iqr.py +0 -0
  98. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/statistical/mad.py +0 -0
  99. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/statistical/manual_bounds.py +0 -0
  100. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/detectors/statistical/zscore.py +0 -0
  101. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/loaders/__init__.py +0 -0
  102. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/loaders/metric_loader.py +0 -0
  103. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/loaders/query_template.py +0 -0
  104. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/orchestration/__init__.py +0 -0
  105. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/orchestration/error_dispatch.py +0 -0
  106. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/orchestration/task_manager/__init__.py +0 -0
  107. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/orchestration/task_manager/_alert_step.py +0 -0
  108. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/orchestration/task_manager/_base.py +0 -0
  109. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/orchestration/task_manager/_detect_step.py +0 -0
  110. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/orchestration/task_manager/_load_step.py +0 -0
  111. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/orchestration/task_manager/_types.py +0 -0
  112. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/orchestration/task_manager/manager.py +0 -0
  113. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/utils/__init__.py +0 -0
  114. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/utils/datetime_utils.py +0 -0
  115. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/utils/env_interpolation.py +0 -0
  116. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/utils/json_utils.py +0 -0
  117. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit/utils/stats.py +0 -0
  118. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit.egg-info/SOURCES.txt +0 -0
  119. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit.egg-info/dependency_links.txt +0 -0
  120. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit.egg-info/entry_points.txt +0 -0
  121. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit.egg-info/requires.txt +0 -0
  122. {detectkit-0.23.1 → detectkit-0.23.2}/detectkit.egg-info/top_level.txt +0 -0
  123. {detectkit-0.23.1 → detectkit-0.23.2}/pyproject.toml +0 -0
  124. {detectkit-0.23.1 → detectkit-0.23.2}/requirements.txt +0 -0
  125. {detectkit-0.23.1 → detectkit-0.23.2}/setup.cfg +0 -0
  126. {detectkit-0.23.1 → detectkit-0.23.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: detectkit
3
- Version: 0.23.1
3
+ Version: 0.23.2
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.23.1"
7
+ __version__ = "0.23.2"
8
8
 
9
9
  from detectkit.core.interval import Interval
10
10
  from detectkit.core.models import ColumnDefinition, TableModel
@@ -58,6 +58,11 @@ _TEMPLATE = """<!doctype html>
58
58
  .brand span { color: var(--faint); font-size: 12px; }
59
59
  h1 { font-size: 18px; line-height: 1.3; margin: 0 0 6px; color: var(--paper); font-weight: 600; }
60
60
  h1 code { color: var(--clay); font-family: var(--mono); font-size: .82em; }
61
+ .ichip { display:inline-flex; align-items:center; gap:6px; vertical-align: middle; margin-left: 8px;
62
+ font-family: var(--mono); font-size: 12px; font-weight: 500; color: var(--paper);
63
+ background: rgba(209,91,54,0.16); border: 1px solid var(--clay); border-radius: 999px; padding: 3px 10px; }
64
+ .ichip .d { width:6px; height:6px; border-radius:50%; background: var(--clay); }
65
+ .ichip b { color: var(--clay); font-weight: 700; }
61
66
  .hint { color: var(--faint); font-size: 13px; margin: 0 0 18px; line-height: 1.55; }
62
67
  .hint code, code.k { color: var(--term-text); font-family: var(--mono); font-size: 12px;
63
68
  background: var(--term-surface); border: 1px solid var(--term-border); border-radius: 5px; padding: 1px 6px; }
@@ -106,7 +111,8 @@ _TEMPLATE = """<!doctype html>
106
111
  <svg viewBox="0 0 100 100" aria-hidden="true"><rect x="3" y="3" width="94" height="94" rx="26" fill="#D15B36"/><polyline points="14,62 36,62 50,22 64,62 86,62" fill="none" stroke="#FBF9F3" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/><circle cx="50" cy="22" r="6.5" fill="#FBF9F3"/></svg>
107
112
  <b>detectkit</b><span>· incident labeler</span>
108
113
  </div>
109
- <h1>Label incidents — <code>__METRIC__</code></h1>
114
+ <h1>Label incidents — <code>__METRIC__</code><span id="intervalchip" class="ichip"
115
+ title="The metric's sampling interval — the spacing between points, taken straight from the metric."></span></h1>
110
116
  <p class="hint">Click-drag across the chart to mark each real incident, add a short description, then
111
117
  <b>Export</b>. Save the file into <code class="k">incidents/__METRIC__/</code> and run
112
118
  <code class="k">dtk autotune --select __METRIC__ --incidents incidents/__METRIC__/</code></p>
@@ -138,6 +144,9 @@ const DATA = __PAYLOAD__;
138
144
  // and Export POSTs straight into incidents/<metric>/. As a static file it is null,
139
145
  // and Export falls back to a browser download.
140
146
  const SAVE_URL = __SAVE_URL__;
147
+ // The metric's sampling interval (seconds). Passed straight from the metric when
148
+ // known; otherwise inferred from the median spacing of points.
149
+ const INTERVAL_S = __INTERVAL__;
141
150
  const pts = DATA.points.map(p => ({ts: Date.parse(p.t.replace(' ','T')+'Z'), v: p.v}));
142
151
  const N = pts.length;
143
152
  const vraw = pts.filter(p => p.v !== null).map(p => p.v);
@@ -455,19 +464,33 @@ function drawAll() { draw(); drawOverview();
455
464
  function fit() { dpr = window.devicePixelRatio || 1;
456
465
  c.width=c.clientWidth*dpr; c.height=c.clientHeight*dpr;
457
466
  ov.width=ov.clientWidth*dpr; ov.height=ov.clientHeight*dpr; drawAll(); }
467
+ function fmtInterval(s) { if (s<=0) return '?';
468
+ if (s%86400===0) return (s/86400)+'d'; if (s%3600===0) return (s/3600)+'h';
469
+ if (s%60===0) return (s/60)+'min'; return s+'s'; }
470
+ function medianIntervalSec() { if (N<2) return 0;
471
+ const d=[]; for (let i=1;i<N;i++) d.push(pts[i].ts-pts[i-1].ts);
472
+ d.sort((a,b)=>a-b); return Math.round(d[Math.floor(d.length/2)]/1000); }
473
+ const intervalSec = (typeof INTERVAL_S==='number' && INTERVAL_S>0) ? INTERVAL_S : medianIntervalSec();
474
+ document.getElementById('intervalchip').innerHTML =
475
+ '<span class="d"></span>interval <b>'+fmtInterval(intervalSec)+'</b>';
458
476
  window.addEventListener('resize', fit); fit(); render();
459
477
  </script>
460
478
  """
461
479
 
462
480
 
463
481
  def render_labeler_html(
464
- metric_name: str, data: dict[str, np.ndarray], *, save_url: str | None = None
482
+ metric_name: str,
483
+ data: dict[str, np.ndarray],
484
+ *,
485
+ save_url: str | None = None,
486
+ interval_seconds: int | None = None,
465
487
  ) -> str:
466
488
  """Return a self-contained HTML labeler page for *metric_name*'s series.
467
489
 
468
490
  With ``save_url`` (set by ``dtk autotune --label``'s local server) the page's
469
491
  Export button POSTs the labels straight to that endpoint; without it (a static
470
- file) Export falls back to a browser download.
492
+ file) Export falls back to a browser download. ``interval_seconds`` is the
493
+ metric's sampling interval shown as a chip (inferred from the data if omitted).
471
494
  """
472
495
  import json
473
496
 
@@ -481,5 +504,6 @@ def render_labeler_html(
481
504
  return (
482
505
  _TEMPLATE.replace("__PAYLOAD__", payload)
483
506
  .replace("__SAVE_URL__", json.dumps(save_url))
507
+ .replace("__INTERVAL__", json.dumps(interval_seconds))
484
508
  .replace("__METRIC__", metric_name)
485
509
  )
@@ -126,7 +126,10 @@ def build_label_server(
126
126
  server.incidents_dir = incidents_dir
127
127
  server.interval_seconds = interval_seconds
128
128
  server.html = render_labeler_html(
129
- metric_name, data, save_url=f"http://127.0.0.1:{port}/save?token={token}"
129
+ metric_name,
130
+ data,
131
+ save_url=f"http://127.0.0.1:{port}/save?token={token}",
132
+ interval_seconds=interval_seconds,
130
133
  )
131
134
  return server, f"http://127.0.0.1:{port}/?token={token}"
132
135
 
@@ -348,7 +348,7 @@ def _tune_one(
348
348
  if label:
349
349
  click.echo(click.style(f"Processing metric: {name}", fg="cyan", bold=True))
350
350
  if no_serve:
351
- html = render_labeler_html(name, data)
351
+ html = render_labeler_html(name, data, interval_seconds=interval_seconds)
352
352
  out = project_root / "metrics" / f"{metric_path.stem}__labeler.html"
353
353
  out.write_text(html, encoding="utf-8")
354
354
  click.echo(f" Wrote labeler: {out.relative_to(project_root)}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: detectkit
3
- Version: 0.23.1
3
+ Version: 0.23.2
4
4
  Summary: Metric monitoring with automatic anomaly detection
5
5
  Author: detectkit team
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes