Child pages
  • Performance Management в NOC Microservices
Skip to end of metadata
Go to start of metadata

Описание

Подсистема Performance Management (PM) в ноке отвечает за сбор метрик с оборудования (дискавери) и контроль их значения (пороги, threshold).

Умеет из коробки:

  • Собрать (collect) метрики по SNMP OID (по интерфейсам и не векторные метрики);
  • Записать, или не записать, метрики в БД ClickHouse (возможна поддержка других БД, писатель есть только для CH);
  • Отобразить метрики при помощи Графаны (Grafana);
  • Пороги - создать аварию по превышению некоторого значения (или значения функции) за интервал времени

Умеет после использования напильника:

  • собрать метрики по CLI (надо писать код сборщика);
  • самые разные метрки по SNMP (для сложных случаев необходимо писать генератор);
  • можно делать свои дашборды в Графане
  • и всякую аналитику по метрикам в CH (необходимо написание запросов руками)

Следует признать, что PM находится в стадии развития. Заложены широкие возможности, но много требует доработки или реализации. Посмотрим на то, что есть сейчас.

Архитектура и компоненты

Архитектурно PM состоит из источника данных, сборщика (коллектора), транспорта, писателя и хранилища. Туда же, можно добавить интерфейс для отображения графиков и интерфейс для аналитики (отчётов).

  • Источник данных может быть внешний (устройство) или внутренний (пингер, дискавери)
  • В качестве сборщика выступает активатор. Инициатором сбора - дискавери. Т.е. со стороны дискавери приходит запрос на активатор, он отрабатывается и возвращает результат дискавери, который уже отправляет его в сторону писателя по транспорту.
  • Транспортом для метрик выступает HTTP (между дискавери и активатором) и NSQ во всех остальных случаях.
  • Писатель отвечает за запись дошедших до него метрик в Хранилище. Для каждого хранилища свой писатель.
  • Хранилищем выступает СУБД ClickHouse от Yandex (CH).
  • Интерфейс для графиков - Grafana.

Пройдёмся по компонентам подробнее:

Активатор

Запускает скрипты для сбора метрик.

  • Generic.get_metrics - реализация сбора метрик по SNMP, поскольку является платформо-независимой. Работа скрипта определяется конфиг-файлами, расположенными в папках snmp_metrics профиля. В ней присутствуют JSON фалйы со специфичными для профиля метрики SNMP (н-р OID’ы для памяти и процессора)  соответствующего профиля. Для добавления своих метрик, необходимо добавить файлик с ними в папку snmp_metrics. Подробнее вопрос будет рассмотрен далее.

  • Profile.get_metrics - реализует различные платформо-зависимые вещи: сбор метрик по CLI и генераторы OID'ов

  • get_capabilities - напрямую в сборе метрик не участвует, но определяет поддержку оборудованием протокола SNMP и различных ньансов работы с ним (поддержку bulk, ). В случае отсутствия поддержки SNMP, сбор метрик запускаться не будет.

  • get_interfaces - сам по себе в сборе метрик не участвует. Но он необходим в случае сбора метрик с интерфейсов, т.к. возвращает ifindex. Если не будет ifindex, то не будет метрик с интрейсов.

Дискавери

За сбор метрик отвечает Periodic дискавери. Его задачи:

  • В заданное время озадачить активатор сбором метрики
  • Отработать пороги, согласно правилам (создать аварию, по необходимости)
  • После получения метрик упаковать их для отправки по NSQ.
  • Поместить в очередь metrics, откуда их заберёт писатель.

Центральная штука, в общем.

NSQD aka транспорт

ПО очереди для работы в реальном времени с гарантированной первой доставкой. Занимается передачей сообщений из одного конца очереди в другой. NSQD необходим в одном экземпляре на каждую ноду, NSQLOOKUPD минимум 1 (2 для отказоустойчивости).

Архитектурно NSQD состоит из 3 компонент: 2 обязательных и 1 опционального. 

  • процесс NSQD отвечает за работу очередей: принимает сообщения и передаёт их к месту назначения. Должен присутствовать на каждой НОДе, где есть процесс, пишущий в очередь. В случае невыполнения требования возможны потери сообщений.
  • процесс NSQLOOKUPD отвечает за поиск демонов NSQD с необходимыми топиками (очередями с сообщениями). Необходим по крайней мере в 1 экземпляре.
  • процесс NSQADMIND Это админка, к NSQD не обязательна, но позволяет просматривать различную статистику и управлять очередями (очищать, удалять и т.д.)

CHWRITER

Слушает приходящие сообщения (канал metrics) и, по мере их накопления, записывает в БД. Интервал записи поддаётся настройке. Рекомендуется держать его поближе к БД.

ClikcHouse (CH)

В качестве хранилища для метрик используется БД Clickhouse от Yandex


Сущности

  • Метрика - некоторая изменяющаяся во времени величина, подлежащая фиксации. Формально говоря, метрикой может быть любая величина: скорость интерфейса, число свободной памяти, статус интерфейса и т.д. Достаточно, чтобы она менялась во времени и представляла какой-то интерес.
    Метрики бывают:

    • Скалярные - когда одной метрике соответствует одно значение. Н-р если у устройства 1 датчик температуры, то метрике Температура будет соотв. 1 значение - показатель этого датчика. Если же, датчиков несколько, то необходимо будет создавать метрики Температура датчика 1Температура датчика 2 и т.д.
    • Векторные - когда одной метрике соответствует более одного значения. Н-р метрике Кол-во входящих пакетов соответствует столько значений, сколько интерфейсов на устройстве. Рядом с векторными метриками идёт понятие Path, рассмотрено ниже.

К основным понятиям PM в НОКе добавляет несколько своих:

  • MetricScope (пространство метрик) - множество метрик, объединённых некоторой общей характеристикой (ключевыми полями). Ближайший пример - это интерфейсные метрики, объединённые индексом интерфейса или н-р датчики оборудования, объединённые местом в устройстве или номером. Физическое представление scope, это таблица в которую идёт запись метрик, ему принадлежащих, с индексом по ключевым полям.
  • MetricType - наименование метрики. Принадлежит какому либо пространству MetricScope. Физическое представление - столбец в таблице (название таблицы в metric_scope)
  • Path - Необходим для векторных метрик. Служит для детализации метрики в пределах объекта. Н-р, может содержать индекс датчика, номер слота памяти и т.д. Точное соответствие полей задаётся в MetricScope, сам передаётся списком.

Байки от разработчика

Байки от разработчика:
Представим, что у вас есть нетрезвый электрик, совковый такой, прям небритый, в кепке и с перегаром. По имени Петрович. И у него есть щиток, в котором 3 фазы.

А вы – начальник электрика Петровича со щитком, в котором 3 фазы. И вольтметром.
И, раз в 5 минут, посылаете его за щитком, мерять напряжение. Которое он пишет на бумажке и отдаёт вам. А вы рисуете по бумажке график. Чтобы все видели, вот.

Прибор у Петровича выдаёт метрику, допустим, Environment | Voltage, а фаз 3. Петрович добивает 0.33, поправляет кепку, идет, и пишет карандашиком на бумажке:

  • Environment | Voltage [“фаза1”] 222.3
  • Environment | Voltage [“фаза2”] 220.7
  • Environment | Voltage [“фаза3”] 222.7

Итого, имеем:

  1. Небритый электрик
  2. 3 фазы
  3. 1 вольтметр
  4. Environment | Voltage [“фаза1”] 222.3Environment | Voltage [“фаза2”] 220.7Environment | Voltage [“фаза3”] 222.7

Тепрерь представьте, что по пути он встретил Прасковью… и она говорит, что у нее тоже напряжение. Петрович поправляет кепку и пишет Environment | Voltage [“Прасковья”] 218.4.

Итого:

  1. Небритый электрик
  2. 3 фазы
  3. 1 вотльтметр
  4. Прасковья
  5. Environment | Voltage [“фаза1”] 222.3Environment | Voltage [“фаза2”] 220.7Environment | Voltage [“фаза3”] 222.7Environment | Voltage [“Прасковья”] 218.4

Но тут вы, находите в запасниках стола температуру, которую меряют градусником! и будет у вас вторая метрика Environment | Temperature. Петровича послали мерять её тоже. Он так и запишет - [“Щитовая”][“Прасковья подмышка”][“Прасковья ad-rectum"]

Резюме: Metric Type на вольтаж у тебя один, на температуру - еще один, где бы Петрович их не замерял: Environment | Wodka [“Петрович”] 0.33 или Environment | Drink [“Водка”, “Петрович”], а путь (Path) до них разный…


  • Генератор - потребен при сборе векторных метрик по SNMP. Реализует интерфейс дискавери метрик, раскладывая базовый SNMP OID на OID’ы по которым пойдёт сбор данных. Самый простой пример - это создание из OID’а кол-ва прошедших байт через интерфейс OID’ов для каждого интерфейса. Н-р базовый OID для входящих пакетов на интерфейс (ifInUcastPkts): 1.3.6.1.2.1.2.2.1.11, чтобы снять эту метрику для конкретного интерфейса к нему необходимо дописать его номер: 1.3.6.1.2.1.2.2.1.11.2, вот этим и занимаются генераторы. Подробнее, рассмотрены в разделе добавления метрик.

Настройка сбора метрик

Прервём поток букв(smile) и попробуем снабдить их картинками. В текущей реализации настройку сбора метрик очень упростили. Фактически, необходимо:

  1. Необходимо добавить метрики для сбора:
    • Интерфейсные метрики добавляются в профиле интерфейса (Interface Profile): Inventory -> Setup -> Interface Profile (вкладка Metrics)
    • Метрики объекта в профиле объекта (Object Profile): Service Activation -> Setup -> Object Profile(вкладка Metrics)
    • Метрики SLA в профиле SLA (SLA Profile): SLA -> Setup -> SLA Profile
  2. Для интерфейсных метрик необходим работающий дискавери интерфейсов и назначить профили на интерфейсы, с которых необходимо собираться метрики. Автоматизации этого процесса посвящена статья
  3. Для SLA метрик необходим SLA дискавери и нзначить профиль SLA на необходимую пробу (пробы собираются SLA дискавери).
  4. Для снятия метрик по SNMP, необходим прописанный и рабочий SNMP_RO community в настройках объекта или назначенный профиль аутентификации с ним.

В случае, если назначен профиль аутентификации (Auth Profile) на устройство, то будет использован он, даже если поле SNMP RO в нём пустое (в этом случае система будет писать, что отсутствует community)

  1. Активировать Periodic Discovery и включить в нём сбор метрик: Service Activation -> Setup -> Object Profile, Periodic -> Metric
  2. Настроить пороги (опционально)

Пройдёмся по этим шагам подробнее:


Настрока Managed Object

Необходимо проверить ManagedObject:

  • SNMP Community необходим прописанный Communtiy RO (либо указан в назначенный Профиль аутентификации (AuthProfile)) в случае снятия метрик по SNMP.

В случае, если назначен профиль аутентификации (Auth Profile) на устройство, то будет использован он, даже если поле SNMP RO в нём пустое (в этом случае система будет писать, что отсутствует community)

  • На вкладке Capabilities, необходимо убедиться, что проверка SNMP на устройстве завершилась успешно (правый скриншот). Вкладка Capabilities (Возможности) заполняется по итогам работы опроса Caps:

  • SNMP Capabilities:
    • SNMP - базовая проверка SNMP, проходит путём опроса устройства OID  sysObjectID (.1.3.6.1.2.1.1.2.0)
    • SNMP | Bulk - поддержка устройством пакетных (Bulk) запросов
    • SNMP | IF-MIB - разрешён ли для опроса IF-MIB (если данного капса нет, то опрос метрик интерфейсов проходить не будет)
    • SNMP | IF-MIB | HC - поддержка 64-разрядных счётчиков
    • SNMP | v1, v2c, v3c - поддержка версии SNMP

Настройка Managed Object Profile

Идём в "Service Activation" -> Setup -> "Managed Object Profile". Выбираем существующий или создаём новый профиль. В нём, на вкладке Metrics нажимаем Add и выбираем метрику, которую необходимо собирать. Для этого достаточно заполнить 3 поля:

  • Metric Type - метрика
  • Active - (включит сбор метрики)
  • Is store - сохранять метрику в БД
  • По необходимости, указываем пороги (описаны в разделе ниже)


После, переходим на вкладку "Periodic Discovery" и активируем сбор метрик (устанавливаем галочка Enable и Metric). По необходимости, настраиваем интервал обхода.


Настройка сбора метрик с интерфейсов

Метрики для интерфейсов настраиваются в Inventory -> Setup -> "Interface Profiles". В нём необходимо аналогично Managed Object Profile добавить метрики.

После этого привязать профиль к интерфейсам. Это можно сделать в меню Inventory -> Interfaces. Необходимо в выпадающем списке выбрать MO и назначить профили. В это же меню можно попасть по кнопке Interfaces из "Service Activation" -> "Managed Object" -> <MO>.

Настройка Interfaces Classification Rules

Делается опционально-обязательно. Предназначены для автоматического назначения профила интерфейса на интерфейс. Конечно, можно вручную устанавливать профили интерфейсов, но это не продуктивно(smile) Поэтому можно расписать правила классификации. Делается это  из меню Inventory -> Setup -> "Interface Classification Rule".

Подробно работа с правилами расписана тут: Классификация интерфейсов.

Настройка Dashboard

Просмотр метрик идёт через Dashboard. Он доступен из интерфейса MO: в этом случае, он, автоматически, настраивается на отображение всех метрик, собираемых с данного MO или по адресу https://<AddressNOCWeb>/ui/grafana:

Если в интерфейсе Графаны вместо в значениях метрик выводится случайная величина: необходимо проверить настройки источника данных (DataSource) в графане.

Для настройки Источника данных (DataSource) необходим админский доступ к Графане (по умолчанию, он у пользователя admin). В левом верхнем углу кликнуть по значку графаны, далее опция "Data Sources". После этого нажать кнопку Add в верхнем меню.

При добавлении указываем следующие опции:

  • Name (может быть любой)
  • Обязательно указываем галочку Default (по умолчанию)
  • Type выбираем ClickHouse (или близкую к ней)
  • В URL - адрес ClickHouse (если стоит на отдельном хосте - то необходимо указать адрес этого хоста), порт 8086 - по умолчанию
  • Access - Proxy (не путать с http_proxy!) это режим доступа к данным.
  • Вкладки Аутентификации выставляем BasicAuth, остальные не отмеченные
  • Basic Auth Details указываем в соответствии с теми, которые прописывали при развёртывании НОКа (по умолчанию пользователь readonly)

Проверить настройки можно кнопкой "Test Connection". После нажимаем Save. Наслаждаемся эффектом.

Добавление своих метрик

Для добавления метрики необходимо выполнить 2 шага:

  1. Создать метрику (Metric Type) (выполняется в веб-интерфейсе)
  2. Написать её конфигурацию (выполняется на активаторе)

Перед добавлением метрики есть 2  пути. Если метрика более менее стандартная (температура, загрузка процессора, интерфейсная) то можно клонировать существующую. В остальных случаях необходимо будет ответить на несколько вопросов:

  1. Необходимо понять, какие ключевые поля будут участвовать в сборе метрики. На этот вопрос можно не отвечать когда:
    • н-р, необходимо снимать интерфейсные метрики (они уже реализованы), копируем, вносим пару изменений и пользуем
    • метрика всегда одна (н-р один процессор на железке и больше быть не может или количество пользователей)
  2. В случае SNMP - всё просто. Открываем её в SNMP браузере и ключевые поля перечислены там. Ищем подходящий MetricScope или создаём свой.
  3. В случае CLI свободы больше. Надо подумать, какие имена/значения будут отличать метрику для данного объекта от других.

Если метрика относится к параметру объекта (н-р показатель какого-нибудь датчика) - используем Environment, если метрика для интерфейса (н-р размер входящего буфера) - то scope interface. Имя задаётся через прямую черту: | это позвляет отстраивать иерархию метрик. Рекомендуется пользоваться данным соглашением


Добавлени MetricTypes

После выбора Metric Scope идём в интерфейс создания метрики: PM -> Setup -> Metric Type. И нажимаем на кнопку Добавить, заполняем поля:

  • Name - имя метрики. Желательно давать осмысленные имена и использовать иерархию (она строится через вертикальный полосы)
  • Scope - выбранный на предыдущем этапе MetricScope
  • FieldName - имя столбца в таблице БД (маленькие буквы, только буквы и нижнее подчёркивание), должно быть уникально в пределах Scope
  • FieldType - тип столбца в таблице БД (выбирать необходимо внимательно т.к. поменять можно будет только с удалением таблицы)
    • Int* - целое число (8, 16, 32 бита)
    • UInt - целое число без знака (положительное)
    • Float* - число с запятой (десятичное)
    • String - строка
  • Measure - единица измерения. 
    • packet/s
    • bit/s
    • C
    • mA
    • dBm
    • %

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

Настройка метрики на сборщике (активаторе)

В задаче активатору приходит список метрик (в виде имён), в зависимости от способа их получения: SNMP или не SNMP дальнейший путь расходится.

За формирование списка OIDов для съёма отвечает генератор. Для объяснения ему что к чему необходимо написать конфигурацию.
Конфигурация метрики:

  • формат: JSON
  • место хранения: директория snmp_metrics профиля
  • потребитель: генератор OID
  • не требуется: если получение метрики не по SNMP
  • пример файла настройки:
{
  "$metric": "CPU | Usage",
  "$type": "oid",
  "oid": "1.3.6.1.4.1.2011.2.23.1.18.1.3.0",
  "type": "gauge",
  "scale": 1
}
  • $metric - Имя метрики, обязательное поле. Должно совпадать с именем, созданным в интерфейсе Metric Type
  • $type - Имя генератора, обязательное поле. Обозначает алгоритм по которому будут создаваться SNMP OID для считывания.
  • oid - SNMP OID или его шаблон, который будет собираться для метрики
  • type - тип SNMP (gauge, counter, bool). Если не указан, то подразумевается gauge
  • scale - множитель может быть целым числом (в этому случае полученное значение умножается на это число) или фцнкцией, тогда число передаётся ей для обработки.
  • Дополнительные параметры (определяются конкретным генератором)

Формулы для Scale можно написать в "<noc>/core/script/metrics.py".

Scale functiion
def percent(value, total):
    """
    Convert absolute and total values to percent
    """
    if total:
        return float(value) * 100.0 / float(total)
    else:
        return 100.0

def percent_one(value, total):
    """
    Convert absolute and total values to percent
    """
    if total:
        return float(value) * 100.0 / (float(total) + float(value))
    else:
        return 100.0

Генераторы

Отвечают за формирование списка SNMP OIDов для сбора устройства на основе файла конфигурации. Указываются в директиве "$type" конфига.

В базовой системы реализованы следующие генераторы:

OID

Считывает OID, заданный в конфиг файле. Доступны параметры type и scale.

{
  "$metric": "CPU | Usage",
  "$type": "oid",
  "oid": "1.3.6.1.4.1.8886.1.1.1.4.1.0"
}

Может указать больше 1 OID’a, но должна быть задана функция, для рассчёта значения метрики:

{
  "$metric": "Memory | Usage",
  "$type": "oid",
  "oid": [
    "1.3.6.1.4.1.2021.4.5.0",
    "1.3.6.1.4.1.2021.4.6.0"
  ],
  "scale": "percent_usage"
}


Сами функции находят в файле core/script/metrics.py
percent_usage(value, total):
percent_invert(value, total):
sum(*args):
subtract(*args):
is1(x):

OIDS

Позволяет перечислять OID’ы списком с указанием path. Полезен, если метрика векторная, но сами значения наперёд известны и неизменны.

Пример конфиг файла:

{
  "$metric": "Environment | Sensor Status",
  "$type": "oids",
  "oids": [{
    "oid": "1.3.6.1.4.1.41752.5.15.1.1.0",
    "path": ["","","", "Door"],
    "$type": "oid",
    "type": "gauge",
    "scale": 1
  },{
    "oid": "1.3.6.1.4.1.41752.5.15.1.7.0",
    "path": ["","","", "Key_State"],
    "$type": "oid",
    "type": "gauge",
    "scale": 1
  }
  ]}

Здесь появляется дополнительное свойство - path. Его формат можно уточнить в MetricScope. Например, для Environment будут:

  • chassis
  • slot
  • module
  • name




CAPS

Специфичный генератор. Проверяет Capabilities, если присутствует - отрабатывает соответствующее правило
! для платформы и версии

CAPINDEX и CAPLIST

При налачии capabilities в специальном формате, позволяет сгенерировать SNMP OID по шаблону.
Capindex - Caps в виде числа, Caplist в виде чисел, разделённых символом.

MATCHERS

Реализует возможность выбора SNMP OIDов на основании платформы/версии ПО оборудования через конфигурацию. Конфигурация для метрик распологается в файликах из папки snmp_metrics профиля. Теперь в них можно применять генератор match:

{
   "$metric": "XXXXX",
   "$type": "match",
   "$matchers": {
     // Локальные матчеры
     // По возможности стоит выносить в платформы
     "is_3328": {
      "platform": {
        "$regex": "3328"
            }
        },
      "is_2328": {
      "platform": {
        "$regex": "2328"
            }
        }
    }
    },
   "$match": [
        {
            "$match": "is_3328",  // Попадает только если сработал матчер из $matchers или из профиля (if getattr(self, name))
            "$type": "oid",
            "..."
        },
        {
           // Нет матчера, срабатывает всегда
            "$type": "oid",
            ...
        }
   ]
   }
}

Блок matchers описывает структуру по которой будет проходить проверку версия и платформа оборудования. На выходе будет совпало или нет. Сами OIDы описываются в разделе $match в виде списка. При работе проходим последовательно список и производим проверку соотв матчера из блока matchers.

  • если совпадение есть - берём данный OID (проверяется матчер, указанный в параметре “$match”),
  • если нет - идём дальше.
  • если совпадений не было - будет использован блок без $match (по-умолчанию он идёт последним)

Внутри можно использовать такие же генераторы, как и в обычных конфигурациях.

Н-р для профиля Huawei.VRP есть стековая серия коммутаторов - 5328, коммутаторы доступа 2328 и остальные. Для стэков есть отдельные OID на каждый коммутатор в стеке и процессор в нём. Для 2328 используюется устаревшая ветка OID. Поэтому, получаем:

{
  "$metric": "CPU | Usage",
  "$type": "match",
  "$matchers": {
    "is_5328": {
      "platform": {
        "$regex": "5328"
            }
        },
    "is_2328": {
      "platform": {
        "$regex": "2328"
            }
        }
    },
  "$match": [{
    "$match": "is_2328",
    "oid": "1.3.6.1.4.1.2011.2.23.1.18.1.3.0",
    "path": ["","","", "Current_Load"],
    "$type": "oid",
    "type": "gauge",
    "scale": 1
  },{
    "$match": "is_5328",
    "$type": "slot",
    "oid": "1.3.6.1.4.1.2011.6.3.4.1.2.{{ hwSlotIndex }}"
   },{
    "$type": "oid",
    "oid": "1.3.6.1.4.1.2011.6.3.4.1.3.0.0.0",
    "type": "gauge",
    "scale": 1
  }]
}

Генератор профиля

Есть возможность написать свой генератор, если не подходит какой-либо из стандартных. Конфиг, при этом выглядит так:

{
  "$metric": "CPU | Load | 1min",
  "$type": "slot",
  "oid": "1.3.6.1.4.1.2011.6.3.4.1.3.{{ hwSlotIndex }}"
}

В данном случае в качестве OID’a записывается шаблон. Заместо переменной {{ hwSlotIndex }} будет подставлено значение из генератора. В поле $type записывается имя созданного генератора (уникально в пределах профиля). Сам генератор помещается в скрипт get_metrics соответствующего профиля. Н-р:

from noc.sa.profiles.Generic.get_metrics import Script as GetMetricsScript
from noc.sa.profiles.Generic.get_metrics import OIDRule
from noc.core.mib import mib

class SlotRule(OIDRule):
    # Имя генератора, должно совпадать с параметром $type в конфиге
    name = "slot"

    def iter_oids(self, script, metric):
        """
        Основной метод, должен вернуть переменные для подстановки в шаблон и путь (path)
        """
        sysSlotIndex = [0]
        i = 1
        r = {}
        # Здесь мы используем значение CAPS для определения правильного числа коммутаторов в стэке
        if script.has_capability("Stack | Member Ids"):
            sysSlotIndex = [int(index) for index in script.capabilities["Stack | Member Ids"].split(" | ")]
        elif script.has_capability("Stack | Members"):
            # Индексы коммутаторов в стеке делаем списком
            sysSlotIndex = range(1, script.capabilities["Stack | Members"] + 1)
        else:
            sysSlotIndex = [1]

        for ms in sysSlotIndex:
            r[str(i)] = "%d" % ms
            # r[str(i)] = {"healthModuleSlot": ms}
            i += 1

        for i in r:
            """
            В цикле обходим индексы и формируем переменную `hwSlotIndex`, для получения нормального OID'a используем метод `self.expand` передавая ему словарь с переменными и шаблон OID (`self.oid`)
            """
            if self.is_complex:
                # Это проверка на наличие нескольких OID (если их необходимо передавать в функцию для расчёта)
                gen = [mib[self.expand(o, {"hwSlotIndex": r[i]})] for o in self.oid]
                path = ["0", "0", i, ""] if "CPU" in metric.metric else ["0", i, "0"]
                if gen:
                    # self.type и self.scale - берутся из конфига. При необходимости, можно задавать другие параметры и получать к ним доступ здесь
                    yield tuple(gen), self.type, self.scale, path
            else:
                oid = mib[self.expand(self.oid, {"hwSlotIndex": r[i]})]
                path = ["0", "0", i, ""] if "CPU" in metric.metric else ["0", i, "0"]
                if oid:
                    yield oid, self.type, self.scale, path


Сбор метрик по CLI

В случае сбора метрик по CLI необходимо писать реализацию полноценного скрипта get_metrics для работы по CLI.

Для примера, возьмём скрипт сбора сессий пользователей для профиля Juniper.JunOSe

from noc.sa.profiles.Generic.get_metrics import Script as GetMetricsScript
from noc.lib.text import parse_table

class Script(GetMetricsScript):
    name = "Juniper.JUNOSe.get_metrics"

    CLI_METRICS = set(["Subscribers | Summary"])
    # Полезно указывать, какие метрики скрипт может собирать. Это исключит его запуск при сборе других метрик.

    def collect_profile_metrics(self, metrics):
        # Основной метод. При вызывается при старте скрипта 
        if self.has_capability("BRAS | PPTP"):
            self.logger.debug("Merics %s" % metrics)
            # Проверяем, что есть соответствующий CAPS и метрики, которые мы можем собрать
            if self.CLI_METRICS.intersection(set(m.metric for m in metrics)):
                # Запускаем функцию сбора. Делить скрипт на функции необязательно, но полезно для удобочитаемости
                self.collect_subscribers_metrics(metrics)

    def collect_subscribers_metrics(self, metrics):
        # if not (self.ALL_SLA_METRICS & set(metrics)):
        #     return  # NO SLA metrics requested
        ts = self.get_ts()
        # Получаем время (timestamp) и запускаем функцию сбора значений метрик с устройства
        m = self.get_subscribers_metrics()
        for bv in metrics:
            # обходим метрики (в данной переменной содержатся все метрики переданные для сбора)
            if bv.metric not in self.CLI_METRICS:
                # Если мы не можем собирать метрику - то пропускаем
                continue
            for slot in m:
                # set_metrics передаёт собранную метрику для отдачи дискавери.
                self.set_metric(
                    id=bv.id,
                    metric=bv.metric,
                    value=m[slot],
                    ts=ts,
                    path=["0", slot, ""]
                )

    def get_subscribers_metrics(self):
        """
        Returns collected subscribers metric in form
        slot id -> {
            rtt: RTT in seconds
        }
        :return:
        """
        v = self.cli("show subscribers summary slot")
        v = v.splitlines()[:-2]
        v = "\n".join(v)
        r_v = parse_table(v)
        if len(r_v) < 3:
            return {}
        # r = defaultdict(dict)
        r = dict(r_v)
        return r


Что-то пошло не так (Отладка)

Возможно разное. Если после выполненных настроек красивые графики не появились, или, внезапно, канули в болото - необходимо разобраться в причинах и починить.

Для выяснение причин отсутствия графиков имеет смысл повторно пройти все этапы настройки и проверить, не пропущена ли где запятая. Если таковую найти не удалось - идём проверять по порядку участия в PM:

Проверка выполненных настроек и дискавери.

Для начала, необходимо заглянуть в лог периодик дискавери. Проверить дату последнего запуска и заглянуть в лог. При нормальной работе там можно увидеть:

|metrics]  Collecting metrics
|metrics]  SLA not configured, skipping SLA metrics
|metrics]  SLA metrics are not configured. Skipping
|metrics]  Spooling 14 metrics

Если при этом метрик мы не видим (на графиках), то смотрим в сторону писателя (chwriter) и интерфейса графаны.

Если мы видим что-то, навроде этого:

|metrics]  Collecting metrics
|metrics]  SLA not configured, skipping SLA metrics
|metrics]  SLA metrics are not configured. Skipping
|metrics]  No metrics found

No metrics found - То имеет смысл пойти разбираться что не так в плане доступа к устройству по SNMP.

Если же мы видим слова:

  • Interface metrics are not configured. Skipping - необходимо проверить назначены ли метрики на профили интерфейсов и профили интерфейсов на интерфейсы
  • SLA not configured, skipping SLA metrics - проверить профили SLA

Проверка реквизитов доступа.

Необходимо проверить, что устройство доступно с активатора по SNMP. Это делается путём запуска скрипта

#./noc script get_uptime MONAME

Если с устройства успешно считался Uptime, то доступ по SNMP есть. И необходимо проверить capabilities на страничке с устройством.

Мы всё сделали, а данных таки нет. Попробуем выяснить - в каком месте может возникнуть проблема.

Проверка работы дискавери

Проверка работы дискавери осуществляется командой: 

#./noc discovery --debug run periodic MONAME

У неё достаточно длинный вывод, в нём необходимо зафиксировать несколько моментов:

  • metrics] Collecting metrics: - после неё идёт перечень метрик, запрашиваемых с активатора
  • [sae] [CALL<] sae.get_credentials (24.18ms), [activator-KAMCHATKA] [SYNC CALL>] - после идёт перечень реквизитов доступа, отправленных на активатор. Необходимо проверить community и поддерживаемые версии SNMP (v1, v2 …)
  • metrics] [Interface | Packets | Out||||Ethernet1/28] Old value: 8.88965844237e+18@1509298271847603200, new value: 8.89067827806e+18@1509300231354959104показатель того, что новые значения получены и идёт расчёт метрик
  • |metrics] Spooling 154 metrics - количество собранных метрик
  • |metrics] 0 alarms detected - отработка порогов
  • Отправляемы метрики
Collected CH data:
Fields: %s interface.date.ts.managed_object.path.discards_out.errors_in.load_in.load_out.status_oper
2017-10-30      2017-10-30 04:03:51     6119069133381749519     ['','','','Ethernet1/16']       0       0       56209   2822339 1
Fields: %s memory.date.ts.managed_object.usage
2017-10-30      2017-10-30 04:03:51     6119069133381749519     95

Проверка писателя.

Достаточно заглянуть в его лог. Там должны быть сообщения о записи метрик:

[chwriter] [interface.date.ts.managed_object.path.discards_in.errors_out.load_in.load_out.packets_in.packets_out.status_admin.status_oper] 58 records sent in 11.94ms
[chwriter] [ping.date.ts.managed_object.rtt.attempts] 86 records sent in 2.75ms
[chwriter] [interface.date.ts.managed_object.path.discards_out.errors_in.load_in.load_out.status_oper] 215 records sent in 9.37ms
[nsq.client] [stage-wrk:4150:chwriter:chwriter] received heartbeat
[chwriter] Feeding speed: 38.10records/sec, active channels: 11, buffered records: 284
[chwriter] [memory.date.ts.managed_object.path.usage_5s] 1 records sent in 5.35ms
[chwriter] [cpu.date.ts.managed_object.path.load_5s] 1 records sent in 2.81ms

Если есть какие-то проблемы с записью в БД в логе будут ругательные сообщения.

Проверка CH

Для этого необходимо подключиться к БД и повыполнять запросы к данным.
Команда для подключения: 

clickhouse-client -h 0.0.0.0, если не настрены права, или clickhouse-client -u USERNAME --password PASSWORD -h 0.0.0.0
Далее:
:) use noc
:) show tables
:) select * from interface order by ts desc limit 10


Посмотреть отображаются ли данные и время последних записей. Если в данных пусто, а лог писателя говорит что они записаны… То необходимо подсмотреть в логе сервера ClickHouse

Отладка скрипта сбора метрик

Чтобы проверить, нет ли ошибки в скриптах, можно воспользоваться механизмом отладки, только, дополнительно передать в скрипт парметры. Делается это так:

# ./noc script --debug Cisco.IOS.get_metrics "xxx-sw61" metrics:='[{"metric": "Environment | Voltage", "id": 0}]'
.....
 Result: [{'scale': 1.0, 'name': 'Memory | Usage', 'tags': {'object': None}, 'ts': 1469865495320386816, 'value': 49.583421519590374, 'type': 'gauge'}]


Уточнения


  • No labels