Логические и тихие индикаторы

Задача

Так как основное предназначение okerr - оповещение о "тревоге", очень важно, чтобы оповещения шли только тогда, когда на самом деле требуется вмешательство. Логический модуль системы представляет очень мощный инструмент для реализации любых сложных условий.

Например, в следующих ситуациях оповещения могут быть не нужны:

  • "Мигание" (flapping). Подозрительная ситуация появляется регулярно, но не требует вмешательства. Например, высокая загрузка сервера случается на многих серверах хотя бы иногда - и это само по себе не проблема. Оповещать о ней каждый раз не нужно. Но если она держится достаточно долго - тогда это уже требует внимания.

  • "Временное окно". Любые неполадки допускаются в интервале с 5 до 6 утра (Если вы назначили это время для регламентных работ и администраторы могут свободно отключать любые сервисы). Но если проблема случается (или продолжается) за границами этого интервала - должно быть выслано оповещение.

  • "Эскалация". Администраторы должны получать оповещение о проблеме и быстро ее решать. Руководство должно быть оповещено только в исключительном случае, когда проблема не решена за отведенное время.

  • "N из M". Для сложных систем из многих серверов, выход из строя 1-2 серверов может быть не критичным и случаться часто. Можно настроить okerr для оповещения если нарушается правило "живы не менее 5 из 8 web серверов и не менее 2 из 3 DB серверов".

Описанные выше ситуации - примеры того, что можно достичь через логические индикаторы. Наверное, любое условие, которое можно описать в виде логического выражения и которое использует известные okerr'у данные - можно реализовать логическим индикатором.

Условно (по возлагаемой на них роли) можно разделить индикаторы на индикаторы "верхнего" и "нижнего" уровня. Индикаторы нижнего уровня - представляют "сырые" исходные данные (например: load average). Переключение состояния индикаторов нижнего уровня, не должно вызывает оповещений. Как правило, индикаторы нижнего уровня имеют флаг Silent (тихий), чтобы от них не отправлялись алерты.

Индикаторы верхнего уровня - имеют логический тип проверки на основании данных от индикаторов нижнего уровня. Обнаружение проблемы индикатором верхнего уровня высылает алерт от системы.

Ошибки в логических индикаторах

Прежде чем мы начнем, нужно научиться исправлять ошибки (так как делать мы их будем много). Если в логическом выражении будет ошибка (например, выражение будет просто 'asdf'), то при следующей проверке okerr ее обнаружит. В детали индикатора будет записана информация об ошибке (Runtime error (NameError): name 'asdf' is not defined) и будет выставлен флаг problem (так же он будет отображаться иконкой ошибки в списке индикаторов) и okerr не будет исполнять этот индикатор пока флаг не будет убран.

После обнаружения ошибки нужно изменить логическое выражение (исправить в нем ошибку), убрать флаг 'problem', применить изменения, и (по желанию) нажать "перепроверить сразу", чтобы увидеть результат через несколько секунд.

Flapping. Предотвращение "мигания" индикаторов

В okerr есть wizard для быстрого создания индикатора верхнего уровня. Можно и вручную, но так проще и удобнее. На странице индикатора нажмите на "Create upper-level logical indicator" (справа-внизу, под круговыми диаграммами аптайма)

Откроется страница параметров wizard'а:

Imgur

Индикатор верхнего уровня будет переключаться в состояние ERR, только тогда, когда индикатор нижнего уровня переключиться в ERR и продержится в нем не менее чем 'ERR threshold' секунд. Аналогично, возвращение в состояние OK регулируется параметром 'OK threshold'.

Для логических индикаторов рекомендуется использовать политику с небольшим периодом, а пороговые значения установить "по вкусу".

После нажатия кнопки "Create upper-level indicator" создастся логический индикатор верхнего уровня. В нашем примере, исходный индикатор назывался "okerr.com", индикатор верхнего уровня был назван "okerr.com-up". Метод проверки - "Logical expression", а само логическое выражение (expr):

(lo['status']=='OK' and lo['statusage']>4800) or (lo['status']=='ERR' and lo['statusage']<8400)

Логическое выражение использует синтаксис языка Python. Обратите внимание - логическое выражение описывает условие, при котором индикатор будет в состоянии OK. (А если условие не выполняется - будет статус ERR ). Таким образом, логическое выражение "True" будет всегда давать статус OK, а выражение "False" всегда давать статус ERR.

В нашем примере, статус ОК будет в одном из двух случаев: - Нижний индикатор в статусе OK и статус держится уже более 4800 секунд - Нижний индикатор в статусе ERR, но недавно - статус установлен менее чем 8400 секунд.

Если ни то, ни то условие не соблюдено - статус верхнего индикатора будет ERR.

Данные, на основе которых индикатор может выполнять логические выражения доступны по ссылке в описании индикатора "Data structure"

Временное окно

Аналогично можно создать индикатор, которые не будет переключаться в состояние ERR в указанное время (чтобы, например, дать возможность администраторам проводить запланированные работы). Создайте любой индикатор - он будет у нас индикатором нижнего уровня, и его статус будет "реальным" (переключаться в любое время). Можете сделать его "тихим", чтобы не было писем от него. Пусть этот индикатор у нас будет называться 'test'.

Дальше, можно создать индикатор верхнего уровня так же, через визард, как и в примере 'Flapping' выше, но заменить логическое выражение. В этом примере, для разнообразия, мы сделаем индикатор напрямую, без визарда. Итак, создадим индикатор как обычно (через "зеленый плюсик" внизу страницы), назовем его, например 'test-logic', сменим его тип на 'Logical expression', сменим политику на quick (600 секунд) и выйдем из режима настройки.

Далее, настроим логическое выражение (Expr). Для начала установим простое выражение:

Expr: s['test']

В этом случае, индикатор просто будет "копировать" статус индикатора 'test', с небольшой задержкой (каждый раз, когда логический индикатор будет исполняться (каждые 600 секунд при политике quick), он будет принимать значение, которое на тот момент будет у индикатора 'test'.

Для удобства, после того, как мы сохранили изменения, мы можем нажать кнопку "Перепроверить сразу" на странице индикатора, и тогда okerr выполнит перепроверку индикатора в ближайшие несколько секунд. (после нажатия кнопки в строчке "Ожидается" будет установлено текущее время и, так как это время уже наступило - появится иконка песочных часов, означающая, что время проверки уже наступило. Несколько раз обновим страницу - и увидим, что через несколько секунд okerr перепроверил индикатор, назначил следующее время проверки и иконка часов пропала).

Теперь, научим индикатор быть в состоянии ОК в указанное время.

Expr: s['test'] or (hhmm>1000 and hhmm<1100)

В структуре данных, доступных логическому индикатору (доступна по ссылке "Data stucture: view" на странице индикатора) есть переменная hhmm, которая представляет текущее серверное время (UTC) в формате HHMM. Шесть утра это 600, Девять-двадцать вечера это 2120.

Таким образом, статус ОК будет в случае, когда либо индикатор 'test' в статусе ОК, либо если время между 10 и 11 утра.

Эскалация

Предположим, среди пользователей проекта, у нас есть несколько технических специалистов и один руководитель. Специалисты - обычные пользователи системы. Они получают уведомления (алерты) о всех изменениях индикаторов и оперативно реагируют на них. Руководитель не должен получать регулярные оповещения (зачем? ведь админы сами получат и исправят ситуацию), но должен контролировать процесс - получать оповещения в случае, когда специалисты не исправили проблему быстро и какой-то индикатор находится в состоянии проблемы достаточно долгое время.

errage и uerrage

У каждого индикатора есть параметр errage и uerrage. errage - возраст (в секундах) статуса ошибки. Если индикатор в статусе ERR, то errage - возраст статуса в секундах. Через пять минут errage будет равен 300 и так далее. uerrage - возраст (в секундах) необработанной ошибки. Аналогично errage, с одним исключением: если индикатор со статусом ERR будет в настройке (maintenance), uerrage будет равен 0 (А errage будет по прежнему "тикать" каждую секунду).

И errage и uerrage оба будут равны 0 в случае: - Индикатор в статусе OK - У индикатора установлен флажок "тихий"

uerrage удобен для отслеживания необработанных ошибок (ошибка возникла, но администраторы еще не начали работать по ней и не поставили индикатор в режим maintenance). errage удобен для отслеживания ошибок, которые долго не исправлены (может быть админы уже начали работу, перевели индикатор в режим настройки, но тем не менее, достаточно долгое время индикатор в состоянии ошибки, и руководитель должен знать об этой проблеме).

Использование errage и uerrage

(Для примеров обычно использовано значение errage, но точно так же можно использовать uerrage и наоборот)

Мы можем использовать как эти параметры какого-то индикатора напрямую: i['test']['errage'] так и сводные: age['tagname:errage'].

В первом случае будет использовано значение errage индикатора с именем 'test'. Во втором - максимальное значение errage среди индикаторов, у которых есть метка 'tagname'. Если же использовать метку ERR вместо tagname: age['ERR:errage'] - будет максимальное значение среди всех индикаторов.

Если мы пометим несколько индикаторов меткой webserver и установим логическое выражение:

age['webserver:uerrage']<2400

тогда наш логический индикатор будет переходить в состояние ERR если среди наблюдаемых вебсерверов возникнет ошибка, которая не будет принята в работу зв 40 минут.

Получение оповещений только от некоторых индикаторов

Для того чтобы не получать обычные оповещения от индикаторов, нужно зайти в Профиль, убрать галочку с "Рассылать оповещения" и применить изменения.

Чтобы затем подключиться к оповещениям от какого-то конкретного индикатора, нужно на странице индикатора в пользовательских настройках (справа-вверху) подписаться на оповещения - установить галочку на 'subscribe' и сохранить изменения. Так можно сделать с несколькими индикаторами.

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

N из M

Допустим, у нас большая серверная ферма (целых M серверов), и выход из строя одного-двух серверов - обычное дело. Мы хотим чтобы у нас был сводный индикатор, который бы переходил в статус ERR только в случае серьезной проблемы (например, вышло из строя больше скольки-то серверов). Для этого есть несколько способов.

С использованием префиксов

Назовем индикаторы с использованием префиксов. Например: web:server1, web:server2 и так далее. При таком подходе во-первых индикаторы будут удобно группироваться в списке, а во-вторых, они уже объединены по имени, и okerr об этом догадывается.

Переменная prefix['ERR:web'] будет содержать количество индикаторов со статусом ERR с префиксом 'web'. Аналогично, prefix['OK:web'] - количество индикаторов ОК в этом префиксе. Мы можем использовать это в логических проверках, например:

prefix['ERR:web']<2

В этом случае, логический индикатор будет OK если количество ошибок меньше 2.

С использованием меток

Установим метку 'test' на несколько индикаторов. В структуре данных, в tags будет отражаться текущее состояние. tags['ERR:test'] и tags['OK:test'] будут отображать количество индикаторов с меткой 'test' в соответствующем состоянии. Например, логическое выражение:

````tags['OK:test']>3````

Индикатор с этим логическим выражением будет OK если количество индикаторов с меткой test в состоянии OK будет более трех.

Замечание про 'okerrm статус'

Индикатор может иметь статус OK либо ERR, и при этом может либо иметь либо не иметь свойства maintenance (в настройке), silent (тихий), disabled (отключен). Это создает довольно большое количество возможных комбинаций (наш аналитический отдел подсчитал, что это 2 в 4 степени - где в интервале от "сорок сороков" до "тьмы" ). Для упрощения в okerr иногда используется так называемый okerrm-статус. У каждого индикатора всегда есть однозначный 'okerrm статус'. Мнемонически и исторически okerrm означало OK/ERR/Maintenance (три возможных варианта статуса), сейчас возможны еще другие варианты, но тем не менее название okerrm-статус решили не менять, иначе оно стало бы очень длинным и еще сложнее произносилось бы.

okerrm статус выбирается по схеме:

  • DISABLED
  • MAINTENANCE
  • SILENT
  • Статус (OK или ERR)

(сначала проверяется, что индикатор DISABLED. Если так, то okerrm-статус='DISABLED'. Если нет - то проверяется следующая строчка, и так далее. Если никаких особых флагов не установлено, то okerrm-статус будет равен обычному статусу: OK либо ERR).

В дата-структуре проекта, в структурах tags и prefix используются именно okerrm-статус. Таким образом, например, если всего 4 индикатора, один из них будет в состоянии MAINTENANCE и статусе ERR, один в состоянии ERR и два в состоянии OK, то tags['ERR:test'] будет равен 1, а не 2.

Таким образом, мы можем делать более гибкие проверки. По ERR мы проверяем именно необработанные ошибки ( администраторы не выставили режим настройки), а по OK - именно живые сервера.