Ad Widget

Collapse

LLD macros в ключе НЕдинамического итема в выражении динамического триггера.

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Lurker
    Member
    • Nov 2016
    • 83

    #1

    LLD macros в ключе НЕдинамического итема в выражении динамического триггера.

    LLD дискавер возвращает список PSU. в LLD максросах есть:
    {#swnum}-содержит номер свича в стеке в вормате Sw* или nostak если стека нет.
    {#module}-содержит значение module\nomodule. Разные виды надо учитывать раздельно
    итемы создаются.
    далее я создал 18 итемов, которые считают количество PSU (9 вариантов значений может принять swnum и 2 варианта значений может принять module 9x2=18)
    ключ имема, который считает общее количество, например, такой psu.count.[module,Sw1] тоже всё корректно считается.
    Вопрос: почему, если я указываю в прототипе триггера
    last(/ciscoEnvMonMib PSU_FAN_Temp/psu.count.[{#MODULE},{#SWNUM}])=1
    то zabbix ругается
    Incorrect item key "psu.count.[{#MODULE},{#SWNUM}]" provided for trigger expression on "ciscoEnvMonMib PSU_FAN_Temp".
    И как этого избежать?

    Есть ещё вариант сделать итемы, которые считают количество PSU через прототипы. Но мне непонятно как себя поведёт заббикс когда попытается создать итем с ключём уже существующего итема. Если просто не создаст новый итем, то всё хорошо. Просто проверить прокатит или нет не хочется т.к. хз насколько поведение будет стабильным.
  • Kos
    Senior Member
    Zabbix Certified SpecialistZabbix Certified Professional
    • Aug 2015
    • 3404

    #2
    Originally posted by Lurker
    И как этого избежать?
    Ну, как бы да - при создании такого прототипа триггера Zabbix не может проверить, что присутствующий в нём элемент данных существует. Если вы такие айтемы создаёте руками, то и триггеры для них нужно создавать руками, а если хотите триггеры создавать через LLD из прототипов, то и айтемы нужно создавать тем же способом.

    Originally posted by Lurker
    Есть ещё вариант сделать итемы, которые считают количество PSU через прототипы. Но мне непонятно как себя поведёт заббикс когда попытается создать итем с ключём уже существующего итема. Если просто не создаст новый итем, то всё хорошо. Просто проверить прокатит или нет не хочется т.к. хз насколько поведение будет стабильным.

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

    Comment

    • Lurker
      Member
      • Nov 2016
      • 83

      #3
      Я готов поэкспериментировать, но я не понимаю как сделать правильную логику создания триггера.
      Рассмотрим самый правильный вариант.
      допустим есть стек из 2х коммутаторов. В одном коммутаторе 2 бп, в другом 1.
      LLD дискаверя Блоки питания должен создать по итему для каждого БП и по триггеру для каждого коммутатора, в котором сослаться на все найденные БП текущего коммутатора.
      Как это сделать?
      На данный момент препроцессингом LLD я имею итемы блоков питания в параметрах ключей которых указан номер свича в стеке (или nostack если стека нет)

      P.S. В исходном посте я пытался сделать более простой вариант: создавать триггер для каждого БП, но в описании выводить общее количество БП для коммутатора.
      P.P.S. Вообще самым правильным было бы считать количество БП в каждом из статусов и на основе этого рисовать проблему. Но подсчёт отпределённых значений в разных итемах обещают сделать только в zabbix 7. Пока можно считать только количество итемов с последними значениями, но без учёта значений итемов. Т.е. я могу посчитать количество БП у коммутатора, но не могу посчитать сколько из них в состоянии 1 к примеру.

      Comment

      • Kos
        Senior Member
        Zabbix Certified SpecialistZabbix Certified Professional
        • Aug 2015
        • 3404

        #4
        Originally posted by Lurker
        Рассмотрим самый правильный вариант.
        допустим есть стек из 2х коммутаторов. В одном коммутаторе 2 бп, в другом 1.
        LLD дискаверя Блоки питания должен создать по итему для каждого БП и по триггеру для каждого коммутатора, в котором сослаться на все найденные БП текущего коммутатора.
        Как это сделать?
        На данный момент препроцессингом LLD я имею итемы блоков питания в параметрах ключей которых указан номер свича в стеке (или nostack если стека нет)
        Функции агрегации вам в помощь (ссылка). Создаётся вычисляемый элемент данных с формулой, включающей функцию агрегации, которая подсчитывает что-либо сразу у всех элементов данных, подпадающих под заданный шаблон (звёздочка вместо параметра ключа).

        Originally posted by Lurker
        Вообще самым правильным было бы считать количество БП в каждом из статусов и на основе этого рисовать проблему. Но подсчёт отпределённых значений в разных итемах обещают сделать только в zabbix 7. Пока можно считать только количество итемов с последними значениями, но без учёта значений итемов. Т.е. я могу посчитать количество БП у коммутатора, но не могу посчитать сколько из них в состоянии 1 к примеру.

        Если айтем может принимать значения 0 или 1, то функцией агрегации считается сумма их последних значений - это и будет количество айтемов в состоянии "1".
        А вот если состояний может быть больше (либо значения не 0/1, а другие), то тогда хуже. Единственное, что приходит в голову (хоть это и некрасиво), - это приводить значения нужных айтемов к паре (0 либо 1) через препроцессинг; а если при этом таки нужны исходные значения - то делать дубликаты с помощью зависимых элементов данных, и такого рода предобработку навешивать уже на эти дубликаты.
        Кстати, количество отдискаверенных айтемов можно узнать при помощи функции агрегации item_count​().
        Last edited by Kos; 27-11-2023, 17:12.

        Comment

        • Lurker
          Member
          • Nov 2016
          • 83

          #5
          Originally posted by Kos
          Функции агрегации вам в помощь
          Я про них знаю, но не знаю как они тут могут решить задачу.
          я же вам написал я могу подсчитать количество элементов, но не могу подсчитать количество элементов, имеющих определённое значение.
          Если айтем может принимать значения 0 или 1
          от 1 до 6
          это приводить значения нужных айтемов к паре (0 либо 1) через препроцессинг
          у меня всего 6 возможных значений. Я могу создать 6 элементов вместо одного и присвоить 1 только тому, чьё значение сейчас в итеме без препроцессинга. Правда тут тоже вылезает нехорошая ситуация. Итемы меняют не синхронно. В результате при двух БП я могу получить что в какой-то момент у меня нет ни одного. Т.к. итемы для состояния ок, перешли уже из состояния 1 в 0, а итемы для состояния варнинг из 0 в 1 не успели перейти.
          Кстати, количество отдискаверенных айтемов можно узнать при помощи функции агрегации item_count​().
          можно. Только эта функция в моём случае работет хуже. Т.к. она считает именно количество итемов, а не количество итемов, имеющих значения.
          Ну к примеру итем создался, но не поддерживается, и item_count​()​ его посчитает за валидный. И там несколько штук таких пограничных случаев.​
          Last edited by Lurker; 28-11-2023, 08:20.

          Comment

          • Alex_UUU
            Senior Member
            • Dec 2018
            • 541

            #6
            А давайте уйдем от понятий коммутаторов, бП и т..д Это ж не относится к заббиксу?
            Из первого поста понял, что дискаверинг выдает:
            {#MODULE},{#SWNUM}
            Sw1,module
            Sw2,nomodule
            nostak,nomodule
            Sw4,module

            Ну и прекрасно должны создаваться прототипы ЭД:
            /ciscoEnvMonMib PSU_FAN_Temp/psu.count.[{#MODULE},{#SWNUM}]
            Тут их будет 4

            И, соответственно прототипы триггеров, тоже 4
            last(/ciscoEnvMonMib PSU_FAN_Temp/psu.count.[{#MODULE},{#SWNUM}])=1

            Comment

            • Kos
              Senior Member
              Zabbix Certified SpecialistZabbix Certified Professional
              • Aug 2015
              • 3404

              #7
              Alex_UUU, насколько я понял автора темы, ему надо, чтобы триггеры срабатывали не тогда, когда возвращается единица для отдельного (созданного из прототипа) элемента данных, а лишь тогда, когда она вернулась для всех элементов данных (созданных из этого прототипа на данном хосте) разом. Т.е. нужен один триггер на все сгенерированные из прототипа айтемы.
              А ещё точнее - нужно несколько вычисляемых элементов данных, которые бы показывали, у какого количества сгенерированных из прототипов айтемов в данный момент значение равно нулю, единице, двойке и т.д. (по числу возможных состояний). Хорошо хоть, количество этих состояний заранее известное, конечное и относительно небольшое (6 штук).

              Comment

              • Alex_UUU
                Senior Member
                • Dec 2018
                • 541

                #8
                Ну тогда да, сделать вычисляемые элементы для каждого состояния. Тут можно подумать над тем, чтобы они создавались автоматически. Но, что-то припоминаю, что у меня вычисляемые сбоили с макросами.
                Ну или вариант свой скрипт который через АПИ считает количество.

                Comment

                • Kos
                  Senior Member
                  Zabbix Certified SpecialistZabbix Certified Professional
                  • Aug 2015
                  • 3404

                  #9
                  Originally posted by Alex_UUU
                  Ну тогда да, сделать вычисляемые элементы для каждого состояния. Тут можно подумать над тем, чтобы они создавались автоматически.
                  Да создать-то не проблема. Проблема в том, чтобы придумать формулу для таких вычисляемых элементов, чтобы не перечислять там каждый отдискаверенный айтем вручную

                  Lurker, а исходный JSON для дискаверинга ведь наверняка формируется каким-то SNMP-запросом?
                  Тогда как идея: добавить в этот запрос ещё и те OID-ы, в которых находятся интересующие состояния (чтобы в результирующем JSON-е были их конкретные значения). Тогда такой запрос можно сделать обычным элементом данных с типом "Text" (чтобы в нём содержался полученный JSON), а затем:
                  • само правило LLD сделать зависимым от этого элемента данных (чтоб не делать ещё одного подобного запроса), при этом в предобработке с помощью JavaScript вырезать (ненужные для LLD динамические) значения, а вторым шагом предобработки делать тротлинг (чтобы зря не гонять предобработку, если сам набор модулей не поменялся);
                  • можно сделать шесть обычных (не-LLD) элементов данных, каждый из которых также будет зависимым от исходного айтема, а с помощью опять же предобработки JavaScript вычислять для него из этого JSON-а то, что душе угодно.
                  Да, нужно чуть-чуть знаний JavaScript, но сам код в обоих случаях будет довольно коротким - всего по несколько строк.
                  Last edited by Kos; 28-11-2023, 15:38.

                  Comment

                  • Lurker
                    Member
                    • Nov 2016
                    • 83

                    #10
                    А давайте уйдем от понятий коммутаторов, бП и т..д Это ж не относится к заббиксу?
                    Из первого поста понял, что дискаверинг выдает:​
                    Давайте не будем уходить, иначе вы не сможете предложить альтернативных вариантов решения, если не будете понимать зачем я делаю именно так.
                    Не совсем. он ещё выдаёт {#snmpindex} что очевидно, поэтому я об этом не написал
                    Ну и прекрасно должны создаваться прототипы ЭД:
                    /ciscoEnvMonMib PSU_FAN_Temp/psu.count.[{#MODULE},{#SWNUM}]
                    Тут их будет 4

                    И, соответственно прототипы триггеров, тоже 4
                    last(/ciscoEnvMonMib PSU_FAN_Temp/psu.count.[{#MODULE},{#SWNUM}])=1​
                    в данном случае вы создали подсчёт количества блоков питания и проверку этого количества, но вы не проверили состояние блоков питания.
                    (ну и не создали сами элементы, впрочем это не проблема) например:
                    last(/ciscoEnvMonMib PSU_FAN_Temp/psu.status.[{#MODULE},{#SWNUM},{#SNMPINDEX}])=4
                    насколько я понял автора темы, ему надо
                    Это идеальный вариант, который будет в zabbix 7. Пока я пытался сделать:
                    дискавер создаёт N элементов
                    psu.status.[{#MODULE},{#SWNUM},{#SNMPINDEX}]
                    и M элементов
                    psu.count.[{#MODULE},{#SWNUM}]
                    где m<=n
                    далее мне нужно создать m триггеров, в каждом из которых я сошлюсь на
                    один psu.count.[{#MODULE},{#SWNUM}]
                    и 1 или более psu.status.[{#MODULE},{#SWNUM},{#SNMPINDEX}]

                    Ну так должно быть в идеале. По факту лучшее чего я добился это создавать N триггеров. И вся польза от psu.count.[{#MODULE},{#SWNUM}] состоит в том, что я могу в описании триггера вывести общее количество БП,
                    Условно говоря мне прилетает алерт: ваш БП помирает, я хватаюсь за сердце, смотрю в описание триггера и вижу что у этого коммутатора их 2 и меня отпускает. А по хорошему мне нужно было сгенерировать аллерт низкой важности т.к. есть запасной БП.


                    а исходный JSON для дискаверинга ведь наверняка формируется каким-то SNMP-запросом?
                    если я вас правильно понял,
                    discovery[{#POWERSUPPLYNAME},1.3.6.1.4.1.9.9.13.1.5.1.2]
                    а JSON это строка, которую я препроцессю?
                    а затем он препроцессится, чтобы создать {#MODULE}, {#SWNUM}
                    Code:
                    var i, n, val, swnum, value2 = '';
                    //add information about sw number in stack
                    value = value.split('},{');//to array
                    value.push(value.pop().slice(0,-2));
                    for (i = 0, n = value.length; i < n; i++) {
                    val=value[i];
                    swnum = val.match(/"{#POWERSUPPLYNAME}":"Sw(itch )?[1-8]/);
                    if (swnum != null){
                    swnum=swnum.toString().slice(0, -1);
                    swnum = swnum.replace('"{#POWERSUPPLYNAME}"','"{#SWNUM}"') ;
                    swnum = swnum.replace('Switch ','Sw');
                    }else{
                    swnum='"{#SWNUM}":"nostack'
                    }
                    value2 = value2 + val + "," + swnum +'"},{';
                    }
                    value=value2.slice(0,-3)+"}]";
                    //add information about module\no module psu
                    value = value.split('},{');//to array
                    value.push(value.pop().slice(0,-2));
                    value2 = '';
                    for (i = 0, n = value.length; i < n; i++) {
                    val=value[i];
                    swnum = val.toLowerCase().match(/"{#powersupplyname}":".*module( )?[0-9]*/);
                    if (swnum != null){
                    swnum=swnum.toString()//.slice(0, -1);
                    swnum = swnum.match(/module( )?[0-9]+/).toString().match(/[0-9]+/);
                    swnum = '"{#MODULE}":"module '+swnum
                    }else{
                    swnum='"{#MODULE}":"nomodule'
                    }
                    value2 = value2 + val + "," + swnum +'"},{';
                    }
                    value=value2.slice(0,-3)+"}]";
                    return(value);​
                    Тогда как идея
                    я понял что мне нужно сделать джаваскриптом, и я могу это сделать, но вот с точки зрения заббикса LLD, зависимый от итема, я такого не умею.
                    Я пока склоняюсь к тому, чтобы оставить всё в текущем состоянии(и так сойдёт). а в zabbix 7 подобный функционал будет из коробки.

                    Comment

                    • Kos
                      Senior Member
                      Zabbix Certified SpecialistZabbix Certified Professional
                      • Aug 2015
                      • 3404

                      #11
                      если я вас правильно понял,
                      discovery[{#POWERSUPPLYNAME},1.3.6.1.4.1.9.9.13.1.5.1.2]
                      а JSON это строка, которую я препроцессю?​
                      Да. Насколько я понимаю, состояние вы берёте из соседней таблицы OID-ов, 1.3.6.1.4.1.9.9.13.1.5.1.3 (в конце тройка, а не двойка).
                      Тогда смысл такой:

                      Шаг 1.
                      Делаем обычный айтем, тип - "SNMP agent", тип информации - "Text", ключ - по вкусу, а в качестве SNMP OID подставляется такая строка:
                      Code:
                      discovery[{#POWERSUPPLYNAME},1.3.6.1.4.1.9.9.13.1.5.1.2,{#POWERSUPPLYSTATE},1.3.6.1.4.1.9.9.13.1.5.1.3]
                      Период выставляем тот, с которым хотим собирать данные о состоянии (предположим, 5 минут).
                      Жмём кнопку "Test", в ответ должны получить JSON, в котором для каждого блока питания будет указано три макроса: {#SNMPINDEX}, {#POWERSUPPLYNAME} и {#POWERSUPPLYSTATE}. Первые два нужны для дискаверинга и их значения практически не меняются; значения третьего могут меняться в зависимости от состояния.

                      Шаг 2.
                      Если нам таки нужен дискаверинг, то мы его делаем на базе этого элемента данных. Т.е. в настройках правила дискаверинга говорим, что его тип - зависимый элемент данных, в качестве основного выбираем сделанный на первом шаге, а первым шагом препроцессинга всандаливаем JavaScript со следующим кодом:
                      Code:
                      //return only members '{#SNMPINDEX}' and '{#POWERSUPPLYNAME}'
                      return JSON.stringify(JSON.parse(value),['{#SNMPINDEX}', '{#POWERSUPPLYNAME}']);​
                      Смысл этого однострочного кода: из исходного JSON-а оставить только элементы с LLD-макросами {#SNMPINDEX}, {#POWERSUPPLYNAME}, убрав {#POWERSUPPLYSTATE}.
                      Вторым шагом препроцессинга добавляем тротлинг с интервалом, скажем, 1 час (чтобы не дёргать дискаверинг каждые 5 минут), ну и далее - по вкусу.

                      Шаг 3.
                      В принципе, если мы хотим иметь в результате дискаверинга элементы данных, содержащие состояние блоков питания, до даже необязательно делать для них прототипы с типом SNMP - можно тоже делать их зависимыми от элемента данных, созданного на шаге 1, и извлекать нужный фрагмент JSON-а через препроцессинг. Если нужны какие-то ещё айтемы, создаём нужные прототипы здесь.

                      Шаг 4.
                      Создаём 6 элементов данных - по одному на каждое из возможных состояний (безо всяких LLD, просто обычные айтемы). Предположим, они будут содержать количество блоков питания на данном устройстве, находящихся в данном конкретном состоянии. Тогда тип информации для них будет - целочисленный, а тип - таки снова "Зависимый", а в качестве основного - тот же айтем, созданный на шаге 1. А в препроцессинге пишем простой код, примерно так (например, для состояния "2"):
                      Code:
                      var i, result=0;
                      
                      //transform source string into JSON object
                      var val_json=JSON.parse(value);
                      
                      //process JSON in loop
                      for (i in val_json) {
                        if ( val_json[i]['{#POWERSUPPLYSTATE}'] == '2' ) {
                          result++;
                        }
                      }
                      
                      //output result
                      return result;

                      Собственно, всё

                      Comment

                      Working...