Snusmumriken
Потому что если так, то тебе достаточно прост держать счётчик: -- глобальный, на всяк случ, если данная переменная уже есть то используем её bad_counter = bad_counter or 0 ... if isGoodRequest then bad_counter = 0 else bad_counter = bad_counter + 1 end if bad_counter == 5 then sendMail(...) end Тогда вообще на каждые пять плохих запросов подряд будет слать, и если много-много плохих запросов подряд — пришлёт только один раз. Если надо в целом на каждые пять плохих — обнуляем счётчик одновременно с sendMail
halt
Вот, уже вырисовывается)
halt
а isGoodRequest откуда береться?
Snusmumriken
Ну как ты проверяешь запрос, плохой он или хороший? Вот и запихни то условие вместо isGoodRequest (но добавь not, или поменяй местами условия if и else)
Snusmumriken
Вот ща типа полностью то как оно должно быть: badreq = badreq or 0 local status = event:getHeader("State") or '' local gateway = event:getHeader("Gateway") or '' if status == "NOREG" and gateway == "mixnet" then badreq = badreq + 1 else badreq = 0 end if badreq == 5 then sendmail(...) -- если хотим чтобы отправляло на -- каждые пять плохих запросов подряд: -- badreq = 0 end
Snusmumriken
Ну, то есть на самом деле, всё простенько, сам видишь. Но это только если все запросы обрабатывает один инстанс вм, и переменная badreq общая. На нескольких машинах или если на каждый запрос/серию запросов запускается новая вм, придётся шарить переменную через базу.
halt
Вот "плохой" статус это NOREG, но gateway несколько
Snusmumriken
Тогда ставь то условие, которое тебе нужно, панимаищ? : )
halt
ну, я же могу их перечислить OR?
Snusmumriken
Можешь
Denis
А можешь и не or, а таблицей
halt
хотя нет. тогда будет считаться в общем на все гейты
Snusmumriken
А ещё можешь занести их в табличку isBad = { NOREG = true, NOREGISTER = true, BADREG = true } if isBad[status] then ... Или в такую табличку которую я приводил выше
Snusmumriken
Тебе нужна помощь с составлением условий, какой запрос плохой а какой хороший? : )
Snusmumriken
Можешь поменять местами гейты и статусы, тогда можно будет вместо if enum[status] and enum[status][gateway] then ... написать if enum[gateway] and enum[gateway][status] then ... Это не принципиально, но может быть меньше придётся заполнять, например отсутствие реакции на некоторые гейты в принципе (просто не добавляем их в enum, добавляем туда только то на что реагируем).
halt
Да я вот пока не вкурил. Условие плохое одно, но гейтов несколько. Если я сейчас так запилю, то счетчик же будет срабатывать на все NOREG. Скажем если с каждого гейта придет по одному NOREG, то оповещалка сработает
Snusmumriken
Ага
Snusmumriken
А тебе нужно чтобы на каждый гейт срабатывало по разному?
halt
Нужно чтоб каждый гейт считался
Snusmumriken
Тогда мути более сложный счётчик. -- можем использовать local, -- потому что таблички ссылочные, -- заодно инициализируем, если это первый запрос -- и её пока не существует local badReq = badReq or {} local status = event:getHeader("State") or '' local gateway = event:getHeader("Gateway") or '' -- заполняем нулём, если у нас ещё нет инфы по этому гейтвею badReq[gateway] = badReq[gateway] or 0 if status == "NOREG" then badReq[gateway] = badReq[gateway] + 1 else badReq[gateway] = 0 end if badReq[gateway] == 5 then sendmail(...) -- badReq[gateway] = 0 end
Snusmumriken
Теперь у тебя есть восхитительная табличка badReq, которая хранит все плохие статусы подряд для каждого гейтвея. Прекольно, да?
halt
Здорово)
halt
Буду пробовать
halt
Спасибо
Snusmumriken
Лучше подробно изучи луа, таблички — очень мощный инструмент. И довольно простой.
halt
Да вот как раз и пытаюсь осваивать
halt
Но без практики много непонятного. Причем я ни разу не программер
Snusmumriken
Ничо, это всё придёт с практикой. Я тоже не особо программер, хотя работаю им.
Pavel
редиска предпочтительнее тем, что можно шарить стейт между пачкой воркеров\машин
Anton
всем привет. подскажите - как передать объект в lua_State - указатель. чтобы его можно было везде достать?
Snusmumriken
https://www.lua.org/pil/28.1.html void *lua_newuserdata (lua_State *L, size_t size); static int newarray (lua_State *L) { int n = luaL_checkint(L, 1); size_t nbytes = sizeof(NumArray) + (n - 1)*sizeof(double); NumArray *a = (NumArray *)lua_newuserdata(L, nbytes); a->size = n; return 1; /* new userdatum is already on the stack */ }
Snusmumriken
Чтобы потом везде достать — передаёшь его как аргумент луа-функций.
Snusmumriken
Если хочешь чего-то похожего на ООП с луёвой стороны — вешаешь на этот указатель метатаблицу с __index равному табличке с методами объекта. Тогда сам указатель при вызове методов будет передаваться первым аргументом автоматически.
Snusmumriken
В следующих трёх главах. Стрелка вправо.
Anton
понял, спасибо
Maxim
Нужно чтоб каждый гейт считался
А пробовали prometheus посмотреть для хранения статусов? в grafana можно отображать красивые и яркие графики, а через alertmanager-bot делать рассылку сообщений при наступлении различных событий через необходимые каналы связи (почта, телеграм, slak, e.t.c), это я к тому что бы не тратить время на создание того что уже есть и можно взять коробку за даром - то есть безвозмездно. Но я мог не верно понять решаемую вами задачу и мой совет заглянуть в доку prometheus вообще не к месту
halt
Тогда мути более сложный счётчик. -- можем использовать local, -- потому что таблички ссылочные, -- заодно инициализируем, если это первый запрос -- и её пока не существует local badReq = badReq or {} local status = event:getHeader("State") or '' local gateway = event:getHeader("Gateway") or '' -- заполняем нулём, если у нас ещё нет инфы по этому гейтвею badReq[gateway] = badReq[gateway] or 0 if status == "NOREG" then badReq[gateway] = badReq[gateway] + 1 else badReq[gateway] = 0 end if badReq[gateway] == 5 then sendmail(...) -- badReq[gateway] = 0 end
Привет. Что то пошло не так... local name = event:getHeader("Event-Name") or '' local subb = event:getHeader("Event-Subclass") or '' --freeswitch.consoleLog("INFO", "Получен Event! " .. name) — Вылавливаем нужный EVENT if name == "CUSTOM" and subb == "sofia::gateway_state" then local badReq = badReq or {} local gateway = event:getHeader("Gateway") local status = event:getHeader("Ping-Status") -- заполняем нулём, если у нас ещё нет инфы по этому гейтвею badReq[gateway] = badReq[gateway] or 0 if status == "UP" then freeswitch.consoleLog("INFO", "Исходный:".. badReq[gateway] .."\n") badReq[gateway] = badReq[gateway] + 1 freeswitch.consoleLog("INFO", "Прибавили:".. badReq[gateway] .."\n") else badReq[gateway] = 0 freeswitch.consoleLog("INFO", "Статус: DOWN\n") end if badReq[gateway] == 2 then freeswitch.consoleLog("INFO", "Bingo..." ..gateway.. "\n") -- sendmail(...) -- badReq[gateway] = 0 end В итоге получаем 2019-05-30 09:24:35.671710 [INFO] switch_cpp.cpp:1365 Исходный:0 2019-05-30 09:24:35.671710 [INFO] switch_cpp.cpp:1365 Прибавили1 2019-05-30 09:24:36.331678 [INFO] switch_cpp.cpp:1365 Исходный:0 2019-05-30 09:24:36.331678 [INFO] switch_cpp.cpp:1365 Прибавили1 2019-05-30 09:24:43.731713 [INFO] switch_cpp.cpp:1365 Исходный:0 2019-05-30 09:24:43.731713 [INFO] switch_cpp.cpp:1365 Прибавили1 2019-05-30 09:24:44.391710 [INFO] switch_cpp.cpp:1365 Исходный:0
Pavel
https://m.habr.com/ru/company/toshibarus/blog/444502/
Maxim
Да, пробовал. Красиво, но для меня избыточно.
А что вам показалось избыточным?
halt
FS стоит на одноплатнике. Не хочется её захламлять
Maxim
Лог нжинкс пишешь в джсон формате тянешь его в прометеус - мониторинг готов :)
Не совсем соглашусь что сборка данных в json формате из nginx prometheus'ом - является готовым мониторингом, скорее это просто сбор и хранение данных с виеменной меткой, для того что бы это стало мониторингом необходим процесс отслеживания событий, что более ближе к мониториргу чем красивые графики на экранах в grafana
halt
Парни, а какое время жизни таблицы в Lua? badReq = badReq or {}; Записываю в таблицу данные и при следующем запросе их уже нет
Highly Likely
Технически пока на них есть ссылка, а после - до итерации GC
halt
Не знаю. Вроде как нет. Правильно ли я заполняю данными в этом случаее? Я про переменную badReq["".. gateway ..""] Т.к. значений несколько... badReq = badReq or {}; n = badReq["".. gateway ..""] or 0; badReq["".. gateway ..""] = badReq["".. gateway ..""] or n; freeswitch.consoleLog("INFO", "Записано в ': ".. badReq["".. gateway ..""': ".. badReq["".. gateway ..""] .."\n"); n = n + 1; badReq["".. gateway ..""] = n; freeswitch.consoleLog("INFO", "После прибавления: ".. badReq["".. gateway ..""] .."\n"); else badReq["".. gateway ..""] = 0; freeswitch.consoleLog("INFO", "+1\n"); end;
Highly Likely
Во что*
halt
Строка. Название гейта gateway = event:getHeader("Gateway") status = event:getHeader("Ping-Status")
Highly Likely
gateway - переменная?
halt
да
Highly Likely
Почему не использовать просто badReq[gateway] или badReq[tostring(gateway)]?
halt
да я уже по всякому пробовал. А если я запилю badReq[gateway] в название строки переменная попадет? Или все же имя строки "gateway"?
halt
В общем проблема ясна. Таблица "умирает". Живет только на 1 запрос
halt
Есть ли возможность продлить ей время жизни?
Serezha
ngx.shared ?
Maxim
Есть ли возможность продлить ей время жизни?
а что говорит ваш debug когда вы дэбажите этот сценарий?
halt
При каждом EVENTE пустые данные. Т.к. это FreeSWITCH деграет этот скрипт при наступлении события
Maxim
При каждом EVENTE пустые данные. Т.к. это FreeSWITCH деграет этот скрипт при наступлении события
так вы угадываете или вам это debuger показывает с возможностю пошагового прохождения вашего сценария?
Snusmumriken
При каждом EVENTE пустые данные. Т.к. это FreeSWITCH деграет этот скрипт при наступлении события
Это значит всего лишь то, что моё предупреждение сработало, и FreeSWITCH очищает/создаёт новую ВМ на каждый запрос.
Snusmumriken
Шарь данные через БД.
halt
Я смотрел дебаг в консоле. Данных в таблице при новом запросе нет
Snusmumriken
Вот это вот
Snusmumriken
Ну, то есть на самом деле, всё простенько, сам видишь. Но это только если все запросы обрабатывает один инстанс вм, и переменная badreq общая. На нескольких машинах или если на каждый запрос/серию запросов запускается новая вм, придётся шарить переменную через базу.
halt
Ну что же, буду курить как отправить в Redis из скрипта, и дальше эти данные считывать
halt
)
Snusmumriken
А, кстати, можешь ещё попробовать убрать local перед badReq, на всякий случай
halt
Пробовал
Snusmumriken
Ну тады глобал спейс каждый раз новый : )
Snusmumriken
Как отправить — local badReqCount = redis:hget("badReq", gateway) or 0 if isBadReq then badReqCount = badReqCount + 1 else badReqCount = 0 end redis:hset("badReq", gateway, badReqCount) ...
Snusmumriken
Редиска супер простая
Highly Likely
Редиска супер простая
Недавно видел учебник по редиске
Highly Likely
Интересно, что там можно понаписать на учебник по Редиске?
Snusmumriken
На самом деле, довольно много всего. Типа "как правильно шардировать, в чём прекол пайплайнов и как их применять чтобы было круто, как оптимизировать память, дёргать удалённые процедуры и писать оптимизированную фигню" и т.п.