Clojure:riemann.streams $ smap $ stream IllegalArgumentException:Key必须是整数

时间:2015-11-18 13:49:01

标签: clojure riemann

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

黎曼代码

Ivan

 123456
Student added
Georgi

,▒( 654321
Student added
Teacher added
Teacher added
Teacher added
Teacher added
E 0▒( 2673448E 0▒( 2673448

riemann服务器的O / P

(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)))))

更新2:

我只是将smap改为sreduce。我应该如何更新,因为我是新手,我对根据你的建议更改代码感到困惑

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)

更新3:

我已使用(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))))) 更新了我的代码,而coalesce有其子代。现在它没有显示任何错误,但电子邮件没有被触发。我的smapcount-of-failures。我猜0无效。

count function

1 个答案:

答案 0 :(得分:1)

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

(by [:Refno] ...

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

更新:我也不确定你是否应该在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)。在哈希映射上调用first会生成一个向量,然后尝试使用符号作为键的assoc会给出错误,因为向量仅支持整数。

你无法以这种方式计算失败,就像你不会在Clojure中使用常规map那样,因为你需要过去的事件。

以下是我认为可能与您的示例兼容的内容。

或者:

  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

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