作法:从stddev /平均值计算中排除一行并稍后加入

时间:2018-11-14 19:20:05

标签: kusto azure-data-explorer

因此,我试图找到与按环境和功能分组的机器相比抛出异常的机器。直觉是,整个组的负载和任务类型应该非常相似,因此,如果一台机器抛出更多异常,则可能某种程度上处于不良状态,应该对其进行维修。

这对于大型计算机组相当有效,但是对于较小的计算机组存在一个问题:如果计算机很少,并且其中只有一台抛出很多异常,则可能无法检测到。原因是因为该数据点是常规stddev和该组平均值计算的参数,所以均值和stddev偏向此异常值。

解决方案是以某种方式从计算出的stddev中减去该数据点并得出整个组的平均值,或者计算每个机器/环境/功能组合的stddev并得出平均值(从stddev /平均值计算),而不仅仅是按环境/功能组。

这是根据环境/功能执行的当前代码。是否有一个优雅的解决方案来扩展它以执行机器/环境/功能?

// Find sick machines
let SickMachinesAt = (AtTime:datetime , TimeWindow:timespan = 1h, Sigmas:double = 3.0, MinimumExceptionsToTrigger:int = 10) {
    // These are the exceptions we are looking at (time window constrained)
    let Exceptions = exception
    | where EventInfo_Time between((AtTime - TimeWindow ) .. AtTime);
    // Calculate mean and stddev for each bin of environmentName + machineFunction
    let MeanAndStdDev = Exceptions
    | summarize count() by environmentName, machineFunction, machineName
    | summarize avg(count_), stdev(count_) by environmentName, machineFunction
    | order by environmentName, machineFunction;
    let MachinesWithMeanAndStdDev = Exceptions
    | summarize count() by environmentName, machineFunction, machineName
    | join kind=fullouter MeanAndStdDev on environmentName, machineFunction;
    let SickMachines = MachinesWithMeanAndStdDev |
    project machineName, 
        machineFunction, 
        environmentName, 
        totalExceptionCount = count_, 
        cutoff = avg_count_ + Sigmas * stdev_count_, 
        signalStrength = ((count_ - avg_count_) / stdev_count_) 
    | where totalExceptionCount > cutoff and totalExceptionCount > MinimumExceptionsToTrigger
    | order by signalStrength desc;
    SickMachines
}

1 个答案:

答案 0 :(得分:1)

避免由于异常值较高而导致漏检的一种方法是使用基于百分位数的检测。为此,您可以使用make-series,然后再使用内置的series_outliers函数。

另一个选择是从计算中删除异常值,然后重新结合数据,并且需要多次联接。假设您的异常位于包含异常变量的 Exception 中:environmentName,machineFunction,machineName,则可以使用以下伪查询删除计数高于98%的所有计算机:

let ExceptionsCounts = Exceptions 
    | summarize counts = count() by environmentName, machineFunction, machineName;
let ExceptionsCleansed = ExceptionsCounts
    | summarize p98 = percentile(counts, 98) by environmentName, machineFunction
    | join kind=inner (ExceptionsCounts) on environmentName, machineFunction
    | where counts < p98;

从那里,您可以使用 ExceptionsCleansed 计算平均值/ stddev,并继续对原始的 Exception 进行检测,并计算出与您发布的查询完全相同的数字。