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

Clojure:riemann.streams$smap$stream IllegalArgumentException:键必须是整数,clojure,riemann,Clojure,Riemann,我有一个clojure代码(riemann),如果满足某些条件,可以发送电子邮件。在将事件传递给riemann服务器时,我遇到了一些问题 黎曼编码 (let [email (mailer {"......"})] (streams (where (service "system_log") (by :RefNo (smap (fn [events] (let [count-of-failures (cou

我有一个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)))))
riemann服务器中的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:

我使用
coalesce
更新了我的代码,
smap
有它的子项。现在它没有显示任何错误,但电子邮件没有被触发。我的失败计数为
0
。我猜
计数功能不起作用

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

在我的帽子顶上,
by
接受向量而不是符号:

(by [:Refno] ...
作为补充说明,我建议使用REPL(例如),这样您可以在测试REPL中的函数时逐步构建流处理。这对我很有效

更新:我也不确定你是否应该在
smap
中嵌套where,因为你分配了“Failure”,但是
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
)。首先在hashmap上调用
会生成一个向量,然后尝试使用符号作为键进行
关联,会出现错误,因为向量只支持整数

您不能像在Clojure中不使用常规的
map
那样以这种方式计算失败,因为您需要过去的事件

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

要么:

  • 使用coalesce和smap作为其子级;我认为smap将收到一份活动列表,就像您最初想要的一样。我没有试过,但没有理由不起作用

  • 您可以通过发送带有1小时TTL的事件并查询流中的索引来控制所需的时间窗口(假设每小时最多2次失败)。下面是一个完整的示例:


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

    我已经更新了我的代码
    (通过[:Refno]
    ),但是我仍然得到了同样的错误。我需要替换
    smap
    。通过将
    smap
    替换为
    sreduce
    我需要保持
    (通过[:Refno]
    原样还是需要删除
    []
    从它开始。它似乎与单个符号一起工作,因此可能函数会处理这种情况。我使用了向量,因为这是我理解引用的方式。但是如果它工作,它就工作。我已经替换了
    sreduce
    ,而不是
    smap
    。我尝试删除了`[[
    ,并且尝试了不删除
    []`对于这两种情况,我都会遇到这个错误。
    “传递的参数(2)的数目错误”
    。如果不查看代码,我就无法找到确切的解决方案。我猜您传递给
    sreduce
    的函数的签名不正确。它应该包含两个参数,就像
    reduce
    一样。