0

我必须每 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")))))))

我哪里错了?

4

1 回答 1

0

这里有几个问题。我将尝试解决其中的一些问题,然后发布一个最小的工作示例:

  1. 传递给smap的第一个 fn应该返回一个事件。可以使用event或通过assoc“进入”接收到的事件之一来创建该事件。在您的示例中,创建了一个普通地图(这不起作用,这不是一个正确的事件),但它甚至丢失了,因为 thenstreams被调用(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 文档

    (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 "123@gmail.com"))
    
  6. :subjectfn formailer应作为第二张地图的一部分传递,如文档mailer中所述

  7. 有一个未解决的问题使它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")))))))
于 2015-07-07T19:36:28.927 回答