Отображение нагрузки порта Eth по счетчику октетов [ошибка перехода через 0]

Started by eugene1, September 21, 2023, 08:48:08 AM

Previous topic - Next topic

eugene1

Нужно вывести график загрузки порта Ethernet. Cчетчик переданных октетов (тип Counter32) на порту раз в 10 минут переходит через ноль (переполняется).

В настройках переменной стоит:
- "Average delta per second"
- в трансформации выражение перевода в Mbps "return (($1 *  8 ) / 1024) / 1024;"



Как организовать отображение корректное ? периодически, когда новое текущее значение меньше чем предыдущее,  Delta в $1 возвращает 0, график ниже. Проблема не в переполнении счетчика, а как корректно скриптом учитывать переход через 0, в примерах нигде не нашел. Хотя задача скорее всего очень типовая и массовая.


Filipp Sudanov

Data type "Counter 32-bit" должен обрабатывать переход на 0 автоматически. Можно посмотреть в history по этому DCI - там будет колонка raw value. Покажите скриншот history в месте где raw value проходит через 0.

Возможно проблема в трансформационном скрипте - возможно за минуту набегает столько, что при умножении на 8 получается число большее, чем 32-битный integer. Для проверки можно сделать такой трансформационный скрипт (8L заставит выполнять 64-битную арифметику):

return (($1 *  8UL ) / 1024) / 1024;"

Но вообще вручную делить для получения мегабит уже не нужно - можно в свойствах DCI поставить Units "b/s" и Use multipliers "Default" или "Yes". Значение будет хранится в битах в сек и переводится при отображении. Если нужно чтоб всегда отображалось в Mbps, на закладке other options поставить Multiplier degree "Fixed to M".


eugene1

Quote from: Filipp Sudanov on September 22, 2023, 08:27:28 PMData type "Counter 32-bit" должен обрабатывать переход на 0 автоматически. Можно посмотреть в history по этому DCI - там будет колонка raw value. Покажите скриншот history в месте где raw value проходит через 0.

eugene1

Quote from: Filipp Sudanov on September 22, 2023, 08:27:28 PMНо вообще вручную делить для получения мегабит уже не нужно - можно в свойствах DCI поставить Units "b/s" и Use multipliers "Default" или "Yes". Значение будет хранится в битах в сек и переводится при отображении. Если нужно чтоб всегда отображалось в Mbps, на закладке other options поставить Multiplier degree "Fixed to M".

 Скрипт из трансформации убран. "Fixed to M" - не срабатывает ? вот результат





при этом через 0 все равно проходит результат




eugene1

Quote from: Filipp Sudanov on September 22, 2023, 08:27:28 PMВозможно проблема в трансформационном скрипте - возможно за минуту набегает столько, что при умножении на 8 получается число большее, чем 32-битный integer. Для проверки можно сделать такой трансформационный скрипт (8L заставит выполнять 64-битную арифметику):

return (($1 *  8UL ) / 1024) / 1024;"

не работает, все равно 0 отображает


eugene1

установил тип переменной в Counter-64, в скрипте трансформации оставил  "return (($1 *  8 ) / 1024) / 1024;" , результат тот же, 0 есть.


 

Filipp Sudanov

Уточнил у разработчиков - да, это сейчас оно действительно так работает. Дело в том, что переполнение счетчика может означать две вещи:
а) действительно на интерфейсе прошло столько байт, что считчик дошел до максимума и перешел через 0
б) счетчики на устройстве сбросились на 0 (рестарт устройства и т.д.)

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

Это переделаем, вот тикет https://track.radensolutions.com/issue/NX-2461

На сейчас можно вместо counter32 выбрать unsigned integer, но тогда нужно скриптом защищаться от ситуации б) - проверять что значение не слишком большое.

eugene1

Quote from: Filipp Sudanov on September 25, 2023, 04:01:21 PMНа сейчас можно вместо counter32 выбрать unsigned integer, но тогда нужно скриптом защищаться от ситуации б) - проверять что значение не слишком большое.
есть ли пример такого скрипта ?  полагаю верхний лимит отсечки в скрипте  очевидно будет:  интерфейс GE0 это  1GB = 1024Mb = 1 048 576 Kb = 1 073 741 824 b/s ?

eugene1

Quote from: Filipp Sudanov on September 22, 2023, 08:27:28 PMНо вообще вручную делить для получения мегабит уже не нужно - можно в свойствах DCI поставить Units "b/s" и Use multipliers "Default" или "Yes". Значение будет хранится в битах в сек и переводится при отображении. Если нужно чтоб всегда отображалось в Mbps, на закладке other options поставить Multiplier degree "Fixed to M".
и почему этот удобный функционал не срабатывает ?

Filipp Sudanov

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

Отображение с Mbps работает в last values. В history его не сделали еще, в 5.0 наверное будет.

eugene1

Quote from: Filipp Sudanov on September 26, 2023, 06:14:40 PMТак что лучшее, что сейчас может делать такой скрипт - возвращать еще раз последнее собранное значение - если нужно, сделаю пример.
Сделайте пожалуйста. Еще вопрос - с таким скриптом, когда интерфейс будет отключен и на нем будет реально 0 b/s, это будет корректно отражаться ?

Filipp Sudanov

Я попробовал сделать скрипт, который автоматом берет скорость интерфейса и считает лимит отсечки в 120% от скорости. Строчки trace(0, ...  пишут отладочные сообщения в лог сервера, для нормальной работы их нужно убрать.

Скрипт годится только для тех DCI, которые создавались механизмом instance discovery - у них тогда заполнен атрибут instance. Скрипт ищет интерфейс под нодой, имя которого совпадает с instance, это будет работать для агентских метрик, для snmp instance будет индексом интерфейса и в 6-й строчке вместо i->name нужно использовать i->ifIndex

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

trace(0, $dci->name . ", $1: " . $1);
lastValue = GetDCIValue($node, $dci->id);
trace(0, "lastValue: " . lastValue);
speed = 0;
for (i: $node->interfaces) {
  if (i->name == $dci->instance) speed = i->speed;
}
trace(0, "speed: " . speed);
if (lastValue == null or speed == 0) return $1 * 8; // could not do much
upperLimit = int64(speed / 8L * 1.2); // in bytes
trace(0, "upperLimit: " . upperLimit);
if ($1 > upperLimit) return lastValue;
trace(0, "returning $1*8: " . $1 * 8);
return $1 * 8;

Если интерфейс продолжает существовать и счетчики трафика на нем не меняются, то скрипт должен корректно отдавать значение 0.