Как: исключить строку из вычислений stddev/mean и присоединиться позже

Поэтому я пытаюсь найти машины, которые генерируют исключительно много исключений по сравнению с их группой по среде и функциям. Интуиция заключается в том, что тип нагрузки и задачи должен быть примерно одинаковым для всей группы, поэтому, если один компьютер генерирует намного больше исключений, он, вероятно, каким-то образом находится в плохом состоянии и должен обслуживаться.

Это работает довольно хорошо для больших групп машин, но для небольших групп есть проблема: если машин очень мало, и только одна из них выдает много исключений, это может не быть обнаружено. Причина состоит в том, что, поскольку этот datapoint является парой общего вычисления stddev и среднего значения для группы, среднее значение и stddev смещены в сторону этого выброса.

Решением было бы либо каким-то образом вычесть эту точку данных из вычисленного значения stddev и среднего значения для всей группы, либо рассчитать значение stddev и среднее значение для каждой комбинации машина / среда / функция (исключая рассматриваемую машину из расчета stddev / mean) вместо того, чтобы просто по среде / функциональной группе.

Вот текущий код, который делает это с помощью среды / функции. Есть ли элегантное решение расширить его, чтобы сделать машину / среду / функцию?

// 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 ответ

Одним из способов избежать пропущенных обнаружений из-за сильных значений выбросов является использование обнаружения на основе процентилей. Для этого вы можете использовать make-series, а затем встроенную функцию series_outliers.

Другой вариант - удалить выбросы из расчета, а затем снова присоединиться к данным и требует нескольких объединений. Предполагая, что ваши исключения находятся в Исключениях, которые содержат dimesnions: 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, чтобы вычислить среднее значение / стандартное отклонение и продолжить обнаружение исходных исключений с вычисленными значениями по точно такому же запросу, который вы разместили.

Другие вопросы по тегам