1

如果满足某些条件,我有一个 clojure 代码(riemann)来发送电子邮件。在将事件传递给 riemann 服务器时,我遇到了一些问题。

黎曼码

(let [email (mailer {"......"})]

  (streams
    (where (service "system_log")

        (by :RefNo
         (smap
          (fn [events]
           (let [count-of-failures (count (filter #(= "Failed" (:Status %)) events))]        
              (assoc (first events)
                :status "Failure"
                 :metric  count-of-failures 
                 :total-fail (>= count-of-failures 2))))

          (where (and (= (:status event) "Failure")
                      (:total-fail event))

            (email "XXXXX@gmail.com"))prn)))))

黎曼服务器中的 O/P

WARN [2015-11-18 05:24:49,596] defaultEventExecutorGroup-2-2 - riemann.streams - riemann.streams$smap$stream__3695@7addde9e threw
java.lang.IllegalArgumentException: Key must be integer
        at clojure.lang.APersistentVector.assoc(APersistentVector.java:335)
        at clojure.lang.APersistentVector.assoc(APersistentVector.java:18)

更新 2:

我只是将 smap 更改为 sreduce。我应该如何更新,因为我是新手,所以我对根据您的建议更改代码有点困惑

(let [email (mailer {"......"})]

      (streams
        (where (service "system_log")

            (by :RefNo
             (sreduce
              (fn [events]
               (let [count-of-failures (count (filter #(= "Failed" (:Status %)) events))]        
                  (assoc (first events)
                    :status "Failure"
                     :metric  count-of-failures 
                     :total-fail (>= count-of-failures 2))))

              (where (and (= (:status event) "Failure")
                          (:total-fail event))

                (email "XXXXX@gmail.com"))prn)))))

更新 3:

我已经更新了我的代码,coalescesmap有了它的孩子。现在它没有显示任何错误,但电子邮件没有被触发。我越来越count-of-failures0。我想count function是行不通的。

(let [email (mailer {"......"})]

          (streams
            (where (service "system_log")

                (by :RefNo
                 (coalesce
                   (smap
                  (fn [events]
                   (let [count-of-failures (count (filter #(= "Failed" (:status %)) events))]        
                      (assoc (first events)
                        :status "Failure"
                         :metric  count-of-failures 
                         :total-fail (>= count-of-failures 2))))

                  (where (and (= (:status event) "Failure")
                              (:total-fail event))

                    (email "XXXXX@gmail.com"))))prn))))
4

1 回答 1

1

在我的帽子顶部,by接受一个矢量而不是一个符号:

(by [:Refno] ...

作为旁注,我建议使用 REPL(例如https://github.com/aphyr/riemann/wiki/playing-with-the-REPL),这样您就可以在测试 REPL 中的功能时逐步构建流处理。它对我很有用。

更新:我也不确定你是否不应该将 where 嵌套在里面,smap因为你正在分配“失败”但是where并行运行,smap所以除非我错过了一些东西,否则我认为它不会看到它。

更新 2:我已经通过连接到 Riemann 的 REPL 运行它,如下所示:

(require '[riemann.streams :refer :all])
(def f (stream
        (where (service "system_log")
               (by :RefNo
                   (smap
                    (fn [events]
                      (let [count-of-failures (count (filter #(= "Failed" (:Status %)) events))]
                        (prn events)
                        (assoc (first events)
                               :status "Failure"
                               :metric  count-of-failures 
                               :total-fail (>= count-of-failures 2))))

                    #_(where (and (= (:status event) "Failure")
                                  (:total-fail event)))
                    prn)))))
(f {:RefNo 4444 :service "system_log" :status "Failed"})

它会产生与您相同的错误。出现错误是因为您假设传递给的函数smap接收事件列表。它没有,它接收一个事件(见prn那里)。调用firsthashmap 会生成一个向量,然后尝试assoc使用符号作为键会给您带来错误,因为向量仅支持整数。

您不能以这种方式计算失败,就像您不会map为此目的在 Clojure 中使用正则一样,因为您需要过去的事件。

这是我认为可能与您的 smap 示例兼容的内容。

任何一个:

  1. 使用 coalesce http://riemann.io/api/riemann.streams.html#var-coalesce和 smap 作为它的孩子;我认为 smap 会收到您最初想要的事件列表。我没有尝试过,但没有理由它不应该工作。

  2. 您可以通过发送具有 1 小时 TTL 的事件并查询流中的索引来控制所需的时间窗口(假设每小时最多 2 次故障)。这是一个完整的例子:http ://riemann.io/howto.html#query-the-index-from-within-a-stream

除此之外,我认为:Status应该是小写的。我希望它有所帮助。

于 2015-11-18T14:20:27.853 回答