Clojure:riemann.streams$smap$stream IllegalArgumentException: ключ должен быть целым числом

У меня есть код 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 "[email protected]"))prn)))))

O/P на сервере riemann

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 "[email protected]"))prn)))))

Обновление 3:

Я обновил свой код, используя coalesce, а smap имеет дочерний элемент. Теперь он не показывает никаких ошибок, но электронная почта не срабатывает. Я получаю count-of-failures как 0. Я предполагаю, что 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 "[email protected]"))))prn))))

person Mangoski    schedule 18.11.2015    source источник


Ответы (1)


Сверху моей шляпы by принимает вектор, а не символ:

(by [:Refno] ...

В качестве примечания я рекомендую использовать REPL (например, https://github.com/aphyr/riemann/wiki/playing-with-the-REPL), чтобы вы могли постепенно наращивать обработку потока, тестируя функции в REPL. Это сработало отлично для меня.

Обновление: я также не уверен, что вам не следует вкладывать where внутри smap, потому что вы назначаете «Failure», но where работает параллельно с smap, поэтому, если я что-то не упустил, я думаю, что он этого не увидит. .

Обновление 2: я прогнал его через 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 с использованием символа в качестве ключа приводит к ошибке, поскольку векторы поддерживают только целые числа.

Вы не можете подсчитывать сбои таким образом, точно так же, как вы не будете использовать для этой цели обычный map в Clojure, потому что вам нужны прошлые события.

Вот то, что я думаю, может быть совместимо с вашим примером smap.

Либо:

  1. Используйте объединение http://riemann.io/api/riemann.streams.html#var-coalesce и smap как его дочерний элемент; Я думаю, что smap получит список событий, как вы и хотели изначально. Я не пробовал, но нет причин, по которым это не должно работать.

  2. Вы можете контролировать необходимое вам временное окно (скажем, максимум 2 отказа в час), отправляя события с 1 часом TTL и запрашивая индекс в потоке. Вот полный пример: http://riemann.io/howto.html#query-the-index-from-within-a-stream

Кроме того, я считаю, что :Status должно быть в нижнем регистре. Я надеюсь, что это помогает.

person Marcin Bilski    schedule 18.11.2015
comment
Я обновил свой код (by [:Refno], но все равно получаю ту же ошибку. Нужно ли заменить smap . - person Mangoski; 19.11.2015
comment
Заменив smap на sreduce, мне нужно оставить (by [:Refno] как есть или мне нужно удалить из него []. - person Mangoski; 19.11.2015
comment
Кажется работает с одним символом, поэтому, возможно, функция обрабатывает этот случай. Я использовал вектор, потому что именно так я понял ссылку. Но если работает, то работает. - person Marcin Bilski; 19.11.2015
comment
Я заменил sreduce вместо smap. Я попытался удалить `[ ] and tried without removing the [ ]` для обоих случаев, я получаю эту ошибку. "wrong number of argument(2) passed". Я не мог найти точное решение - person Mangoski; 19.11.2015
comment
Не видя кода, я предполагаю, что функция, которую вы передаете sreduce, имеет неправильную подпись. Он должен принимать два аргумента, как и для reduce. riemann.io/api/riemann.streams.html#var-sreduce - person Marcin Bilski; 19.11.2015
comment
Давайте продолжим обсуждение в чате. - person Mangoski; 19.11.2015
comment
Я обновил свой код с помощью объединения, теперь он не показывает никаких ошибок, как раньше, но электронная почта не срабатывает. - person Mangoski; 20.11.2015
comment
1. Вы исправили :Status и положение где? 2. Когда вы помещаете prn внутрь smap (как одного из его дочерних элементов), что он выводит? - person Marcin Bilski; 20.11.2015
comment
1. Да, я исправил :Status и где мне нужно изменить положение where. 2. Он печатает событие как есть, я вижу поле count-of-failure как zero. не могли бы вы проверить мой updated code 3 в вопросе и предложить свою модификацию. - person Mangoski; 20.11.2015
comment
Вот так очень сложно сказать, что может быть не так. Слишком много факторов, TTL и т. д. Вы пробовали REPL? Вы можете анализировать пайплайн и строить его постепенно, попутно проверяя свои предположения. Также см. информацию о тестировании Римана. Просто пытаться исправить это, угадывая, — не очень продуктивное использование ни вашего, ни моего времени. - person Marcin Bilski; 20.11.2015
comment
Посмотрите на мой код (обновление 2), это именно то, что вам нужно для оценки конвейера в REPL. Это намного быстрее, чем перезагружать Riemann (или перезапускать его!) каждый раз, когда вы что-то меняете, отправляете события и просматриваете результат. - person Marcin Bilski; 20.11.2015