Azure data explorer 如何:从stddev/mean计算中排除一行,并在以后联接

Azure data explorer 如何:从stddev/mean计算中排除一行,并在以后联接,azure-data-explorer,Azure Data Explorer,因此,我试图找到那些抛出异常的机器,与它们的组(按环境和功能划分)相比,它们抛出异常的数量异常多。直觉是,整个组中的负载和任务类型应该相当相似,因此如果一台机器抛出更多的异常,它可能处于某种不好的状态,应该得到服务 这对于大型计算机组来说效果相当好,但对于较小的计算机组,则存在一个问题:如果计算机非常少,并且只有一台计算机抛出了大量异常,则可能无法检测到。原因是因为数据点是该组的一般STDEV和平均值计算的PAR,所以平均值和STDEV偏向于该异常值 解决方案是从整个组的计算stddev和平均值

因此,我试图找到那些抛出异常的机器,与它们的组(按环境和功能划分)相比,它们抛出异常的数量异常多。直觉是,整个组中的负载和任务类型应该相当相似,因此如果一台机器抛出更多的异常,它可能处于某种不好的状态,应该得到服务

这对于大型计算机组来说效果相当好,但对于较小的计算机组,则存在一个问题:如果计算机非常少,并且只有一台计算机抛出了大量异常,则可能无法检测到。原因是因为数据点是该组的一般STDEV和平均值计算的PAR,所以平均值和STDEV偏向于该异常值

解决方案是从整个组的计算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
}

避免由于强异常值而遗漏检测的一个选择是使用基于百分位数的检测。为此,可以使用后跟的内置函数

另一种选择是从计算中删除异常值,然后重新连接数据,并且需要多个连接。假设您的异常位于包含维度的异常中: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;
let Exceptions counts=异常
|按环境名称、machineFunction、machineName汇总计数=计数();
let ExceptionsCleansed=例外计数
|按环境名称、机器功能汇总p98=百分位数(计数,98)
|在environmentName、machineFunction上联接种类=内部(例外计数)
|其中计数
在此基础上,您可以使用ExceptionsCleansed计算平均值/stddev,并使用与您发布的查询完全相同的计算数据继续检测原始异常