2

我正在与 Riemann 一起发现/学习 Clojure,并且我编写了以下代码来汇总每个主机的 CPU 指标:

(streams
 (by [:host]
     smap (aggregate-cpu-metrics "user" folds/mean)
     smap (aggregate-cpu-metrics "nice" folds/mean)
     smap (aggregate-cpu-metrics "system" folds/mean)
     smap (aggregate-cpu-metrics "idle" folds/mean)
     smap (aggregate-cpu-metrics "wait" folds/mean)
     smap (aggregate-cpu-metrics "interrupt" folds/mean)
     smap (aggregate-cpu-metrics "softirq" folds/mean)
     smap (aggregate-cpu-metrics "steal" folds/mean)))


(defn aggregate-cpu-metrics
  [name, aggr]
  (where (service (re-pattern (str "cpu-[0-9]+ " name)))
      (coalesce 10
          (smap aggr
              (with :service (str "cpu-average " name) reinject)))))

为了稍微解释一下代码,我收到了这样的事件:

  • :服务“cpu-0 空闲”:公制 58.23
  • :服务“cpu-1 空闲”:公制 98.11
  • :服务“cpu-2 空闲”:公制 12.23

我的目标是计算平均值并将此事件重新注入 riemann :

  • :service "cpu-average" :metric 56.19

它正在工作,这不是问题。但是正如您在第 3 到第 10 行中看到的那样,这里有很多重复的代码。我正在寻找一种方法来重构这段代码,但我被困住了。

我想用我的指标名称定义一个向量:

(def cpu-metrics ["user", "nice", "system", "idle", "interrupt", "softirq", "steal"])

...并使用它来调用smap(aggregate-cpu-metrics ...

但我不知道该怎么做。我试过mapdoseq,但没有任何成功。

你会怎么做?

(更新/解决方案)

在阅读亚瑟的回答后,这是我的重构版本。

(streams
 (where
  (service #"^cpu-[0-9]+ ")
  (adjust
   [:service #(clojure.string/replace % #"^cpu-[0-9]+" "cpu-average")]
   (by [:host :service]
       (fixed-time-window 10 (smap folds/mean reinject))))))
4

1 回答 1

1

我可能会先提取名称并创建新的服务名称,然后使用服务名称和主机来拆分事件流,从而将函数从内到外翻转。

像这样的东西:

(streams 
   (where (service #"cpu-[0-9]+ ")
     (adjust [:service (fn [service] 
                         (str "cpu-average "
                              (second (clojure.string/split service #"cpu-[0-9]+ "))))]
       (by [:host :service]  ...  )))

这有一个副作用,即允许任何被报告的 cpu 服务显示在统计信息中,而无需更改您的监控代码。如果你不想要这个,你可以添加另一个where来明确接受你想要的。我这里没有设置来测试这个,所以如果代码被破坏,请编辑:-)

于 2015-02-06T22:19:00.413 回答