2015-07-07 2 views
0

Я должен проверить количество отсчетов, отображаемых в событии, с каждым интервалом каждые 30 секунд. Если значение счета больше 5, мне нужно вызвать электронное письмо.Счет событий в определенный промежуток времени в riemann

Я использую приведенный ниже код, но электронная почта не срабатывала.

(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 "[email protected]"})] 
     (streams 
      (where (and (:status "login failures") 
         (:totalFail true)) 
      (email "[email protected]"))))))) 

Куда я иду не так?

+0

Есть довольно много недостающих частей на этом фрагменте, но независимо от того, что есть некоторые очевидные неправильные выражения как '(и (: статус «неудачи входа») (: totalFail true)) '(он всегда будет производить nil).Я предлагаю вам проверить строку за строкой в ​​REPL и использовать другой поток, чтобы периодически проверять значение счетчика, заключенное в [atom] (https://clojuredocs.org/clojure.core/atom) –

ответ

0

Здесь есть пара вопросов. Я попытаюсь рассмотреть некоторые из них, а затем опубликовать минимальный рабочий пример:

  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 ...)})) 
        ...) 
    
  2. Для расчета totalFail помните, что вы должны использовать префикс нотацию для вызова >, поэтому он должен быть (> totalFail 5). И boolean не нужен, так как > уже будет возвращать логическое значение.

  3. Я хотел бы инициализировать почтовую программу из верхнего уровня streams вызова, в качестве области видимости с использованием let или с def. Но он должен работать так, как есть.

  4. Вы должны передать последний where в качестве потока детей, чтобы smap, так что это должен быть второй аргумент для smap. Давайте вспомним smap docs:

    (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" 
    
  5. Последнее where не должно быть отделено streams и and предложение должно работать на event, поэтому он должен быть:

    (where (and (= (:status event) "login failures") 
          (:total-fail event)) 
        (email "[email protected]")) 
    
  6. :subject Fn для mailer должен быть передан как часть второй карты, как описано в mailer documentation

  7. Существует open issue на fixed-time-window, что делает его немного ненадежным: он не срабатывает, как только появится окно времени, но ждет, пока не будет запущено новое событие, поэтому вам может понадобиться использовать другую стратегию окон, пока это не будет исправлено.

Здесь идет полный минимальный рабочий пример на основе твоего:

(let [email (mailer {:host "localhost" 
        :port 1025 
        :from "[email protected]"})] 
    (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 "[email protected]"))))))) 
+0

Большое спасибо nberger. Ваше объяснение было потрясающим, и я научил меня функциональности кода. Но все-таки электронная почта не срабатывала, поскольку вы сказали, что ошибка в фиксированном окне. Я удалил фиксированное окно. Осталось последнее, когда условие в моем коде не работало. – Mangoski

+0

Несмотря на то, что я удалил и условие из своего кода, но все же я столкнулся с той же проблемой. Я отправляю свой последний код для вашего обзора. – Mangoski

+0

(пусть [по электронной почте (почтовик {...})] (потоки (где (и (услуга "system_log") (не (просрочен? Событие))) (ПДО (Fn [события] (let [count-of-failures (count (of error) (= «IE» (: описание%)) события))] (события {: состояние «неудачи входа» : показатель количества ошибок : fail (> count-of-failures 5)}))) (где (= (: статус-событие) "логин-неудачи") (электронная почта "[email protected]")))))) – Mangoski