|
|
|
@ -3,6 +3,7 @@ use crate::services::{analytic_service::types::{self, HSR}, metric_service::Metr
|
|
|
|
|
use super::types::{AnalyticUnit, AnalyticUnitConfig, AnomalyConfig, LearningResult}; |
|
|
|
|
|
|
|
|
|
use async_trait::async_trait; |
|
|
|
|
use subbeat::metric::MetricResult; |
|
|
|
|
|
|
|
|
|
// TODO: move to config
|
|
|
|
|
const DETECTION_STEP: u64 = 10; |
|
|
|
@ -15,6 +16,30 @@ impl AnomalyAnalyticUnit {
|
|
|
|
|
pub fn new(config: AnomalyConfig) -> AnomalyAnalyticUnit { |
|
|
|
|
AnomalyAnalyticUnit { config } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn get_hsr_from_metric_result(&self, mr: &MetricResult) -> anyhow::Result<HSR> { |
|
|
|
|
if mr.data.keys().len() == 0 { |
|
|
|
|
return Ok(HSR::ConfidenceTimeSerie(Vec::new())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let k = mr.data.keys().nth(0).unwrap(); |
|
|
|
|
let ts = mr.data[k].clone(); |
|
|
|
|
|
|
|
|
|
if ts.len() == 0 { |
|
|
|
|
return Ok(HSR::ConfidenceTimeSerie(Vec::new())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let mut sts = Vec::new(); |
|
|
|
|
sts.push((ts[0].0, ts[0].1, ((ts[0].1 + self.config.confidence, ts[0].1 - self.config.confidence)))); |
|
|
|
|
|
|
|
|
|
for t in 1..ts.len() { |
|
|
|
|
let alpha = self.config.alpha; |
|
|
|
|
let stv = alpha * ts[t].1 + (1.0 - alpha) * sts[t - 1].1; |
|
|
|
|
sts.push((ts[t].0, stv, (stv + self.config.confidence, stv - self.config.confidence))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(HSR::ConfidenceTimeSerie(sts)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[async_trait] |
|
|
|
@ -42,18 +67,43 @@ impl AnalyticUnit for AnomalyAnalyticUnit {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let k = mr.data.keys().nth(0).unwrap(); |
|
|
|
|
let ts = &mr.data[k]; |
|
|
|
|
let ts = mr.data[k].clone(); |
|
|
|
|
|
|
|
|
|
if ts.len() == 0 { |
|
|
|
|
return Ok(Vec::new()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let ct = ts[0]; |
|
|
|
|
let mut result = Vec::new(); |
|
|
|
|
|
|
|
|
|
if let HSR::ConfidenceTimeSerie(hsr) = self.get_hsr_from_metric_result(&mr)? { |
|
|
|
|
|
|
|
|
|
let mut from = None; |
|
|
|
|
|
|
|
|
|
for ((t, _, (u, l)), (t1, rv)) in hsr.iter().zip(ts) { |
|
|
|
|
if *t != t1 { |
|
|
|
|
return Err(anyhow::format_err!("incompatible hsr/ts")) |
|
|
|
|
} |
|
|
|
|
if rv > *u || rv < *l { |
|
|
|
|
if from.is_none() { |
|
|
|
|
from = Some(*t); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if from.is_some() { |
|
|
|
|
result.push((from.unwrap(), *t)); |
|
|
|
|
from = None; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: implement
|
|
|
|
|
// TODO: decide what to do it from is Some() in the end
|
|
|
|
|
return Ok(result); |
|
|
|
|
|
|
|
|
|
Ok(Default::default()) |
|
|
|
|
} else { |
|
|
|
|
return Err(anyhow::format_err!("bad hsr")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: use hsr for learning and detections
|
|
|
|
@ -64,27 +114,6 @@ impl AnalyticUnit for AnomalyAnalyticUnit {
|
|
|
|
|
to: u64, |
|
|
|
|
) -> anyhow::Result<HSR> { |
|
|
|
|
let mr = ms.query(from, to, DETECTION_STEP).await.unwrap(); |
|
|
|
|
|
|
|
|
|
if mr.data.keys().len() == 0 { |
|
|
|
|
return Ok(HSR::TimeSerie(Vec::new())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let k = mr.data.keys().nth(0).unwrap(); |
|
|
|
|
let ts = mr.data[k].clone(); |
|
|
|
|
|
|
|
|
|
if ts.len() == 0 { |
|
|
|
|
return Ok(HSR::TimeSerie(Vec::new())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let mut sts = Vec::new(); |
|
|
|
|
sts.push((ts[0].0, ts[0].1, ((ts[0].1 + self.config.confidence, ts[0].1 - self.config.confidence)))); |
|
|
|
|
|
|
|
|
|
for t in 1..ts.len() { |
|
|
|
|
let alpha = self.config.alpha; |
|
|
|
|
let stv = alpha * ts[t].1 + (1.0 - alpha) * sts[t - 1].1; |
|
|
|
|
sts.push((ts[t].0, stv, (stv + self.config.confidence, stv - self.config.confidence))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(HSR::ConfidenceTimeSerie(sts)) |
|
|
|
|
return self.get_hsr_from_metric_result(&mr); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|