Количество событий в определенный промежуток времени в Римане
Я должен проверить количество отсчетов, появляющихся в событии на каждом интервале каждые 30 секунд. Если число больше 5 означает, мне нужно вызвать электронное письмо.
Я использую приведенный ниже код, но электронная почта не сработала.
(let [userindex1 (default :ttl 300 (update-index (index)))]
(streams
prn
userindex1))
(streams
(where (and (service "system_log")
(not (expired? event)))
; fixed-time-window sends a vector of events out every 30 seconds
(fixed-time-window
30
; smap passes those events into a function
(smap
(fn [events]
;Calculate the no of count of events for failure
(let [numberofFailure (count (filter #(="IE" (:description %)) events))]
{:status "login failures"
:metric numberofFailure
:totalFail (boolean(numberofFailure > 5))}
(streams
prn
numberofFailure))))
;check if the variable status is true if condition satisfied then trigger an email
(let [email (mailer {:host "smtp.gmail.com"
:port 25
:user "aaaaa"
:pass "bbbbb"
:auth "true"
:subject (fn [events]
(clojure.string/join ", "
(map :service events)))
:from "abc@gmail.com"})]
(streams
(where (and (:status "login failures")
(:totalFail true))
(email "123@gmail.com")))))))
Куда я иду не так?
1 ответ
Здесь есть пара вопросов. Я постараюсь обратиться к некоторым из них, а затем выложу минимальный рабочий пример:
Первый fn, переданный в smap, должен вернуть событие. Это событие может быть создано с
event
илиassoc
в одно из полученных событий. В вашем примере создается простая карта (которая не будет работать, это не правильное событие), но это даже потеряно, потому что тогдаstreams
называется (который AFAIK следует вызывать только на верхнем уровне). Так что вместо:(smap (fn [events] (let [numberofFailure ...] {:status "login failures" :metric numberofFailure :totalFail (boolean ...)} (streams prn numberofFailure))) ...)
Вы должны сделать что-то вроде:
(smap (fn [events] (let [numberofFailure ...] (event {:status "login failures" :metric numberofFailure :totalFail (boolean ...)})) ...)
Вычислять
totalFail
помните, что вам нужно использовать префиксную нотацию для вызова>
так должно быть(> totalFail 5)
, А такжеboolean
не нужен, так как>
уже вернет логическое значение.Я бы инициализировал почтовик из верхнего уровня
streams
вызов, как охватывающая область видимости, используяlet
или сdef
, Но это должно работать как есть.Вы должны пройти последний
where
как дочерний поток для smap, поэтому он должен быть вторым аргументом для smap. Давайте вспомним документы Smap:(smap f & children) Streaming map. Calls children with (f event), whenever (f event) is non-nil. Prefer this to (adjust f) and (combine f). Example: (smap :metric prn) ; prints the metric of each event. (smap #(assoc % :state "ok") index) ; Indexes each event with state "ok"
Последний
where
не должен быть закрытstreams
иand
Приговор должен работать наevent
так и должно быть:(where (and (= (:status event) "login failures") (:total-fail event)) (email "123@gmail.com"))
:subject
FN дляmailer
должны быть переданы как часть второй карты, как описано вmailer
документацияЕсть открытый вопрос по
fixed-time-window
что делает его немного ненадежным: он не срабатывает, как только истекает временное окно, а ждет, пока не сработает новое событие, так что вы можете использовать другую стратегию управления окнами, пока это не будет исправлено.
Вот полный минимальный рабочий пример, основанный на вашем:
(let [email (mailer {:host "localhost"
:port 1025
:from "abc@gmail.com"})]
(streams
(where (and (service "system_log")
(not (expired? event)))
(fixed-time-window
5
(smap
(fn [events]
(let [count-of-failures (count (filter #(= "IE" (:description %)) events))]
(event
{:status "login failures"
:metric count-of-failures
:total-fail (>= count-of-failures 2)})))
(where (and (= (:status event) "login failures")
(:total-fail event))
(email "hello123@gmail.com")))))))