Ad Widget

Collapse

Из скрипта добавлять в базу данных zabbix несколько записей за один сеанс

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • bestick
    Junior Member
    • May 2021
    • 8

    #1

    Из скрипта добавлять в базу данных zabbix несколько записей за один сеанс

    Доброе время суток!
    Из скрипта заполняем базу данных zabbix - пишем историю. За один сеанс - один пакет данных, состоящий из нескольких записей. Пакет переменной длины.
    Т.е. в пакете может быть 5 записей или 300 записей или 1 запись или вообще ни одной.
    Структура записи - это 3 поля: Дата-время(текст), предмет(текст), его количество(число).

    Вопрос - как грамотно это реализовать, максимально просто?
    ;
    Что предпринималось:
    1. Через UserParameters - основной элемент данных в JSON и три зависимых элемента.
    Для основного элемента все хорошо - доступно любое количество записей, для зависимых - парсится только первая запись, а как достать остальные - непонятки.
    2. Использование Zabbix API - попробовал библиотеку py-zabbix от a.dubkov. Созданы три траппер элемента данных.

    from pyzabbix import ZabbixMetric, ZabbixSender
    # Send metrics to zabbix trapper
    packet = [
    ZabbixMetric('hostname1', 'Datetime', '09.05.2021 15:21:16'),
    ZabbixMetric('hostname1', 'thing', 'table'),
    ZabbixMetric('hostname1', 'count', 5)
    ]

    result = ZabbixSender(use_config=True).send(packet)

    Здесь в чем проблема? C одним packet все отлично. С двумя разными packet, которые в цикле for, в history попадает только выполнявшийся последним,
    хотя и по первому выполнявшемуся, и по второму выполнявшемуся result отличный - оба выполнены без ошибок с одним chunk. Но в history присутствует дважды(!!) только последний
    packet. Понятно, что я что-то не знаю в Zabbix )). Наверное, дело в chunk, но где он регулируется в Zabbix? Тестирую в Zabbix 5.2 на Ubuntu 20.4
  • Kos
    Senior Member
    Zabbix Certified SpecialistZabbix Certified Professional
    • Aug 2015
    • 3404

    #2
    Originally posted by bestick
    Доброе время суток!
    Из скрипта заполняем базу данных zabbix - пишем историю. За один сеанс - один пакет данных, состоящий из нескольких записей. Пакет переменной длины.
    Т.е. в пакете может быть 5 записей или 300 записей или 1 запись или вообще ни одной.
    Структура записи - это 3 поля: Дата-время(текст), предмет(текст), его количество(число).

    Вопрос - как грамотно это реализовать, максимально просто?
    Я в таких случаях вызываю в скрипте утилиту zabbix_sender (ссылка), которую вызываю с ключами "-T -i -", а ей в stdin (как правило, через конвейер) скармливаю нужные данные в правильном формате. Работает надёжно.

    Насколько я понимаю, ваш второй вариант должен делать то же самое, но через промежуточную прослойку в виде библиотеки на Python-е. Видимо, что-то не то накрутили в цикле; т.к. тоже должно работать.

    Comment

    • bestick
      Junior Member
      • May 2021
      • 8

      #3
      Originally posted by Kos
      Видимо, что-то не то накрутили в цикле; т.к. тоже должно работать.
      Ну, да, накосячил - просто к концу дня голова гудела от прочтения документации и опытов с zabbix - в send оставил старую переменную, хотя должен был брать ее с переменной цикла Сейчас все работает, спасибо вам.

      Почему-то я не смог обнаружить у себя утилиту zabbix_send, хотя рассчитывал увидеть ее с zabbix_agent

      Comment

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

        #4
        Originally posted by bestick
        Почему-то я не смог обнаружить у себя утилиту zabbix_send, хотя рассчитывал увидеть ее с zabbix_agent
        В зависимости от метода установки и версии агента утилита zabbix_sender может идти либо сразу вместе с агентом, либо в отдельном пакете.

        Comment

        • bestick
          Junior Member
          • May 2021
          • 8

          #5
          Originally posted by Kos
          Я в таких случаях вызываю в скрипте утилиту zabbix_sender (ссылка), которую вызываю с ключами "-T -i -", а ей в stdin (как правило, через конвейер) скармливаю нужные данные в правильном формате. Работает надёжно.
          Т.е. снимаете нужные данные не с экрана и потом их не парсите, а скармливаете через переменные сразу в нужном формате, а сама утилита в цикле? Если так, то очень похоже на powershell скрипты.

          Comment

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

            #6
            Originally posted by bestick
            Т.е. снимаете нужные данные не с экрана и потом их не парсите, а скармливаете через переменные сразу в нужном формате, а сама утилита в цикле? Если так, то очень похоже на powershell скрипты.
            В цикле идёт получение данных, при необходимости - их парсинг и преобразование в нужный формат (например, таймстэмпов в unixtime), а также вывод. Вывод цикла конвейером перенаправляется на вход утилиты zabbix_sender, которая вызывается один раз. Если получение и обработка данных может занимать какое-то заметное время, то в параметры команды zabbix_sender добавляется ещё и ключик "-r".

            В качестве примера - мой скрипт check_idm_drivers.sh, который анализирует состояние драйверов Novell (ныне - Micro Focus) IDM при помощи утилиты idmutil.sh.
            Распарсивая её вывод (TAB-separated), вызываем zabbix_sender дважды: сначала для отрабатывания механизма LLD (передавая JSON со списком имён драйверов), затем - для того, чтобы передать данные по каждому драйверу (его тип автозапуска и текущее состояние). При первом вызове передаётся одно значение (JSON), при втором - много значений (по два для каждого драйвера), роль цикла выполняет вызов awk.
            Code:
            #!/bin/bash
            ZABBIX_HOST=zabbix.mydomain.lv
            HOST=$(hostname -s)
            STAT=$(/usr/local/bin/idmutil.sh status)
            
            DISCOVERY=$(echo "$STAT" | awk -F"\t" '
            BEGIN {printf "{ \"data\":[ "}
              { if (FIRST!=0) {
                printf ", "
                } else {
                FIRST=1
                }
                printf "{\"{#IDM_DRIVER}\":\"" $1 "\"}"
              }
            END {printf " ] }"}
            ' )
            /usr/local/bin/zabbix_sender -z $ZABBIX_HOST -s $HOST -k idm.driver.discovery -o "$DISCOVERY" >/dev/null
            
            echo "$STAT" | awk -F"\t" '
              {
                printf "- \"idm.driver.autostart[" $1 "]\" " $3 "\n"
                printf "- \"idm.driver.state[" $1 "]\" " $2 "\n"
              }
            ' | /usr/local/bin/zabbix_sender -z $ZABBIX_HOST -s $HOST -i - >/dev/null

            Comment

            • bestick
              Junior Member
              • May 2021
              • 8

              #7
              Замечательно! Такое в документации не найдешь. Как раз то, что я хотел узнать и услышать - вариант реализации. Очень интересно!. Я вроде где-то читал в доках по zabbix, что за один раз zabbix_sender переваривает 250 записей, если читает из файла, потом, как я понимаю, пауза в связи с забором новой порции. Аналогично, мне кажется, утилита работает и со стримом. По-любому, информации у меня для решения задачи более, чем достаточно, большое вам спасибо за это.

              Comment

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

                #8
                Originally posted by bestick
                Я вроде где-то читал в доках по zabbix, что за один раз zabbix_sender переваривает 250 записей, если читает из файла, потом, как я понимаю, пауза в связи с забором новой порции. Аналогично, мне кажется, утилита работает и со стримом.
                Да, так и есть; вот этот кусок исходника из файла src/zabbix_sender/zabbix_sender.c:
                Code:
                /* sending a huge amount of values in a single connection is likely to */
                /* take long and hit timeout, so we limit values to 250 per connection */
                #define VALUES_MAX 250
                Только это не должно волновать при вызове из скриптов: 250 - это ограничение на количество значений, передаваемых за одно TCP-соединение, после чего соединение разрывается и устанавливается заново (для пересылки следующей порции). Сделано специально, чтобы не нарываться на ограничения по тайм-аутам во время пересылки большого количества данных. И, поскольку вся эта машинерия выполняется самим zabbix_sender-ом, то для автора скрипта это происходит совершенно прозрачно.

                Comment

                Working...