编写规则简介

规则文件的组织

进行报警判定的规则是由 Clojure 语言编写的,放在 rules 文件夹中。

这些规则将由 Riemann 进行执行, Riemann 会接受从 transfer 发来的指标,交给编写的规则进行判定,然后再发送给 alarm 进行报警。

规则的 .clj 文件需按照约定放在单层的文件夹下,并且 namespace 需要与文件夹和文件名对应。 文件中所有以 -rules 结尾的公开变量都会被当做 riemann 流来做判定。

Copy & Paste 的正确姿势

因为通常规则文件长得都差不多,所以推荐找一个附带的规则 Copy & Paste 一下, 比如,我想添加一个 foo/bar.clj 作为 foo 服务下关于 bar 的监控, 那么就随便找一个文件夹中的规则(最外层的不行!),然后修改 ns 为 foo.bar , 然后挑一个规则复制进来,规则的名字改成 foo-bar-rules ,然后按照需求修改规则就好了。

(ns infra.memcache ; 这里要修改
  (:use riemann.streams
        agent-plugin
        alarm))

(def infra-memcache-rules ; 这里名字要修改
  (where (host #"cache\d+$") ; 规则当然也要改
    (plugin-dir "memcache")
    (plugin "net.port.listen" 30 {:port 11211})

    (where (and (service "net.port.listen")
                (= (:port event) 11211))
      (by :host
        (judge-gapped (< 1) (> 0)
          (alarm-every 2 :min
            (! {:note "memcache 端口不监听了!"
                :level 0
                :groups [:operation :api]})))))))

修改成

(ns foo.bar
  (:use riemann.streams
        agent-plugin
        alarm))

(def foo-bar-rules ; 随便叫什么但是一定要以 -rules 结尾
  (where (host "host-which-run-foo-bar")
    (plugin-dir "foo/bar") ; 要运行 foo/bar 目录里的插件
    (plugin "net.port.listen" 30 {:port 12345}) ; 运行 net.port.listen 插件,30秒一次,以及参数

    (where (and (service "net.port.listen")
                (= (:port event) 12345)) ; 匹配 net.port.listen 插件收集的 metric
      (by :host ; 按照 host 分成子流(这个例子里就只有一个 host 所以并不会分)
        (judge-gapped (< 1) (> 0)  ; 根据条件设置事件的 :state
          (alarm-every 2 :min ; 如果是 :problem 每2分钟发一次报警。
            (! {:note "foobar 服务端口不监听了!"
                :level 0
                :groups [:operation :api]})))))))

commit 然后 push 上去就会生效了。

事件流的组织

所有的事件汇集到 Riemann 之后,你看到的是一个由所有机器、服务收集上来的指标组成的一个单一的事件流, 或者说,每一个 (def xxx-yyy-rules ...) 都能够看到整个集群(或者n个集群,看你是怎么部署的了)所有的指标, 你需要做的是通过过滤、变换等等手段最后将你关心的东西过滤出来,判定问题并告诉 alarm。

错误处理

可以在 riemann.config 中找到相关的规则,可以修改报警级别和报警组(与正常的规则一样)。

监控规则 Reload 失败后还会用老规则,所以不用担心。

发送报警

流向 发送报警(!) 流的事件都会发送到 alarm 进行报警。 但是不能直接把事件喂给 发送报警(!) ,因为 发送报警(!) 并不知道这个事件是正常还是有问题的状态, 所以需要指定事件的状态是 :ok 还是 :problem 。 通常可以用 judgejudge-gapped 这两个流来完成。

Riemann 提供的文档

在 Riemann 中可用的流不仅仅是这里介绍的,还可以参考 Riemann 官方文档 ,还有很多不常用函数/流在里面有介绍。