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