detectkit 0.31.0__tar.gz → 0.31.1__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.31.0/detectkit.egg-info → detectkit-0.31.1}/PKG-INFO +1 -1
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/__init__.py +1 -1
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/tuning/assets/tune.js +3 -3
- {detectkit-0.31.0 → detectkit-0.31.1/detectkit.egg-info}/PKG-INFO +1 -1
- {detectkit-0.31.0 → detectkit-0.31.1}/LICENSE +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/MANIFEST.in +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/README.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/channels/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/channels/base.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/channels/branding.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/channels/email.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/channels/factory.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/channels/mattermost.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/channels/slack.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/channels/telegram.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/channels/webhook.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/orchestrator/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/orchestrator/_base.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/orchestrator/_cooldown.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/orchestrator/_decision.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/orchestrator/_dispatch.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/orchestrator/_recovery.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/orchestrator/_replay.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/orchestrator/_types.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/alerting/orchestrator/orchestrator.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/_base.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/_types.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/autotuner.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/config_emitter.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/crossval.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/detector_select.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/distribution.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/grid_search.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/html_labeler.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/label_server.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/labels.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/result.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/scoring.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/seasonality_search.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/settings.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/autotune/window_select.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/_output.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/CLAUDE.section.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/rules/alerting.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/rules/autotune.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/rules/cli.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/rules/detectors.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/rules/metrics.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/rules/overview.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/rules/project.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/skills/dtk-feedback/SKILL.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/skills/dtk-setup-project/SKILL.md +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/commands/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/commands/autotune.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/commands/clean.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/commands/init.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/commands/init_claude.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/commands/run.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/commands/test_alert.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/commands/tune.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/commands/unlock.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/main.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/config/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/config/metric_config.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/config/profile.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/config/project_config.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/config/validator.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/core/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/core/interval.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/core/models.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/_sql_manager.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/clickhouse_manager.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/_alert_states.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/_autotune_runs.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/_base.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/_datapoints.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/_detections.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/_maintenance.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/_metrics.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/_schema.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/_tasks.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/internal_tables/manager.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/manager.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/mysql_manager.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/postgres_manager.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/database/tables.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/base.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/factory.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/seasonality.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/statistical/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/statistical/_windowed.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/statistical/iqr.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/statistical/mad.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/statistical/manual_bounds.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/detectors/statistical/zscore.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/loaders/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/loaders/metric_loader.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/loaders/query_template.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/orchestration/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/orchestration/error_dispatch.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/orchestration/task_manager/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/orchestration/task_manager/_alert_step.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/orchestration/task_manager/_base.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/orchestration/task_manager/_detect_step.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/orchestration/task_manager/_load_step.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/orchestration/task_manager/_types.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/orchestration/task_manager/manager.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/reporting/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/reporting/assets/report.js +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/reporting/builder.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/reporting/html_report.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/tuning/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/tuning/config_writer.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/tuning/html.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/tuning/payload.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/tuning/server.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/utils/__init__.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/utils/datetime_utils.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/utils/env_interpolation.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/utils/json_utils.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit/utils/stats.py +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit.egg-info/SOURCES.txt +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit.egg-info/dependency_links.txt +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit.egg-info/entry_points.txt +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit.egg-info/requires.txt +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/detectkit.egg-info/top_level.txt +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/pyproject.toml +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/requirements.txt +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/setup.cfg +0 -0
- {detectkit-0.31.0 → detectkit-0.31.1}/setup.py +0 -0
|
@@ -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.31.
|
|
7
|
+
__version__ = "0.31.1"
|
|
8
8
|
|
|
9
9
|
from detectkit.core.interval import Interval
|
|
10
10
|
from detectkit.core.models import ColumnDefinition, TableModel
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";(()=>{var tt={"--term-bg":"#211e1a","--clay":"#d15b36","--st-anomaly":"#d63232","--st-recovery":"#36a64f","--st-nodata":"#f0ad4e","--st-error":"#5a7a8c","--faint":"#9a9384","--muted":"#6e675b","--border":"#332f29","--term-border":"#332f29"};function O(t){return getComputedStyle(document.documentElement).getPropertyValue(t).trim()||tt[t]||"#888"}function nt(t){let r=t.replace("#","").trim();r.length===3&&(r=r[0]+r[0]+r[1]+r[1]+r[2]+r[2]);let u=parseInt(r,16);return r.length!==6||Number.isNaN(u)?[209,91,54]:[u>>16&255,u>>8&255,u&255]}function R(t,r){let[u,e,d]=nt(t);return`rgba(${u},${e},${d},${r})`}function Fe(t){let r=Math.max(1,window.devicePixelRatio||1),u=t.clientWidth||t.offsetWidth||0,e=t.clientHeight||t.offsetHeight||0;return t.width=Math.round(u*r),t.height=Math.round(e*r),r}var $e=Number.isFinite;function ze(t,r,u,e,d,i,p,s,m,x,f,k){let z=r.length,S=Math.max(1,Math.round(p)),A=d-e||1,ie=0;for(let W=0;W<z;W++){let N=u[W];!$e(N)||r[W]<e||r[W]>d||ie++}if(t.strokeStyle=x,t.lineWidth=f*k,t.lineJoin="round",t.beginPath(),ie<=S){let W=!1;for(let N=0;N<z;N++){let D=u[N],T=r[N];if(!$e(D)||T<e||T>d){W=!1;continue}let E=s(T),I=m(D);W?t.lineTo(E,I):(t.moveTo(E,I),W=!0)}}else{let W=new Array(S).fill(null),N=new Array(S).fill(null);for(let T=0;T<z;T++){let E=u[T],I=r[T];if(!$e(E)||I<e||I>d)continue;let P=Math.floor((I-e)/A*(S-1));P=P<0?0:P>S-1?S-1:P,(W[P]===null||E<W[P])&&(W[P]=E),(N[P]===null||E>N[P])&&(N[P]=E)}let D=!1;for(let T=0;T<S;T++){if(N[T]===null){D=!1;continue}let E=i+T,I=m(N[T]),P=m(W[T]);D?t.lineTo(E,I):(t.moveTo(E,I),D=!0),t.lineTo(E,P)}}t.stroke()}function Be(t){let r=Math.abs(t);return r>=1e3?t.toFixed(0):r>=10?t.toFixed(1):r>=1?t.toFixed(2):t.toFixed(3)}function je(t,r){let u=new Date(t).toISOString();return r<2*864e5?u.slice(5,16).replace("T"," "):u.slice(5,10)}function Ye(t,r,u){return{left:r.l*u,top:r.t*u,right:t.width-r.r*u,bottom:t.height-r.b*u}}function Ue(t,r,u,e,d,i,p){let s=Ye(r,u,e),m=Math.max(s.left,Math.min(d(i),s.right));m<=s.left+.5||(t.save(),t.fillStyle="rgba(17,15,13,0.42)",t.fillRect(s.left,s.top,m-s.left,s.bottom-s.top),t.strokeStyle=R(O("--faint"),.7),t.lineWidth=1*e,t.setLineDash([4*e,4*e]),t.beginPath(),t.moveTo(m,s.top),t.lineTo(m,s.bottom),t.stroke(),t.setLineDash([]),t.fillStyle=R(O("--faint"),.95),t.font=`${10*e}px ui-monospace, monospace`,t.textAlign="left",t.textBaseline="top",t.fillText(p,m+6*e,s.top+5*e),t.restore())}function Ge(t,r,u,e,d,i,p){let s=Ye(r,u,e),m=5*e;t.save();for(let x=0;x<i.length;x++){let f=i[x],k=d(f.t);if(k<s.left-1||k>s.right+1)continue;let z=p(f.kind);t.strokeStyle=R(z,.45),t.lineWidth=1*e,t.beginPath(),t.moveTo(k,s.top),t.lineTo(k,s.bottom),t.stroke(),t.fillStyle=z,t.beginPath(),t.moveTo(k-m,s.top),t.lineTo(k+m,s.top),t.lineTo(k,s.top+m*1.4),t.closePath(),t.fill()}t.restore()}var ot={mad:1,zscore:2,iqr:4};function rt(t,r){let u=t.seasonalityData;if(!u||u.length===0)return 0;let e=0;for(let d of r){let i=new Set;for(let p of u)i.add(d.map(s=>{var m;return String((m=p==null?void 0:p[s])!=null?m:"")}).join("|"));e=Math.max(e,i.size)}return e}function Ve(t,r){let u=t.timestamps.length,e=Math.max(r.minSamples,ot[r.type]);if(r.smoothing==="sma"&&(e=Math.max(e,r.smoothingWindow-1)),r.smoothing==="ema"&&(e=Math.max(e,Math.ceil(5/r.smoothingAlpha))),r.inputType!=="values"&&(e=Math.max(e,1)),r.seasonalityComponents!==null&&r.seasonalityComponents.length>0&&Array.isArray(t.seasonalityData)&&t.seasonalityData.length>0){let i=rt(t,r.seasonalityComponents);if(i>0){let p=r.minSamplesPerGroup*i;r.windowSize>=p&&(e=Math.max(e,p))}}return Math.min(e,u)}var C={l:52,r:14,t:14,b:26},Ie=46,Ke=10,it=13,te=Number.isFinite,ce=1e3,ue=60*ce,de=60*ue,q=24*de,Oe=[ce,2*ce,5*ce,10*ce,15*ce,30*ce,ue,2*ue,5*ue,10*ue,15*ue,30*ue,de,2*de,3*de,6*de,12*de,q,2*q,3*q,5*q,7*q,14*q];function Xe(t,r,u){let e=Math.max(r-t,1);if(e>u*28*q){let s=[1,2,3,6,12,24,36,60,120,240],m=s[s.length-1];for(let A of s)if(e/(A*30.44*q)<=u){m=A;break}let x=new Date(t),f=x.getUTCFullYear(),k=x.getUTCMonth();if(m>=12){let A=m/12;f=Math.floor(f/A)*A,k=0}else k=Math.floor(k/m)*m;let z=[],S=Date.UTC(f,k,1);for(;S<=r;)S>=t&&z.push(S),k+=m,f+=Math.floor(k/12),k%=12,S=Date.UTC(f,k,1);return{ticks:z,step:m*30*q}}let d=Oe[Oe.length-1];for(let s of Oe)if(e/s<=u){d=s;break}let i;if(d%q===0){let s=new Date(t);i=Date.UTC(s.getUTCFullYear(),s.getUTCMonth(),s.getUTCDate());let m=d/q,x=Math.round(i/q);i+=(m-x%m)%m*q}else i=Math.ceil(t/d)*d;let p=[];for(let s=i;s<=r;s+=d)s>=t&&p.push(s);return{ticks:p,step:d}}function Je(t,r){let u=new Date(t).toISOString();return r>=320*q?u.slice(0,4):r>=26*q?u.slice(0,7):r>=q?u.slice(5,10):r>=de?u.slice(5,16).replace("T"," "):u.slice(5,19).replace("T"," ")}function Qe(t,r={}){let u=t.getContext("2d");if(!u)throw new Error("chart: 2D context unavailable");let e=u,d=!!r.navigable,i=1,p=null,s=-1,m=0,x=0,f=1,k=0,z=1,S=0,A=1,ie="";function W(){i=Fe(t)}let N=()=>d?(Ke+Ie)*i:0,D=()=>t.width-(C.l+C.r)*i,T=()=>t.height-(C.t+C.b)*i-N(),E=()=>d?S:x,I=()=>d?A:f,P=()=>I()-E()||1,Y=()=>f-x||1,H=n=>C.l*i+(n-E())/P()*D(),G=n=>t.height-C.b*i-N()-(n-k)/(z-k||1)*T(),V=()=>t.height-Ie*i,K=()=>(Ie-it)*i,ne=()=>t.width-(C.l+C.r)*i,Q=n=>C.l*i+(n-x)/Y()*ne(),Ae=n=>V()+K()-(n-k)/(z-k||1)*K(),X=(n,o,a)=>Math.max(o,Math.min(a,n)),oe=()=>{let n=p==null?void 0:p.series,o=n?n.timestamps.length:0,a=o>1?Y()/(o-1):1e3;return Math.max(a*8,1e3)};function J(n,o){let a=o-n,c=oe();if(a<c){let l=(n+o)/2;n=l-c/2,o=l+c/2,a=c}a>=Y()&&(n=x,o=f),n<x&&(o+=x-n,n=x),o>f&&(n-=o-f,o=f),S=X(n,x,f),A=X(o,x,f),re()}let De=n=>{let o=(n-C.l*i)/(D()||1);return E()+X(o,0,1)*P()},se=n=>{let o=(n-C.l*i)/(ne()||1);return x+X(o,0,1)*Y()};function Pe(n){let o=p==null?void 0:p.series;if(!o||o.timestamps.length===0)return-1;let a=(n-C.l*i)/(D()||1),c=E()+a*P(),l=o.timestamps,h=0,y=l.length-1;for(;h<y;){let _=h+y>>1;l[_]<c?h=_+1:y=_}return h>0&&c-l[h-1]<l[h]-c&&(h-=1),h}function Le(n,o){let a=n.timestamps;if(x=a[0],f=a[a.length-1],d){let y=`${a.length}:${x}:${f}`;y!==ie?(ie=y,S=x,A=f):(S=X(S,x,f),A=X(Math.max(A,S+oe()),x,f))}let c=1/0,l=-1/0;for(let y of n.values)te(y)&&(y<c&&(c=y),y>l&&(l=y));for(let y of o)y.scored&&(te(y.lower)&&y.lower<c&&(c=y.lower),te(y.upper)&&y.upper>l&&(l=y.upper));(!te(c)||!te(l))&&(c=0,l=1),l<=c&&(l=c+1);let h=(l-c)*.06;k=c-h,z=l+h}function ae(n,o,a){let c=p.series.timestamps;ze(e,c,n,E(),I(),C.l*i,D(),H,G,o,a,i)}function ge(n,o){let a=[],c=-1;for(let l=Math.max(0,o);l<n.length;l++){let h=n[l];h.scored&&te(h.lower)&&te(h.upper)?c===-1&&(c=l):c!==-1&&(a.push([c,l-1]),c=-1)}return c!==-1&&a.push([c,n.length-1]),a}function Z(){if(m=0,!p||t.width===0||t.height===0)return;let{series:n,scored:o,params:a,alerts:c}=p;if(n.timestamps.length===0){e.fillStyle=O("--term-bg"),e.fillRect(0,0,t.width,t.height);return}let l=O("--clay"),h=O("--st-anomaly"),y=O("--faint"),_=O("--muted");e.fillStyle=O("--term-bg"),e.fillRect(0,0,t.width,t.height),e.font=`${11*i}px ui-monospace, 'JetBrains Mono', monospace`,e.textBaseline="middle";for(let g=0;g<=4;g++){let v=k+(z-k)*g/4,w=G(v);e.strokeStyle=R(y,.1),e.lineWidth=1*i,e.beginPath(),e.moveTo(C.l*i,w),e.lineTo(t.width-C.r*i,w),e.stroke(),e.fillStyle=_,e.textAlign="right",e.fillText(Be(v),(C.l-8)*i,w)}e.textBaseline="top";let F=t.height-C.b*i-N();if(d){let g=Xe(E(),I(),7);for(let v of g.ticks){let w=H(v);e.strokeStyle=R(y,.1),e.lineWidth=1*i,e.beginPath(),e.moveTo(w,C.t*i),e.lineTo(w,F),e.stroke(),e.fillStyle=_,e.textAlign=w<(C.l+24)*i?"left":w>t.width-(C.r+24)*i?"right":"center",e.fillText(Je(v,g.step),w,F+7*i)}}else{let g=P();for(let v=0;v<=5;v++){let w=x+g*v/5,U=H(w);e.fillStyle=_,e.textAlign=v===0?"left":v===5?"right":"center",e.fillText(je(w,g),U,F+7*i)}}e.save(),e.beginPath(),e.rect(C.l*i,C.t*i,D(),T()),e.clip();let B=o.length,M=Math.min(Ve(n,a),B),L=M<B?n.timestamps[M]:void 0,j=ge(o,M);e.fillStyle=R(l,.13);for(let[g,v]of j){e.beginPath(),e.moveTo(H(o[g].timestamp),G(o[g].upper));for(let w=g+1;w<=v;w++)e.lineTo(H(o[w].timestamp),G(o[w].upper));for(let w=v;w>=g;w--)e.lineTo(H(o[w].timestamp),G(o[w].lower));e.closePath(),e.fill()}e.strokeStyle=R(l,.4),e.lineWidth=1*i;for(let[g,v]of j)for(let w of["upper","lower"]){e.beginPath();for(let U=g;U<=v;U++){let Ce=H(o[U].timestamp),Te=G(o[U][w]);U===g?e.moveTo(Ce,Te):e.lineTo(Ce,Te)}e.stroke()}e.strokeStyle=R(y,.55),e.lineWidth=1*i,e.setLineDash([3*i,3*i]);for(let[g,v]of j){e.beginPath();for(let w=g;w<=v;w++){let U=o[w].center;if(!te(U))continue;let Ce=H(o[w].timestamp),Te=G(U);w===g?e.moveTo(Ce,Te):e.lineTo(Ce,Te)}e.stroke()}if(e.setLineDash([]),a.smoothing!=="none"){ae(n.values,R(l,.28),1.25);let g=o.map(v=>v.processedValue);ae(g,l,1.6)}else ae(n.values,l,1.5);for(let g=M;g<B;g++){let v=o[g];if(!v.scored||!te(v.value))continue;let w=H(v.timestamp),U=G(v.value);v.isAnomaly?(e.fillStyle=R(h,.18),e.beginPath(),e.arc(w,U,6*i,0,Math.PI*2),e.fill(),e.fillStyle=h,e.beginPath(),e.arc(w,U,3*i,0,Math.PI*2),e.fill()):n.truthAnomaly[g]&&(e.strokeStyle=R(_,.7),e.lineWidth=1.25*i,e.beginPath(),e.arc(w,U,3.5*i,0,Math.PI*2),e.stroke())}L!==void 0&&Ue(e,t,C,i,H,L,"detection at full power \u2192"),s>=0&&s<o.length&&me(s,a.windowSize,o,n,y),c&&c.length&&Ge(e,t,C,i,H,c,g=>g==="anomaly"?O("--st-anomaly"):g==="recovery"?O("--st-recovery"):O("--st-nodata")),e.restore(),d&&ve(n,c,l,y,_)}function ve(n,o,a,c,l){let h=V(),y=h+K(),_=C.l*i,F=t.width-C.r*i,B=Xe(x,f,5);e.save(),e.beginPath(),e.rect(_,h,ne(),K()),e.clip(),e.strokeStyle=R(c,.1),e.lineWidth=1*i;for(let g of B.ticks){let v=Q(g);e.beginPath(),e.moveTo(v,h),e.lineTo(v,y),e.stroke()}ze(e,n.timestamps,n.values,x,f,_,ne(),Q,Ae,R(a,.7),1.1,i),e.restore();let M=Q(S),L=Q(A);if(e.fillStyle="rgba(27,25,22,0.55)",e.fillRect(_,h,M-_,K()),e.fillRect(L,h,F-L,K()),o&&o.length){let g=O("--st-anomaly");e.fillStyle=R(g,.85);for(let v of o){let w=Q(v.t);e.fillRect(w-1*i,h,2*i,K())}}e.fillStyle="rgba(245,241,232,0.06)",e.fillRect(M,h,L-M,K()),e.strokeStyle=a,e.lineWidth=1.5*i,e.strokeRect(M,h+1,L-M,K()-2),e.fillStyle=a;let j=h+K()/2-8*i;e.fillRect(M-2*i,j,4*i,16*i),e.fillRect(L-2*i,j,4*i,16*i),e.font=`${10*i}px ui-monospace, monospace`,e.textBaseline="top",e.fillStyle=l;for(let g of B.ticks){let v=Q(g);e.strokeStyle=R(c,.25),e.lineWidth=1*i,e.beginPath(),e.moveTo(v,y),e.lineTo(v,y+3*i),e.stroke(),e.textAlign=v<(C.l+26)*i?"left":v>t.width-(C.r+26)*i?"right":"center",e.fillText(Je(g,B.step),v,y+5*i)}}function me(n,o,a,c,l){let h=c.timestamps,y=Math.max(0,n-o),_=n-1,F=C.t*i,B=T();if(_>=y){let j=c.intervalSeconds*1e3/P()*D()*.5,g=H(h[y])-j,v=H(h[_])+j;e.fillStyle="rgba(255,255,255,0.05)",e.fillRect(g,F,v-g,B),e.strokeStyle=R(l,.5),e.lineWidth=1*i,e.beginPath(),e.moveTo(g,F),e.lineTo(g,F+B),e.moveTo(v,F),e.lineTo(v,F+B),e.stroke()}let M=H(h[n]);e.strokeStyle=R(l,.85),e.lineWidth=1*i,e.setLineDash([2*i,2*i]),e.beginPath(),e.moveTo(M,F),e.lineTo(M,F+B),e.stroke(),e.setLineDash([]);let L=a[n];if(L.scored&&te(L.lower)&&te(L.upper)){let j=5*i;e.strokeStyle=R(O("--clay"),.85),e.lineWidth=1.5*i;for(let g of[L.lower,L.upper]){let v=G(g);e.beginPath(),e.moveTo(M-j,v),e.lineTo(M+j,v),e.stroke()}}if(te(L.value)){let j=G(L.value);e.fillStyle=O("--term-bg"),e.beginPath(),e.arc(M,j,4*i,0,Math.PI*2),e.fill(),e.strokeStyle=L.isAnomaly?O("--st-anomaly"):O("--clay"),e.lineWidth=2*i,e.beginPath(),e.arc(M,j,4*i,0,Math.PI*2),e.stroke()}}function re(){m===0&&(m=requestAnimationFrame(Z))}function fe(){var a;if(!r.onHover||!p)return;if(s<0){r.onHover(null);return}let n=(a=p.scored[s])!=null?a:null,o={index:s,point:n,windowStart:Math.max(0,s-p.params.windowSize),windowEnd:s-1};r.onHover(o)}let ee=null,$=null,le=n=>{let o=t.getBoundingClientRect();return{x:(n.clientX-o.left)*i,y:(n.clientY-o.top)*i}},xe=n=>d&&n>=V(),ye=n=>{let o=Q(S),a=Q(A),c=8*i;return Math.abs(n-o)<=c?"l":Math.abs(n-a)<=c?"r":n>o&&n<a?"move":"out"};function pe(n){if(!p)return;let{x:o,y:a}=le(n);if(ee||$)return;if(xe(a)){s!==-1&&(s=-1,fe(),re());let l=ye(o);t.style.cursor=l==="l"||l==="r"?"ew-resize":l==="move"?"grab":"pointer";return}d&&(t.style.cursor="grab");let c=Pe(o);c!==s&&(s=c,fe(),re())}function we(){s!==-1&&(s=-1,fe(),re())}function ke(n){if(!d||!p)return;let{x:o,y:a}=le(n);if(a>=V()){let c=ye(o);if(c==="l")$={type:"l",grab:0,vMin:S,vMax:A};else if(c==="r")$={type:"r",grab:0,vMin:S,vMax:A};else if(c==="move")$={type:"move",grab:se(o),vMin:S,vMax:A};else{let l=se(o),h=P();J(l-h/2,l+h/2),$={type:"move",grab:l,vMin:S,vMax:A}}t.style.cursor="grabbing",n.preventDefault()}else a>C.t*i&&a<V()-Ke*i&&(ee={x:o,vMin:S,vMax:A},t.style.cursor="grabbing",n.preventDefault())}function Ee(n){if(!p)return;let{x:o}=le(n);if(ee){let a=(o-ee.x)*(ee.vMax-ee.vMin)/(D()||1);J(ee.vMin-a,ee.vMax-a)}else if($){let a=se(o);$.type==="l"?J(Math.min(a,A-oe()),A):$.type==="r"?J(S,Math.max(a,S+oe())):J($.vMin+(a-$.grab),$.vMax+(a-$.grab))}}function he(){(ee||$)&&(ee=null,$=null,t.style.cursor="grab")}function be(n){if(!d||!p)return;n.preventDefault();let{x:o,y:a}=le(n),c=X(P()*Math.pow(1.0015,n.deltaY),oe(),Y());if(a>=V()){let l=se(o);J(l-c/2,l+c/2)}else{let l=De(o),h=(l-S)/(P()||1);J(l-h*c,l-h*c+c)}}function Se(){d&&J(x,f)}t.addEventListener("mousemove",pe),t.addEventListener("mouseleave",we),d&&(t.addEventListener("mousedown",ke),t.addEventListener("wheel",be,{passive:!1}),t.addEventListener("dblclick",Se),window.addEventListener("mousemove",Ee),window.addEventListener("mouseup",he));function Me(n){p=n,Le(n.series,n.scored),s>=n.series.timestamps.length&&(s=-1),re()}function Ne(){W(),p&&(Le(p.series,p.scored),re())}function _e(){t.removeEventListener("mousemove",pe),t.removeEventListener("mouseleave",we),d&&(t.removeEventListener("mousedown",ke),t.removeEventListener("wheel",be),t.removeEventListener("dblclick",Se),window.removeEventListener("mousemove",Ee),window.removeEventListener("mouseup",he)),m!==0&&cancelAnimationFrame(m),m=0,p=null}return W(),{render:Me,resize:Ne,destroy:_e}}var st={mad:3,zscore:3,iqr:1.5},at={mad:10,zscore:3,iqr:4},lt="dtk-tune";function b(t,r,u){let e=document.createElement(t);return r&&(e.className=r),u!=null&&(e.textContent=u),e}function He(t,r){let u=b("label","dtk-ctl-label",t);if(r){u.title=r;let e=b("span","dtk-ctl-info","\u24D8");e.title=r,u.appendChild(document.createTextNode(" ")),u.appendChild(e)}return u}function We(t,r,u,e,d){let i=b("div","dtk-ctl");i.appendChild(He(t,d));let p=b("div","dtk-seg"),s=u,m=[],x=()=>{m.forEach(f=>f.classList.toggle("on",f.dataset.v===s))};return r.forEach(f=>{let k=b("button","dtk-seg-btn",f.label);k.type="button",k.dataset.v=f.value,k.onclick=()=>{s=f.value,x(),e(s)},m.push(k),p.appendChild(k)}),x(),i.appendChild(p),{row:i,get:()=>s,set:f=>{s=f,x()}}}function Re(t,r,u){var x;let e=b("div","dtk-ctl"),d=b("div","dtk-ctl-head"),i=He(t,r.hint),p=b("span","dtk-ctl-val"),s=(x=r.fmt)!=null?x:(f=>String(f));d.appendChild(i),d.appendChild(p),e.appendChild(d);let m=b("input","dtk-range");return m.type="range",m.min=String(r.min),m.max=String(r.max),m.step=String(r.step),m.value=String(r.value),p.textContent=s(r.value),m.oninput=()=>{let f=Number(m.value);p.textContent=s(f),u(f)},e.appendChild(m),{row:e,get:()=>Number(m.value),setMax:f=>{m.max=String(f),Number(m.value)>f&&(m.value=String(f),p.textContent=s(f))}}}function et(t){let r={threshold:t.threshold,window_size:t.windowSize};return t.windowWeights!=="none"&&(r.window_weights=t.windowWeights,t.windowWeights==="exponential"&&t.halfLife!=null&&(r.half_life=t.halfLife)),t.detrend!=="none"&&(r.detrend=t.detrend),t.smoothing!=="none"&&(r.smoothing=t.smoothing),t.inputType!=="values"&&(r.input_type=t.inputType),t.seasonalityComponents&&t.seasonalityComponents.length&&(r.seasonality_components=t.seasonalityComponents,r.min_samples_per_group=t.minSamplesPerGroup),r}function ct(t,r){let u=et(t),e=[`type: ${t.type}`];for(let[d,i]of Object.entries(u))e.push(`${d}=${typeof i=="object"?JSON.stringify(i):i}`);return e.push(`consecutive_anomalies=${r}`),e.join(" \xB7 ")}function ut(t,r){var Ne,_e;pt(),r.classList.add(lt),r.innerHTML="";let u=b("div","dtk-tune-root");r.appendChild(u);let e=t.points.length,d={timestamps:t.points.map(n=>n.t),values:t.points.map(n=>n.v==null?NaN:n.v),intervalSeconds:t.interval_seconds,truthAnomaly:new Array(e).fill(!1),seasonalityData:t.seasonality_columns.length?t.seasonality:void 0,seasonalityColumns:t.seasonality_columns.length?t.seasonality_columns:void 0},i=d,p=n=>{let o=Math.max(0,e-n);return o<=0?d:{timestamps:d.timestamps.slice(o),values:d.values.slice(o),intervalSeconds:d.intervalSeconds,truthAnomaly:d.truthAnomaly.slice(o),seasonalityData:d.seasonalityData?d.seasonalityData.slice(o):void 0,seasonalityColumns:d.seasonalityColumns}},s=t.detector,m=t.consecutive_anomalies,x=(Ne=s.seasonalityComponents)!=null?Ne:[],f=new Map;x.forEach((n,o)=>n.forEach(a=>f.set(a,o+1)));let k=()=>{let n=0;f.forEach(a=>{a>n&&(n=a)});let o=[];for(let a=1;a<=n;a++){let c=t.seasonality_columns.filter(l=>f.get(l)===a);c.length&&o.push(c)}return o.length?o:null},z=()=>{var n;return{type:ve.get(),threshold:me.get(),windowSize:le.get(),minSamples:s.minSamples,inputType:s.inputType,smoothing:ke.get(),smoothingAlpha:s.smoothingAlpha,smoothingWindow:s.smoothingWindow,windowWeights:xe.get(),halfLife:xe.get()==="exponential"?ye.get():null,detrend:we.get(),seasonalityComponents:k(),minSamplesPerGroup:(n=at[ve.get()])!=null?n:s.minSamplesPerGroup,consecutiveAnomalies:m}},S=b("div","dtk-tune-header"),A=b("div","dtk-tune-titlerow");A.appendChild(b("h1","dtk-tune-title",t.metric));let ie=b("span","dtk-tune-badge",t.save_url?"manual tuning":"preview");A.appendChild(ie),S.appendChild(A);let W=t.project?`${t.project} \xB7 `:"";S.appendChild(b("div","dtk-tune-sub",`${W}${e} points \xB7 ${ft(t.interval_seconds)} grid`)),t.description&&S.appendChild(b("div","dtk-tune-desc",t.description)),u.appendChild(S);let N=b("div","dtk-tune-grid"),D=b("div","dtk-tune-controls"),T=b("div","dtk-tune-main");N.appendChild(D),N.appendChild(T),u.appendChild(N);let E=b("div","dtk-tune-trim"),I=b("div","dtk-tune-trim-head");I.appendChild(He("Points shown","Trim the active sample to the most-recent N points. Fewer points recompute faster (cost grows with points \xD7 window) and make a shorter period easier to read \u2014 handy once you can see a smaller window/period is enough."));let P=b("span","dtk-tune-trim-val");I.appendChild(P),E.appendChild(I);let Y=b("input","dtk-range");Y.type="range",Y.min=String(Math.min(e,200)),Y.max=String(e),Y.step=String(Math.max(1,Math.round(e/200))),Y.value=String(e),E.appendChild(Y),T.appendChild(E);let H=b("div","dtk-tune-chart"),G=b("canvas");H.appendChild(G);let V=b("div","dtk-tune-spin");V.appendChild(b("span","dtk-spin-ring")),V.appendChild(b("span","dtk-spin-txt","computing\u2026")),H.appendChild(V),T.appendChild(H);let K=b("div","dtk-tune-legend"),ne=(n,o,a)=>{let c=b("span","dtk-leg-item");c.title=a,c.appendChild(b("span",`dtk-leg-sw ${n}`)),c.appendChild(b("span","dtk-leg-txt",o)),K.appendChild(c)};ne("line","metric","The metric value over time."),ne("band","expected range","The detector's confidence band \u2014 values inside it read as normal."),ne("center","band center","The expected value at the middle of the band."),ne("dot","anomaly","A point the detector flagged as anomalous (outside the band)."),ne("alert","alert","Where an alert fired \u2014 enough consecutive anomalies to meet the rule."),T.appendChild(K);let Q=b("div","dtk-tune-readout");T.appendChild(Q);let Ae=Qe(G,{navigable:!0,onHover:n=>{if(!n||!n.point||!n.point.scored){Q.textContent="";return}let o=n.point;Q.textContent=`t=${dt(o.timestamp)} value=${qe(o.value)} band=[${qe(o.lower)}, ${qe(o.upper)}]`+(o.isAnomaly?` \u26A0 ${o.direction} (sev ${o.severity.toFixed(2)})`:"")}}),X=new Worker(URL.createObjectURL(new Blob([`"use strict";(()=>{var X={mad:1,zscore:2,iqr:4};function T(n){let e=0;for(let t of n)e+=t;return e}function ie(n){let e=n.map((t,r)=>r);return e.sort((t,r)=>n[t]<n[r]?-1:n[t]>n[r]?1:t-r),e}function se(n,e,t){let r=e.length;if(r===0)return NaN;if(n<=e[0])return t[0];if(n>=e[r-1])return t[r-1];for(let i=1;i<r;i++)if(n<=e[i]){let o=e[i-1],c=e[i],u=t[i-1],s=t[i];if(c===o)return u;let d=(n-o)/(c-o);return u+d*(s-u)}return t[r-1]}function F(n,e,t){let r=ie(n),i=r.map(b=>n[b]),o=r.map(b=>e[b]),c=T(o),u=new Array(o.length),s=0;for(let b=0;b<o.length;b++)s+=o[b],u[b]=(s-.5*o[b])/c;let d=t/100;return se(d,u,i)}function S(n,e){return F(n,e,50)}function ce(n,e,t){let r=t===void 0?S(n,e):t,i=n.map(o=>Math.abs(o-r));return S(i,e)}function ue(n,e){let t=T(e),r=0;for(let i=0;i<n.length;i++)r+=n[i]*(e[i]/t);return r}function me(n,e,t,r=0){let i=T(e),o=e.map(s=>s/i),c=t===void 0?T(n.map((s,d)=>s*o[d])):t,u=0;for(let s=0;s<n.length;s++)u+=o[s]*(n[s]-c)**2;if(r===1){let s=1-T(o.map(d=>d*d));s>1e-12&&(u/=s)}return Math.sqrt(u)}function le(n,e){return e.smoothing==="none"?n.slice():e.smoothing==="ema"?ae(n,e.smoothingAlpha):fe(n,e.smoothingWindow)}function ae(n,e){let t=n.length,r=new Array(t).fill(NaN);if(t===0)return r;let i=-1;for(let o=0;o<t;o++)if(!Number.isNaN(n[o])){i=o;break}if(i===-1)return r;r[i]=n[i];for(let o=i+1;o<t;o++)Number.isNaN(n[o])?r[o]=r[o-1]:r[o]=e*n[o]+(1-e)*r[o-1];return r}function fe(n,e){let t=n.length,r=new Array(t).fill(NaN);for(let i=0;i<t;i++){let o=Math.max(0,i-e+1),c=0,u=0;for(let s=o;s<=i;s++)Number.isNaN(n[s])||(c+=n[s],u+=1);r[i]=u>0?c/u:NaN}return r}function de(n,e){let t=n.length;if(e.inputType==="values")return n.slice();let r=new Array(t).fill(NaN);for(let i=1;i<t;i++){let o=n[i-1],c=n[i];e.inputType==="changes"?r[i]=(c-o)/o:e.inputType==="absolute_changes"?r[i]=c-o:r[i]=Math.log(c+1)-Math.log(o+1)}return r}function be(n,e){return n.halfLife!==null?n.halfLife:Math.max(n.windowSize/20,e/2,1)}function pe(n,e){if(n.windowWeights==="none")return null;let t=n.windowSize,r=new Array(t);if(n.windowWeights==="exponential"){let i=be(n,e);for(let o=1;o<=t;o++){let c=Math.min(o/i,1e3);r[o-1]=Math.pow(.5,c)}return r}for(let i=1;i<=t;i++)r[i-1]=(t+1-i)/t;return r}function K(n,e){return e===null?n.map(()=>1):n.map(t=>e[t-1])}function ge(n){let e=n[0];for(let t of n)t>e&&(e=t);return e}function ye(n){let e=n[0];for(let t of n)t<e&&(e=t);return e}function he(n,e,t){if(n.length<4)return 0;let r=(ge(e)+ye(e))/2,i=e.map(l=>l>r),o=i.map(l=>!l),c=0,u=0;for(let l=0;l<e.length;l++)i[l]?c++:u++;if(c<2||u<2)return 0;let s=(l,N)=>N.filter((L,y)=>l[y]),d=s(o,n),b=s(i,n),k=s(o,e),C=s(i,e),g=s(o,t),f=s(i,t),q=S(d,g),p=S(b,f),w=S(k,g),M=S(C,f);return M===w?0:(q-p)/(M-w)}var Se={mad:[["median","center"],["mad","spread"]],zscore:[["mean","center"],["std","spread"]],iqr:[["q1","center"],["q3","center"],["iqr","spread"]]};function Q(n,e,t){if(n==="mad"){let o=S(e,t);return{median:o,mad:ce(e,t,o)}}if(n==="zscore"){let o=ue(e,t);return{mean:o,std:me(e,t,o,1)}}let r=F(e,t,25),i=F(e,t,75);return{q1:r,q3:i,iqr:i-r}}function we(n,e,t){if(n==="mad"){if(e.mad===0)return[e.median-1e-10,e.median+1e-10];let r=t*1.4826*e.mad;return[e.median-r,e.median+r]}return n==="zscore"?e.std===0?[e.mean-1e-10,e.mean+1e-10]:[e.mean-t*e.std,e.mean+t*e.std]:e.iqr===0?[e.q1-1e-10,e.q3+1e-10]:[e.q1-t*e.iqr,e.q3+t*e.iqr]}function Me(n,e,t){if(n==="mad"){let r=1.4826*e.mad;return r>0?t/r:1/0}return n==="zscore"?e.std>0?t/e.std:1/0:e.iqr>0?t/e.iqr:1/0}function Ne(n,e){return n==="mad"?e.median:n==="zscore"?e.mean:(e.q1+e.q3)/2}function U(n,e,t,r,i){return{index:n,timestamp:e,value:t,processedValue:r,scored:!1,isAnomaly:!1,lower:NaN,upper:NaN,center:NaN,direction:null,severity:0,reason:i}}function Y(n,e){let{type:t}=e,r=Math.max(e.minSamples,X[t]),i=Se[t],{timestamps:o,values:c}=n,u=o.length,s=le(c,e),d=de(s,e),b=e.seasonalityComponents!==null&&e.seasonalityComponents.length>0&&Array.isArray(n.seasonalityData)&&n.seasonalityData.length>0,k=n.seasonalityData,C=pe(e,r),g=[];for(let f=0;f<u;f++){let q=c[f],p=d[f],w=o[f];if(Number.isNaN(p)){g.push(U(f,w,q,p,"missing_data"));continue}let M=Math.max(0,f-e.windowSize),l=f-M,N=d.slice(M,f),L=N.map(m=>!Number.isNaN(m)),y=[];for(let m=0;m<N.length;m++)L[m]&&y.push(N[m]);if(y.length<r){g.push(U(f,w,q,p,"insufficient_data"));continue}let O=new Array(l);for(let m=0;m<l;m++)O[m]=l-m;let z=[];for(let m=0;m<l;m++)L[m]&&z.push(O[m]);let V=K(z,C),P=0;e.detrend==="linear"&&(P=he(y,z,V));let $=P!==0?y.map((m,W)=>m+P*z[W]):y,G=Q(t,$,V),I={...G};if(b&&k){let m=k[f];for(let W of e.seasonalityComponents){let J=new Array(l).fill(!0);for(let a=0;a<l;a++){let D=k[M+a],x=!0;for(let j of W)if(!D||D[j]!==(m==null?void 0:m[j])){x=!1;break}J[a]=x}let _=[],E=[];for(let a=0;a<l;a++)L[a]&&J[a]&&(_.push(N[a]),E.push(O[a]));if(_.length<e.minSamplesPerGroup)continue;let ne=K(E,C),te=P!==0?_.map((a,D)=>a+P*E[D]):_,re=Q(t,te,ne);for(let[a,D]of i){let x=G[a],oe=(D==="spread"?x>0:x!==0)?re[a]/x:1;I[a]*=oe}}}let[h,A]=we(t,I,e.threshold);h>A&&([h,A]=[A,h]);let H=p<h||p>A,R=null,B=0;if(H){let m;p<h?(R="below",m=h-p):(R="above",m=p-A),B=Me(t,I,m)}let ee=Ne(t,I);g.push({index:f,timestamp:w,value:q,processedValue:p,scored:!0,isAnomaly:H,lower:h,upper:A,center:ee,direction:R,severity:B,reason:"ok"})}return g}function Ae(n,e){let t=n.seasonalityData;if(!t||t.length===0)return 0;let r=0;for(let i of e){let o=new Set;for(let c of t)o.add(i.map(u=>{var s;return String((s=c==null?void 0:c[u])!=null?s:"")}).join("|"));r=Math.max(r,o.size)}return r}function Z(n,e){let t=n.timestamps.length,r=Math.max(e.minSamples,X[e.type]);if(e.smoothing==="sma"&&(r=Math.max(r,e.smoothingWindow-1)),e.smoothing==="ema"&&(r=Math.max(r,Math.ceil(5/e.smoothingAlpha))),e.inputType!=="values"&&(r=Math.max(r,1)),e.seasonalityComponents!==null&&e.seasonalityComponents.length>0&&Array.isArray(n.seasonalityData)&&n.seasonalityData.length>0){let o=Ae(n,e.seasonalityComponents);if(o>0){let c=e.minSamplesPerGroup*o;e.windowSize>=c&&(r=Math.max(r,c))}}return Math.min(r,t)}var v=null;function De(n,e,t){let r=[],i=0;for(let o=0;o<n.length;o++){if(!(n[o].scored&&n[o].isAnomaly)){i=0;continue}let u=o>0&&n[o-1].scored&&n[o-1].isAnomaly,s=o>0&&n[o].timestamp-n[o-1].timestamp===e;i=u&&s?i+1:1,i===t&&r.push(o)}return r}self.onmessage=n=>{let e=n.data;if(e.type==="series"){v=e.series;return}if(e.type==="run"&&v){let t=e.params,r=Y(v,t),i=v.intervalSeconds*1e3,o=De(r,i,t.consecutiveAnomalies),c=Z(v,t),u=0;for(let s of r)s.scored&&s.isAnomaly&&u++;self.postMessage({type:"result",id:e.id,scored:r,fires:o,eff:c,flagged:u})}};})();
|
|
2
|
-
`],{type:"text/javascript"})));X.postMessage({type:"series",series:i});let oe=0,J=null;X.onmessage=n=>{let o=n.data;if(o.type!=="result"||o.id!==oe||!J)return;V.classList.remove("on");let a=J,c=o.fires.map(l=>({t:i.timestamps[l],kind:"anomaly"}));Ae.render({series:i,scored:o.scored,params:a,alerts:c}),he.textContent=`${o.flagged} flagged \xB7 ${o.fires.length} alert${o.fires.length===1?"":"s"} \xB7 warm-up ${o.eff} pts`,Se.textContent=
|
|
1
|
+
"use strict";(()=>{var nt={"--term-bg":"#211e1a","--clay":"#d15b36","--st-anomaly":"#d63232","--st-recovery":"#36a64f","--st-nodata":"#f0ad4e","--st-error":"#5a7a8c","--faint":"#9a9384","--muted":"#6e675b","--border":"#332f29","--term-border":"#332f29"};function O(t){return getComputedStyle(document.documentElement).getPropertyValue(t).trim()||nt[t]||"#888"}function ot(t){let r=t.replace("#","").trim();r.length===3&&(r=r[0]+r[0]+r[1]+r[1]+r[2]+r[2]);let u=parseInt(r,16);return r.length!==6||Number.isNaN(u)?[209,91,54]:[u>>16&255,u>>8&255,u&255]}function R(t,r){let[u,e,d]=ot(t);return`rgba(${u},${e},${d},${r})`}function Be(t){let r=Math.max(1,window.devicePixelRatio||1),u=t.clientWidth||t.offsetWidth||0,e=t.clientHeight||t.offsetHeight||0;return t.width=Math.round(u*r),t.height=Math.round(e*r),r}var He=Number.isFinite;function ze(t,r,u,e,d,i,p,s,m,x,f,k){let z=r.length,S=Math.max(1,Math.round(p)),A=d-e||1,ie=0;for(let W=0;W<z;W++){let N=u[W];!He(N)||r[W]<e||r[W]>d||ie++}if(t.strokeStyle=x,t.lineWidth=f*k,t.lineJoin="round",t.beginPath(),ie<=S){let W=!1;for(let N=0;N<z;N++){let D=u[N],T=r[N];if(!He(D)||T<e||T>d){W=!1;continue}let E=s(T),I=m(D);W?t.lineTo(E,I):(t.moveTo(E,I),W=!0)}}else{let W=new Array(S).fill(null),N=new Array(S).fill(null);for(let T=0;T<z;T++){let E=u[T],I=r[T];if(!He(E)||I<e||I>d)continue;let P=Math.floor((I-e)/A*(S-1));P=P<0?0:P>S-1?S-1:P,(W[P]===null||E<W[P])&&(W[P]=E),(N[P]===null||E>N[P])&&(N[P]=E)}let D=!1;for(let T=0;T<S;T++){if(N[T]===null){D=!1;continue}let E=i+T,I=m(N[T]),P=m(W[T]);D?t.lineTo(E,I):(t.moveTo(E,I),D=!0),t.lineTo(E,P)}}t.stroke()}function je(t){let r=Math.abs(t);return r>=1e3?t.toFixed(0):r>=10?t.toFixed(1):r>=1?t.toFixed(2):t.toFixed(3)}function Ye(t,r){let u=new Date(t).toISOString();return r<2*864e5?u.slice(5,16).replace("T"," "):u.slice(5,10)}function Ue(t,r,u){return{left:r.l*u,top:r.t*u,right:t.width-r.r*u,bottom:t.height-r.b*u}}function Ge(t,r,u,e,d,i,p){let s=Ue(r,u,e),m=Math.max(s.left,Math.min(d(i),s.right));m<=s.left+.5||(t.save(),t.fillStyle="rgba(17,15,13,0.42)",t.fillRect(s.left,s.top,m-s.left,s.bottom-s.top),t.strokeStyle=R(O("--faint"),.7),t.lineWidth=1*e,t.setLineDash([4*e,4*e]),t.beginPath(),t.moveTo(m,s.top),t.lineTo(m,s.bottom),t.stroke(),t.setLineDash([]),t.fillStyle=R(O("--faint"),.95),t.font=`${10*e}px ui-monospace, monospace`,t.textAlign="left",t.textBaseline="top",t.fillText(p,m+6*e,s.top+5*e),t.restore())}function Ve(t,r,u,e,d,i,p){let s=Ue(r,u,e),m=5*e;t.save();for(let x=0;x<i.length;x++){let f=i[x],k=d(f.t);if(k<s.left-1||k>s.right+1)continue;let z=p(f.kind);t.strokeStyle=R(z,.45),t.lineWidth=1*e,t.beginPath(),t.moveTo(k,s.top),t.lineTo(k,s.bottom),t.stroke(),t.fillStyle=z,t.beginPath(),t.moveTo(k-m,s.top),t.lineTo(k+m,s.top),t.lineTo(k,s.top+m*1.4),t.closePath(),t.fill()}t.restore()}var rt={mad:1,zscore:2,iqr:4};function it(t,r){let u=t.seasonalityData;if(!u||u.length===0)return 0;let e=0;for(let d of r){let i=new Set;for(let p of u)i.add(d.map(s=>{var m;return String((m=p==null?void 0:p[s])!=null?m:"")}).join("|"));e=Math.max(e,i.size)}return e}function Ke(t,r){let u=t.timestamps.length,e=Math.max(r.minSamples,rt[r.type]);if(r.smoothing==="sma"&&(e=Math.max(e,r.smoothingWindow-1)),r.smoothing==="ema"&&(e=Math.max(e,Math.ceil(5/r.smoothingAlpha))),r.inputType!=="values"&&(e=Math.max(e,1)),r.seasonalityComponents!==null&&r.seasonalityComponents.length>0&&Array.isArray(t.seasonalityData)&&t.seasonalityData.length>0){let i=it(t,r.seasonalityComponents);if(i>0){let p=r.minSamplesPerGroup*i;r.windowSize>=p&&(e=Math.max(e,p))}}return Math.min(e,u)}var C={l:52,r:14,t:14,b:26},Ie=46,Xe=10,st=13,te=Number.isFinite,ce=1e3,ue=60*ce,de=60*ue,q=24*de,Oe=[ce,2*ce,5*ce,10*ce,15*ce,30*ce,ue,2*ue,5*ue,10*ue,15*ue,30*ue,de,2*de,3*de,6*de,12*de,q,2*q,3*q,5*q,7*q,14*q];function Je(t,r,u){let e=Math.max(r-t,1);if(e>u*28*q){let s=[1,2,3,6,12,24,36,60,120,240],m=s[s.length-1];for(let A of s)if(e/(A*30.44*q)<=u){m=A;break}let x=new Date(t),f=x.getUTCFullYear(),k=x.getUTCMonth();if(m>=12){let A=m/12;f=Math.floor(f/A)*A,k=0}else k=Math.floor(k/m)*m;let z=[],S=Date.UTC(f,k,1);for(;S<=r;)S>=t&&z.push(S),k+=m,f+=Math.floor(k/12),k%=12,S=Date.UTC(f,k,1);return{ticks:z,step:m*30*q}}let d=Oe[Oe.length-1];for(let s of Oe)if(e/s<=u){d=s;break}let i;if(d%q===0){let s=new Date(t);i=Date.UTC(s.getUTCFullYear(),s.getUTCMonth(),s.getUTCDate());let m=d/q,x=Math.round(i/q);i+=(m-x%m)%m*q}else i=Math.ceil(t/d)*d;let p=[];for(let s=i;s<=r;s+=d)s>=t&&p.push(s);return{ticks:p,step:d}}function Qe(t,r){let u=new Date(t).toISOString();return r>=320*q?u.slice(0,4):r>=26*q?u.slice(0,7):r>=q?u.slice(5,10):r>=de?u.slice(5,16).replace("T"," "):u.slice(5,19).replace("T"," ")}function Ze(t,r={}){let u=t.getContext("2d");if(!u)throw new Error("chart: 2D context unavailable");let e=u,d=!!r.navigable,i=1,p=null,s=-1,m=0,x=0,f=1,k=0,z=1,S=0,A=1,ie="";function W(){i=Be(t)}let N=()=>d?(Xe+Ie)*i:0,D=()=>t.width-(C.l+C.r)*i,T=()=>t.height-(C.t+C.b)*i-N(),E=()=>d?S:x,I=()=>d?A:f,P=()=>I()-E()||1,Y=()=>f-x||1,$=n=>C.l*i+(n-E())/P()*D(),G=n=>t.height-C.b*i-N()-(n-k)/(z-k||1)*T(),V=()=>t.height-Ie*i,K=()=>(Ie-st)*i,ne=()=>t.width-(C.l+C.r)*i,Q=n=>C.l*i+(n-x)/Y()*ne(),Ae=n=>V()+K()-(n-k)/(z-k||1)*K(),X=(n,o,a)=>Math.max(o,Math.min(a,n)),oe=()=>{let n=p==null?void 0:p.series,o=n?n.timestamps.length:0,a=o>1?Y()/(o-1):1e3;return Math.max(a*8,1e3)};function J(n,o){let a=o-n,c=oe();if(a<c){let l=(n+o)/2;n=l-c/2,o=l+c/2,a=c}a>=Y()&&(n=x,o=f),n<x&&(o+=x-n,n=x),o>f&&(n-=o-f,o=f),S=X(n,x,f),A=X(o,x,f),re()}let De=n=>{let o=(n-C.l*i)/(D()||1);return E()+X(o,0,1)*P()},se=n=>{let o=(n-C.l*i)/(ne()||1);return x+X(o,0,1)*Y()};function Pe(n){let o=p==null?void 0:p.series;if(!o||o.timestamps.length===0)return-1;let a=(n-C.l*i)/(D()||1),c=E()+a*P(),l=o.timestamps,h=0,y=l.length-1;for(;h<y;){let _=h+y>>1;l[_]<c?h=_+1:y=_}return h>0&&c-l[h-1]<l[h]-c&&(h-=1),h}function Le(n,o){let a=n.timestamps;if(x=a[0],f=a[a.length-1],d){let y=`${a.length}:${x}:${f}`;y!==ie?(ie=y,S=x,A=f):(S=X(S,x,f),A=X(Math.max(A,S+oe()),x,f))}let c=1/0,l=-1/0;for(let y of n.values)te(y)&&(y<c&&(c=y),y>l&&(l=y));for(let y of o)y.scored&&(te(y.lower)&&y.lower<c&&(c=y.lower),te(y.upper)&&y.upper>l&&(l=y.upper));(!te(c)||!te(l))&&(c=0,l=1),l<=c&&(l=c+1);let h=(l-c)*.06;k=c-h,z=l+h}function ae(n,o,a){let c=p.series.timestamps;ze(e,c,n,E(),I(),C.l*i,D(),$,G,o,a,i)}function ge(n,o){let a=[],c=-1;for(let l=Math.max(0,o);l<n.length;l++){let h=n[l];h.scored&&te(h.lower)&&te(h.upper)?c===-1&&(c=l):c!==-1&&(a.push([c,l-1]),c=-1)}return c!==-1&&a.push([c,n.length-1]),a}function Z(){if(m=0,!p||t.width===0||t.height===0)return;let{series:n,scored:o,params:a,alerts:c}=p;if(n.timestamps.length===0){e.fillStyle=O("--term-bg"),e.fillRect(0,0,t.width,t.height);return}let l=O("--clay"),h=O("--st-anomaly"),y=O("--faint"),_=O("--muted");e.fillStyle=O("--term-bg"),e.fillRect(0,0,t.width,t.height),e.font=`${11*i}px ui-monospace, 'JetBrains Mono', monospace`,e.textBaseline="middle";for(let g=0;g<=4;g++){let v=k+(z-k)*g/4,w=G(v);e.strokeStyle=R(y,.1),e.lineWidth=1*i,e.beginPath(),e.moveTo(C.l*i,w),e.lineTo(t.width-C.r*i,w),e.stroke(),e.fillStyle=_,e.textAlign="right",e.fillText(je(v),(C.l-8)*i,w)}e.textBaseline="top";let F=t.height-C.b*i-N();if(d){let g=Je(E(),I(),7);for(let v of g.ticks){let w=$(v);e.strokeStyle=R(y,.1),e.lineWidth=1*i,e.beginPath(),e.moveTo(w,C.t*i),e.lineTo(w,F),e.stroke(),e.fillStyle=_,e.textAlign=w<(C.l+24)*i?"left":w>t.width-(C.r+24)*i?"right":"center",e.fillText(Qe(v,g.step),w,F+7*i)}}else{let g=P();for(let v=0;v<=5;v++){let w=x+g*v/5,U=$(w);e.fillStyle=_,e.textAlign=v===0?"left":v===5?"right":"center",e.fillText(Ye(w,g),U,F+7*i)}}e.save(),e.beginPath(),e.rect(C.l*i,C.t*i,D(),T()),e.clip();let B=o.length,M=Math.min(Ke(n,a),B),L=M<B?n.timestamps[M]:void 0,j=ge(o,M);e.fillStyle=R(l,.13);for(let[g,v]of j){e.beginPath(),e.moveTo($(o[g].timestamp),G(o[g].upper));for(let w=g+1;w<=v;w++)e.lineTo($(o[w].timestamp),G(o[w].upper));for(let w=v;w>=g;w--)e.lineTo($(o[w].timestamp),G(o[w].lower));e.closePath(),e.fill()}e.strokeStyle=R(l,.4),e.lineWidth=1*i;for(let[g,v]of j)for(let w of["upper","lower"]){e.beginPath();for(let U=g;U<=v;U++){let Ce=$(o[U].timestamp),Te=G(o[U][w]);U===g?e.moveTo(Ce,Te):e.lineTo(Ce,Te)}e.stroke()}e.strokeStyle=R(y,.55),e.lineWidth=1*i,e.setLineDash([3*i,3*i]);for(let[g,v]of j){e.beginPath();for(let w=g;w<=v;w++){let U=o[w].center;if(!te(U))continue;let Ce=$(o[w].timestamp),Te=G(U);w===g?e.moveTo(Ce,Te):e.lineTo(Ce,Te)}e.stroke()}if(e.setLineDash([]),a.smoothing!=="none"){ae(n.values,R(l,.28),1.25);let g=o.map(v=>v.processedValue);ae(g,l,1.6)}else ae(n.values,l,1.5);for(let g=M;g<B;g++){let v=o[g];if(!v.scored||!te(v.value))continue;let w=$(v.timestamp),U=G(v.value);v.isAnomaly?(e.fillStyle=R(h,.18),e.beginPath(),e.arc(w,U,6*i,0,Math.PI*2),e.fill(),e.fillStyle=h,e.beginPath(),e.arc(w,U,3*i,0,Math.PI*2),e.fill()):n.truthAnomaly[g]&&(e.strokeStyle=R(_,.7),e.lineWidth=1.25*i,e.beginPath(),e.arc(w,U,3.5*i,0,Math.PI*2),e.stroke())}L!==void 0&&Ge(e,t,C,i,$,L,"detection at full power \u2192"),s>=0&&s<o.length&&me(s,a.windowSize,o,n,y),c&&c.length&&Ve(e,t,C,i,$,c,g=>g==="anomaly"?O("--st-anomaly"):g==="recovery"?O("--st-recovery"):O("--st-nodata")),e.restore(),d&&ve(n,c,l,y,_)}function ve(n,o,a,c,l){let h=V(),y=h+K(),_=C.l*i,F=t.width-C.r*i,B=Je(x,f,5);e.save(),e.beginPath(),e.rect(_,h,ne(),K()),e.clip(),e.strokeStyle=R(c,.1),e.lineWidth=1*i;for(let g of B.ticks){let v=Q(g);e.beginPath(),e.moveTo(v,h),e.lineTo(v,y),e.stroke()}ze(e,n.timestamps,n.values,x,f,_,ne(),Q,Ae,R(a,.7),1.1,i),e.restore();let M=Q(S),L=Q(A);if(e.fillStyle="rgba(27,25,22,0.55)",e.fillRect(_,h,M-_,K()),e.fillRect(L,h,F-L,K()),o&&o.length){let g=O("--st-anomaly");e.fillStyle=R(g,.85);for(let v of o){let w=Q(v.t);e.fillRect(w-1*i,h,2*i,K())}}e.fillStyle="rgba(245,241,232,0.06)",e.fillRect(M,h,L-M,K()),e.strokeStyle=a,e.lineWidth=1.5*i,e.strokeRect(M,h+1,L-M,K()-2),e.fillStyle=a;let j=h+K()/2-8*i;e.fillRect(M-2*i,j,4*i,16*i),e.fillRect(L-2*i,j,4*i,16*i),e.font=`${10*i}px ui-monospace, monospace`,e.textBaseline="top",e.fillStyle=l;for(let g of B.ticks){let v=Q(g);e.strokeStyle=R(c,.25),e.lineWidth=1*i,e.beginPath(),e.moveTo(v,y),e.lineTo(v,y+3*i),e.stroke(),e.textAlign=v<(C.l+26)*i?"left":v>t.width-(C.r+26)*i?"right":"center",e.fillText(Qe(g,B.step),v,y+5*i)}}function me(n,o,a,c,l){let h=c.timestamps,y=Math.max(0,n-o),_=n-1,F=C.t*i,B=T();if(_>=y){let j=c.intervalSeconds*1e3/P()*D()*.5,g=$(h[y])-j,v=$(h[_])+j;e.fillStyle="rgba(255,255,255,0.05)",e.fillRect(g,F,v-g,B),e.strokeStyle=R(l,.5),e.lineWidth=1*i,e.beginPath(),e.moveTo(g,F),e.lineTo(g,F+B),e.moveTo(v,F),e.lineTo(v,F+B),e.stroke()}let M=$(h[n]);e.strokeStyle=R(l,.85),e.lineWidth=1*i,e.setLineDash([2*i,2*i]),e.beginPath(),e.moveTo(M,F),e.lineTo(M,F+B),e.stroke(),e.setLineDash([]);let L=a[n];if(L.scored&&te(L.lower)&&te(L.upper)){let j=5*i;e.strokeStyle=R(O("--clay"),.85),e.lineWidth=1.5*i;for(let g of[L.lower,L.upper]){let v=G(g);e.beginPath(),e.moveTo(M-j,v),e.lineTo(M+j,v),e.stroke()}}if(te(L.value)){let j=G(L.value);e.fillStyle=O("--term-bg"),e.beginPath(),e.arc(M,j,4*i,0,Math.PI*2),e.fill(),e.strokeStyle=L.isAnomaly?O("--st-anomaly"):O("--clay"),e.lineWidth=2*i,e.beginPath(),e.arc(M,j,4*i,0,Math.PI*2),e.stroke()}}function re(){m===0&&(m=requestAnimationFrame(Z))}function fe(){var a;if(!r.onHover||!p)return;if(s<0){r.onHover(null);return}let n=(a=p.scored[s])!=null?a:null,o={index:s,point:n,windowStart:Math.max(0,s-p.params.windowSize),windowEnd:s-1};r.onHover(o)}let ee=null,H=null,le=n=>{let o=t.getBoundingClientRect();return{x:(n.clientX-o.left)*i,y:(n.clientY-o.top)*i}},xe=n=>d&&n>=V(),ye=n=>{let o=Q(S),a=Q(A),c=8*i;return Math.abs(n-o)<=c?"l":Math.abs(n-a)<=c?"r":n>o&&n<a?"move":"out"};function pe(n){if(!p)return;let{x:o,y:a}=le(n);if(ee||H)return;if(xe(a)){s!==-1&&(s=-1,fe(),re());let l=ye(o);t.style.cursor=l==="l"||l==="r"?"ew-resize":l==="move"?"grab":"pointer";return}d&&(t.style.cursor="grab");let c=Pe(o);c!==s&&(s=c,fe(),re())}function we(){s!==-1&&(s=-1,fe(),re())}function ke(n){if(!d||!p)return;let{x:o,y:a}=le(n);if(a>=V()){let c=ye(o);if(c==="l")H={type:"l",grab:0,vMin:S,vMax:A};else if(c==="r")H={type:"r",grab:0,vMin:S,vMax:A};else if(c==="move")H={type:"move",grab:se(o),vMin:S,vMax:A};else{let l=se(o),h=P();J(l-h/2,l+h/2),H={type:"move",grab:l,vMin:S,vMax:A}}t.style.cursor="grabbing",n.preventDefault()}else a>C.t*i&&a<V()-Xe*i&&(ee={x:o,vMin:S,vMax:A},t.style.cursor="grabbing",n.preventDefault())}function Ee(n){if(!p)return;let{x:o}=le(n);if(ee){let a=(o-ee.x)*(ee.vMax-ee.vMin)/(D()||1);J(ee.vMin-a,ee.vMax-a)}else if(H){let a=se(o);H.type==="l"?J(Math.min(a,A-oe()),A):H.type==="r"?J(S,Math.max(a,S+oe())):J(H.vMin+(a-H.grab),H.vMax+(a-H.grab))}}function he(){(ee||H)&&(ee=null,H=null,t.style.cursor="grab")}function be(n){if(!d||!p)return;n.preventDefault();let{x:o,y:a}=le(n),c=X(P()*Math.pow(1.0015,n.deltaY),oe(),Y());if(a>=V()){let l=se(o);J(l-c/2,l+c/2)}else{let l=De(o),h=(l-S)/(P()||1);J(l-h*c,l-h*c+c)}}function Se(){d&&J(x,f)}t.addEventListener("mousemove",pe),t.addEventListener("mouseleave",we),d&&(t.addEventListener("mousedown",ke),t.addEventListener("wheel",be,{passive:!1}),t.addEventListener("dblclick",Se),window.addEventListener("mousemove",Ee),window.addEventListener("mouseup",he));function Me(n){p=n,Le(n.series,n.scored),s>=n.series.timestamps.length&&(s=-1),re()}function Ne(){W(),p&&(Le(p.series,p.scored),re())}function _e(){t.removeEventListener("mousemove",pe),t.removeEventListener("mouseleave",we),d&&(t.removeEventListener("mousedown",ke),t.removeEventListener("wheel",be),t.removeEventListener("dblclick",Se),window.removeEventListener("mousemove",Ee),window.removeEventListener("mouseup",he)),m!==0&&cancelAnimationFrame(m),m=0,p=null}return W(),{render:Me,resize:Ne,destroy:_e}}var at={mad:3,zscore:3,iqr:1.5},lt={mad:10,zscore:3,iqr:4},ct="dtk-tune";function b(t,r,u){let e=document.createElement(t);return r&&(e.className=r),u!=null&&(e.textContent=u),e}function $e(t,r){let u=b("label","dtk-ctl-label",t);if(r){u.title=r;let e=b("span","dtk-ctl-info","\u24D8");e.title=r,u.appendChild(document.createTextNode(" ")),u.appendChild(e)}return u}function We(t,r,u,e,d){let i=b("div","dtk-ctl");i.appendChild($e(t,d));let p=b("div","dtk-seg"),s=u,m=[],x=()=>{m.forEach(f=>f.classList.toggle("on",f.dataset.v===s))};return r.forEach(f=>{let k=b("button","dtk-seg-btn",f.label);k.type="button",k.dataset.v=f.value,k.onclick=()=>{s=f.value,x(),e(s)},m.push(k),p.appendChild(k)}),x(),i.appendChild(p),{row:i,get:()=>s,set:f=>{s=f,x()}}}function Re(t,r,u){var x;let e=b("div","dtk-ctl"),d=b("div","dtk-ctl-head"),i=$e(t,r.hint),p=b("span","dtk-ctl-val"),s=(x=r.fmt)!=null?x:(f=>String(f));d.appendChild(i),d.appendChild(p),e.appendChild(d);let m=b("input","dtk-range");return m.type="range",m.min=String(r.min),m.max=String(r.max),m.step=String(r.step),m.value=String(r.value),p.textContent=s(r.value),m.oninput=()=>{let f=Number(m.value);p.textContent=s(f),u(f)},e.appendChild(m),{row:e,get:()=>Number(m.value),setMax:f=>{m.max=String(f),Number(m.value)>f&&(m.value=String(f),p.textContent=s(f))}}}function tt(t){let r={threshold:t.threshold,window_size:t.windowSize};return t.windowWeights!=="none"&&(r.window_weights=t.windowWeights,t.windowWeights==="exponential"&&t.halfLife!=null&&(r.half_life=t.halfLife)),t.detrend!=="none"&&(r.detrend=t.detrend),t.smoothing!=="none"&&(r.smoothing=t.smoothing),t.inputType!=="values"&&(r.input_type=t.inputType),t.seasonalityComponents&&t.seasonalityComponents.length&&(r.seasonality_components=t.seasonalityComponents,r.min_samples_per_group=t.minSamplesPerGroup),r}function ut(t,r){let u=tt(t),e=[`type: ${t.type}`];for(let[d,i]of Object.entries(u))e.push(`${d}=${typeof i=="object"?JSON.stringify(i):i}`);return e.push(`consecutive_anomalies=${r}`),e.join(" \xB7 ")}function dt(t,r){var Ne,_e;pt(),r.classList.add(ct),r.innerHTML="";let u=b("div","dtk-tune-root");r.appendChild(u);let e=t.points.length,d={timestamps:t.points.map(n=>n.t),values:t.points.map(n=>n.v==null?NaN:n.v),intervalSeconds:t.interval_seconds,truthAnomaly:new Array(e).fill(!1),seasonalityData:t.seasonality_columns.length?t.seasonality:void 0,seasonalityColumns:t.seasonality_columns.length?t.seasonality_columns:void 0},i=d,p=n=>{let o=Math.max(0,e-n);return o<=0?d:{timestamps:d.timestamps.slice(o),values:d.values.slice(o),intervalSeconds:d.intervalSeconds,truthAnomaly:d.truthAnomaly.slice(o),seasonalityData:d.seasonalityData?d.seasonalityData.slice(o):void 0,seasonalityColumns:d.seasonalityColumns}},s=t.detector,m=t.consecutive_anomalies,x=(Ne=s.seasonalityComponents)!=null?Ne:[],f=new Map;x.forEach((n,o)=>n.forEach(a=>f.set(a,o+1)));let k=()=>{let n=0;f.forEach(a=>{a>n&&(n=a)});let o=[];for(let a=1;a<=n;a++){let c=t.seasonality_columns.filter(l=>f.get(l)===a);c.length&&o.push(c)}return o.length?o:null},z=()=>{var n;return{type:ve.get(),threshold:me.get(),windowSize:le.get(),minSamples:s.minSamples,inputType:s.inputType,smoothing:ke.get(),smoothingAlpha:s.smoothingAlpha,smoothingWindow:s.smoothingWindow,windowWeights:xe.get(),halfLife:xe.get()==="exponential"?ye.get():null,detrend:we.get(),seasonalityComponents:k(),minSamplesPerGroup:(n=lt[ve.get()])!=null?n:s.minSamplesPerGroup,consecutiveAnomalies:m}},S=b("div","dtk-tune-header"),A=b("div","dtk-tune-titlerow");A.appendChild(b("h1","dtk-tune-title",t.metric));let ie=b("span","dtk-tune-badge",t.save_url?"manual tuning":"preview");A.appendChild(ie),S.appendChild(A);let W=t.project?`${t.project} \xB7 `:"";S.appendChild(b("div","dtk-tune-sub",`${W}${e} points \xB7 ${ft(t.interval_seconds)} grid`)),t.description&&S.appendChild(b("div","dtk-tune-desc",t.description)),u.appendChild(S);let N=b("div","dtk-tune-grid"),D=b("div","dtk-tune-controls"),T=b("div","dtk-tune-main");N.appendChild(D),N.appendChild(T),u.appendChild(N);let E=b("div","dtk-tune-trim"),I=b("div","dtk-tune-trim-head");I.appendChild($e("Points shown","Trim the active sample to the most-recent N points. Fewer points recompute faster (cost grows with points \xD7 window) and make a shorter period easier to read \u2014 handy once you can see a smaller window/period is enough."));let P=b("span","dtk-tune-trim-val");I.appendChild(P),E.appendChild(I);let Y=b("input","dtk-range");Y.type="range",Y.min=String(Math.min(e,200)),Y.max=String(e),Y.step=String(Math.max(1,Math.round(e/200))),Y.value=String(e),E.appendChild(Y),T.appendChild(E);let $=b("div","dtk-tune-chart"),G=b("canvas");$.appendChild(G);let V=b("div","dtk-tune-spin");V.appendChild(b("span","dtk-spin-ring")),V.appendChild(b("span","dtk-spin-txt","computing\u2026")),$.appendChild(V),T.appendChild($);let K=b("div","dtk-tune-legend"),ne=(n,o,a)=>{let c=b("span","dtk-leg-item");c.title=a,c.appendChild(b("span",`dtk-leg-sw ${n}`)),c.appendChild(b("span","dtk-leg-txt",o)),K.appendChild(c)};ne("line","metric","The metric value over time."),ne("band","expected range","The detector's confidence band \u2014 values inside it read as normal."),ne("center","band center","The expected value at the middle of the band."),ne("dot","anomaly","A point the detector flagged as anomalous (outside the band)."),ne("alert","alert","Where an alert fired \u2014 enough consecutive anomalies to meet the rule."),T.appendChild(K);let Q=b("div","dtk-tune-readout");T.appendChild(Q);let Ae=Ze(G,{navigable:!0,onHover:n=>{if(!n||!n.point||!n.point.scored){Q.textContent="";return}let o=n.point;Q.textContent=`t=${mt(o.timestamp)} value=${qe(o.value)} band=[${qe(o.lower)}, ${qe(o.upper)}]`+(o.isAnomaly?` \u26A0 ${o.direction} (sev ${o.severity.toFixed(2)})`:"")}}),X=new Worker(URL.createObjectURL(new Blob([`"use strict";(()=>{var X={mad:1,zscore:2,iqr:4};function T(n){let e=0;for(let t of n)e+=t;return e}function ie(n){let e=n.map((t,r)=>r);return e.sort((t,r)=>n[t]<n[r]?-1:n[t]>n[r]?1:t-r),e}function se(n,e,t){let r=e.length;if(r===0)return NaN;if(n<=e[0])return t[0];if(n>=e[r-1])return t[r-1];for(let i=1;i<r;i++)if(n<=e[i]){let o=e[i-1],c=e[i],u=t[i-1],s=t[i];if(c===o)return u;let d=(n-o)/(c-o);return u+d*(s-u)}return t[r-1]}function F(n,e,t){let r=ie(n),i=r.map(b=>n[b]),o=r.map(b=>e[b]),c=T(o),u=new Array(o.length),s=0;for(let b=0;b<o.length;b++)s+=o[b],u[b]=(s-.5*o[b])/c;let d=t/100;return se(d,u,i)}function S(n,e){return F(n,e,50)}function ce(n,e,t){let r=t===void 0?S(n,e):t,i=n.map(o=>Math.abs(o-r));return S(i,e)}function ue(n,e){let t=T(e),r=0;for(let i=0;i<n.length;i++)r+=n[i]*(e[i]/t);return r}function me(n,e,t,r=0){let i=T(e),o=e.map(s=>s/i),c=t===void 0?T(n.map((s,d)=>s*o[d])):t,u=0;for(let s=0;s<n.length;s++)u+=o[s]*(n[s]-c)**2;if(r===1){let s=1-T(o.map(d=>d*d));s>1e-12&&(u/=s)}return Math.sqrt(u)}function le(n,e){return e.smoothing==="none"?n.slice():e.smoothing==="ema"?ae(n,e.smoothingAlpha):fe(n,e.smoothingWindow)}function ae(n,e){let t=n.length,r=new Array(t).fill(NaN);if(t===0)return r;let i=-1;for(let o=0;o<t;o++)if(!Number.isNaN(n[o])){i=o;break}if(i===-1)return r;r[i]=n[i];for(let o=i+1;o<t;o++)Number.isNaN(n[o])?r[o]=r[o-1]:r[o]=e*n[o]+(1-e)*r[o-1];return r}function fe(n,e){let t=n.length,r=new Array(t).fill(NaN);for(let i=0;i<t;i++){let o=Math.max(0,i-e+1),c=0,u=0;for(let s=o;s<=i;s++)Number.isNaN(n[s])||(c+=n[s],u+=1);r[i]=u>0?c/u:NaN}return r}function de(n,e){let t=n.length;if(e.inputType==="values")return n.slice();let r=new Array(t).fill(NaN);for(let i=1;i<t;i++){let o=n[i-1],c=n[i];e.inputType==="changes"?r[i]=(c-o)/o:e.inputType==="absolute_changes"?r[i]=c-o:r[i]=Math.log(c+1)-Math.log(o+1)}return r}function be(n,e){return n.halfLife!==null?n.halfLife:Math.max(n.windowSize/20,e/2,1)}function pe(n,e){if(n.windowWeights==="none")return null;let t=n.windowSize,r=new Array(t);if(n.windowWeights==="exponential"){let i=be(n,e);for(let o=1;o<=t;o++){let c=Math.min(o/i,1e3);r[o-1]=Math.pow(.5,c)}return r}for(let i=1;i<=t;i++)r[i-1]=(t+1-i)/t;return r}function K(n,e){return e===null?n.map(()=>1):n.map(t=>e[t-1])}function ge(n){let e=n[0];for(let t of n)t>e&&(e=t);return e}function ye(n){let e=n[0];for(let t of n)t<e&&(e=t);return e}function he(n,e,t){if(n.length<4)return 0;let r=(ge(e)+ye(e))/2,i=e.map(l=>l>r),o=i.map(l=>!l),c=0,u=0;for(let l=0;l<e.length;l++)i[l]?c++:u++;if(c<2||u<2)return 0;let s=(l,N)=>N.filter((L,y)=>l[y]),d=s(o,n),b=s(i,n),k=s(o,e),C=s(i,e),g=s(o,t),f=s(i,t),q=S(d,g),p=S(b,f),w=S(k,g),M=S(C,f);return M===w?0:(q-p)/(M-w)}var Se={mad:[["median","center"],["mad","spread"]],zscore:[["mean","center"],["std","spread"]],iqr:[["q1","center"],["q3","center"],["iqr","spread"]]};function Q(n,e,t){if(n==="mad"){let o=S(e,t);return{median:o,mad:ce(e,t,o)}}if(n==="zscore"){let o=ue(e,t);return{mean:o,std:me(e,t,o,1)}}let r=F(e,t,25),i=F(e,t,75);return{q1:r,q3:i,iqr:i-r}}function we(n,e,t){if(n==="mad"){if(e.mad===0)return[e.median-1e-10,e.median+1e-10];let r=t*1.4826*e.mad;return[e.median-r,e.median+r]}return n==="zscore"?e.std===0?[e.mean-1e-10,e.mean+1e-10]:[e.mean-t*e.std,e.mean+t*e.std]:e.iqr===0?[e.q1-1e-10,e.q3+1e-10]:[e.q1-t*e.iqr,e.q3+t*e.iqr]}function Me(n,e,t){if(n==="mad"){let r=1.4826*e.mad;return r>0?t/r:1/0}return n==="zscore"?e.std>0?t/e.std:1/0:e.iqr>0?t/e.iqr:1/0}function Ne(n,e){return n==="mad"?e.median:n==="zscore"?e.mean:(e.q1+e.q3)/2}function U(n,e,t,r,i){return{index:n,timestamp:e,value:t,processedValue:r,scored:!1,isAnomaly:!1,lower:NaN,upper:NaN,center:NaN,direction:null,severity:0,reason:i}}function Y(n,e){let{type:t}=e,r=Math.max(e.minSamples,X[t]),i=Se[t],{timestamps:o,values:c}=n,u=o.length,s=le(c,e),d=de(s,e),b=e.seasonalityComponents!==null&&e.seasonalityComponents.length>0&&Array.isArray(n.seasonalityData)&&n.seasonalityData.length>0,k=n.seasonalityData,C=pe(e,r),g=[];for(let f=0;f<u;f++){let q=c[f],p=d[f],w=o[f];if(Number.isNaN(p)){g.push(U(f,w,q,p,"missing_data"));continue}let M=Math.max(0,f-e.windowSize),l=f-M,N=d.slice(M,f),L=N.map(m=>!Number.isNaN(m)),y=[];for(let m=0;m<N.length;m++)L[m]&&y.push(N[m]);if(y.length<r){g.push(U(f,w,q,p,"insufficient_data"));continue}let O=new Array(l);for(let m=0;m<l;m++)O[m]=l-m;let z=[];for(let m=0;m<l;m++)L[m]&&z.push(O[m]);let V=K(z,C),P=0;e.detrend==="linear"&&(P=he(y,z,V));let $=P!==0?y.map((m,W)=>m+P*z[W]):y,G=Q(t,$,V),I={...G};if(b&&k){let m=k[f];for(let W of e.seasonalityComponents){let J=new Array(l).fill(!0);for(let a=0;a<l;a++){let D=k[M+a],x=!0;for(let j of W)if(!D||D[j]!==(m==null?void 0:m[j])){x=!1;break}J[a]=x}let _=[],E=[];for(let a=0;a<l;a++)L[a]&&J[a]&&(_.push(N[a]),E.push(O[a]));if(_.length<e.minSamplesPerGroup)continue;let ne=K(E,C),te=P!==0?_.map((a,D)=>a+P*E[D]):_,re=Q(t,te,ne);for(let[a,D]of i){let x=G[a],oe=(D==="spread"?x>0:x!==0)?re[a]/x:1;I[a]*=oe}}}let[h,A]=we(t,I,e.threshold);h>A&&([h,A]=[A,h]);let H=p<h||p>A,R=null,B=0;if(H){let m;p<h?(R="below",m=h-p):(R="above",m=p-A),B=Me(t,I,m)}let ee=Ne(t,I);g.push({index:f,timestamp:w,value:q,processedValue:p,scored:!0,isAnomaly:H,lower:h,upper:A,center:ee,direction:R,severity:B,reason:"ok"})}return g}function Ae(n,e){let t=n.seasonalityData;if(!t||t.length===0)return 0;let r=0;for(let i of e){let o=new Set;for(let c of t)o.add(i.map(u=>{var s;return String((s=c==null?void 0:c[u])!=null?s:"")}).join("|"));r=Math.max(r,o.size)}return r}function Z(n,e){let t=n.timestamps.length,r=Math.max(e.minSamples,X[e.type]);if(e.smoothing==="sma"&&(r=Math.max(r,e.smoothingWindow-1)),e.smoothing==="ema"&&(r=Math.max(r,Math.ceil(5/e.smoothingAlpha))),e.inputType!=="values"&&(r=Math.max(r,1)),e.seasonalityComponents!==null&&e.seasonalityComponents.length>0&&Array.isArray(n.seasonalityData)&&n.seasonalityData.length>0){let o=Ae(n,e.seasonalityComponents);if(o>0){let c=e.minSamplesPerGroup*o;e.windowSize>=c&&(r=Math.max(r,c))}}return Math.min(r,t)}var v=null;function De(n,e,t){let r=[],i=0;for(let o=0;o<n.length;o++){if(!(n[o].scored&&n[o].isAnomaly)){i=0;continue}let u=o>0&&n[o-1].scored&&n[o-1].isAnomaly,s=o>0&&n[o].timestamp-n[o-1].timestamp===e;i=u&&s?i+1:1,i===t&&r.push(o)}return r}self.onmessage=n=>{let e=n.data;if(e.type==="series"){v=e.series;return}if(e.type==="run"&&v){let t=e.params,r=Y(v,t),i=v.intervalSeconds*1e3,o=De(r,i,t.consecutiveAnomalies),c=Z(v,t),u=0;for(let s of r)s.scored&&s.isAnomaly&&u++;self.postMessage({type:"result",id:e.id,scored:r,fires:o,eff:c,flagged:u})}};})();
|
|
2
|
+
`],{type:"text/javascript"})));X.postMessage({type:"series",series:i});let oe=0,J=null;X.onmessage=n=>{let o=n.data;if(o.type!=="result"||o.id!==oe||!J)return;V.classList.remove("on");let a=J,c=o.fires.map(l=>({t:i.timestamps[l],kind:"anomaly"}));Ae.render({series:i,scored:o.scored,params:a,alerts:c}),he.textContent=`${o.flagged} flagged \xB7 ${o.fires.length} alert${o.fires.length===1?"":"s"} \xB7 warm-up ${o.eff} pts`,Se.textContent=ut(a,m)},X.onerror=()=>{V.classList.remove("on"),he.textContent="recompute failed \u2014 see the browser console"};let De=()=>{J=z(),oe+=1,V.classList.add("on"),X.postMessage({type:"run",id:oe,params:J})},se=n=>n>1?Fe(d.timestamps[e-1]-d.timestamps[e-n]):"\u2014",Pe=n=>{P.textContent=n>=e?`${e} pts \xB7 full (${se(e)})`:`${n} pts \xB7 ${se(n)}`};Pe(e);function Le(n){i=p(n),X.postMessage({type:"series",series:i}),Z()}let ae=0;Y.oninput=()=>{let n=Number(Y.value);Pe(n),ae&&window.clearTimeout(ae),ae=window.setTimeout(()=>Le(n),200)};let ge=0,Z=()=>{ge&&window.clearTimeout(ge),ge=window.setTimeout(De,130)},ve=We("Detector",[{label:"MAD",value:"mad"},{label:"Z-Score",value:"zscore"},{label:"IQR",value:"iqr"}],s.type,n=>{var o;ee((o=at[n])!=null?o:3),Z()},"The statistic used for the center/spread of the band: MAD (robust median, default), Z-Score (mean/std) or IQR (quartiles). All share the same windowing.");D.appendChild(ve.row);let me=Re("Threshold (\u03C3-equivalent)",{min:.5,max:10,step:.1,value:s.threshold,fmt:n=>n.toFixed(1),hint:"Band half-width in \u03C3-equivalents. Lower = tighter band = more flags; higher = wider band = fewer flags."},Z);D.appendChild(me.row);let re=me.row.querySelector("input"),fe=me.row.querySelector(".dtk-ctl-val"),ee=n=>{re&&(re.value=String(n)),fe&&(fe.textContent=n.toFixed(1))},H=Math.max(50,Math.min(2e3,Math.floor(e/2))),le=Re("Window size (points)",{min:10,max:H,step:5,value:Math.min(s.windowSize,H),fmt:n=>`${n} \xB7 ${Fe(n*t.interval_seconds*1e3)}`,hint:"How many trailing points form the baseline window for each scored point. Larger = steadier baseline (more history); smaller = adapts faster to shifts."},Z);D.appendChild(le.row);let xe=We("Recency weighting",[{label:"none",value:"none"},{label:"exponential",value:"exponential"},{label:"linear",value:"linear"}],s.windowWeights,n=>{pe.style.display=n==="exponential"?"":"none",Z()},"Weight recent points in the window more heavily: none (flat), exponential (half-life decay) or linear. Helps the baseline track a drifting level.");D.appendChild(xe.row);let ye=Re("Half-life (points)",{min:1,max:H,step:1,value:(_e=s.halfLife)!=null?_e:Math.max(5,Math.round(s.windowSize/20)),fmt:n=>`${n} \xB7 ${Fe(n*t.interval_seconds*1e3)}`,hint:"Exponential weighting only: the age (in points) at which a point counts half as much as the newest. Smaller = faster decay = fresher baseline."},Z),pe=ye.row;pe.style.display=s.windowWeights==="exponential"?"":"none",D.appendChild(pe);let we=We("Detrend",[{label:"none",value:"none"},{label:"linear",value:"linear"}],s.detrend,Z,"Remove a robust linear trend from each window before computing the band, so a steadily rising/falling metric is not flagged for the trend itself.");D.appendChild(we.row);let ke=We("Smoothing",[{label:"none",value:"none"},{label:"EMA",value:"ema"},{label:"SMA",value:"sma"}],s.smoothing,Z,"Smooth the series before detection (EMA or SMA) so single-point jitter does not flag. The detector judges the smoothed line; the raw values show as a faint ghost.");if(D.appendChild(ke.row),t.seasonality_columns.length){let n=t.seasonality_columns,o=b("div","dtk-ctl");o.appendChild($e("Seasonality groups","Condition the band on seasonal keys. Pick a group per column: columns in the SAME group are combined into one key (e.g. dow\xD7hour); separate groups each apply their own correction. Off = ignore that column."));let a=Math.min(n.length,6),c=[{label:"\u2014",value:"0"}];for(let l=1;l<=a;l++)c.push({label:`G${l}`,value:String(l)});n.forEach(l=>{let h=b("div","dtk-season-row");h.appendChild(b("span","dtk-season-col",l));let y=b("div","dtk-seg dtk-season-seg"),_=[],F=()=>{var M;return(M=f.get(l))!=null?M:0},B=()=>_.forEach(M=>M.classList.toggle("on",Number(M.dataset.v)===F()));c.forEach(M=>{let L=b("button","dtk-seg-btn",M.label);L.type="button",L.dataset.v=M.value,L.title=M.value==="0"?`ignore ${l}`:`put ${l} in group ${M.value}`,L.onclick=()=>{f.set(l,Number(M.value)),B(),Z()},_.push(L),y.appendChild(L)}),B(),h.appendChild(y),o.appendChild(h)}),D.appendChild(o)}let Ee=Re("Alert: consecutive anomalies",{min:1,max:10,step:1,value:m,fmt:n=>String(n),hint:"How many anomalies in a row are required before an alert fires. Higher = fewer, more-confident alerts (the \u25BC markers on the chart)."},n=>{m=n,Z()});D.appendChild(Ee.row);let he=b("div","dtk-tune-stat");T.appendChild(he);let be=b("div","dtk-tune-cfg");be.appendChild(b("span","dtk-tune-cfg-k","// effective config"));let Se=b("code","dtk-tune-cfg-v");if(be.appendChild(Se),T.appendChild(be),t.save_url){let n=b("div","dtk-tune-apply"),o=b("button","dtk-apply-btn","Apply to metric");o.type="button",o.title="Write this detector config back into the metric YAML (the previous version is archived under metrics/.history/). Trimming the sample does not change what is written.";let a=b("span","dtk-apply-msg");o.onclick=()=>{let c=z();o.disabled=!0,a.className="dtk-apply-msg info",a.textContent="Applying\u2026",fetch(t.save_url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({detector:{type:c.type,params:tt(c)},consecutive_anomalies:m})}).then(l=>l.ok?l.json():l.text().then(h=>{throw new Error(h||`HTTP ${l.status}`)})).then(l=>{var h;a.className="dtk-apply-msg ok",a.textContent=`Applied \u2192 ${(h=l.saved)!=null?h:"metric"} (previous archived). You can close this tab.`}).catch(l=>{o.disabled=!1,a.className="dtk-apply-msg err",a.textContent=`Apply failed: ${l.message}`})},n.appendChild(o),n.appendChild(a),T.appendChild(n)}else T.appendChild(b("div","dtk-tune-note","Static preview \u2014 sliders recompute live, but there is no write-back. Run `dtk tune` (without --no-serve) to apply a config."));De();let Me=0;window.addEventListener("resize",()=>{Me&&cancelAnimationFrame(Me),Me=requestAnimationFrame(()=>Ae.resize())})}function qe(t){if(!Number.isFinite(t))return"\u2014";let r=Math.abs(t);return r!==0&&(r<.01||r>=1e6)?t.toExponential(2):Number(t.toFixed(r<1?4:2)).toString()}function mt(t){return new Date(t).toISOString().slice(0,16).replace("T"," ")}function Fe(t){let r=Math.round(t/6e4);if(r<60)return`${r}m`;let u=Math.floor(r/60);if(u<24)return`${u}h`;let e=Math.floor(u/24),d=u%24;return d?`${e}d ${d}h`:`${e}d`}function ft(t){return t%86400===0?`${t/86400}d`:t%3600===0?`${t/3600}h`:t%60===0?`${t/60}min`:`${t}s`}var et=!1;function pt(){if(et)return;et=!0;let t=`
|
|
3
3
|
.dtk-tune{--c:#d15b36;--c7:#b4471f;--ink:#1b1916;--muted:#6e675b;--faint:#9a9384;
|
|
4
4
|
--paper:#f5f1e8;--surface:#fbf9f3;--border:#e6e0d4;--green:#2e9e73;--anom:#d63232;
|
|
5
5
|
--mono:'JetBrains Mono',ui-monospace,Menlo,monospace;
|
|
@@ -77,4 +77,4 @@
|
|
|
77
77
|
overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
78
78
|
.dtk-season-seg{flex:0 0 auto;padding:2px;}
|
|
79
79
|
.dtk-season-seg .dtk-seg-btn{flex:0 0 auto;padding:3px 7px;font-family:var(--mono);font-size:11px;}
|
|
80
|
-
`,r=document.createElement("style");r.textContent=t,document.head.appendChild(r)}window.__DTK_TUNE__={render:
|
|
80
|
+
`,r=document.createElement("style");r.textContent=t,document.head.appendChild(r)}window.__DTK_TUNE__={render:dt};})();
|
|
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
|
{detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md
RENAMED
|
File without changes
|
{detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/skills/dtk-feedback/SKILL.md
RENAMED
|
File without changes
|
{detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md
RENAMED
|
File without changes
|
{detectkit-0.31.0 → detectkit-0.31.1}/detectkit/cli/assets/claude/skills/dtk-setup-project/SKILL.md
RENAMED
|
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
|
|
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
|