很久很久以前,大家都在问 Tdengine 支不支持事件报警,后来,估计是被否定的答案伤透了心,就渐渐没人问了:(。但实际上,报警用途真的非常广泛,比如:一家运输公司要监测车辆的速度,希望车辆最近五分钟的平均速度超过100km/h时,能及时提醒驾驶员。那么,这家公司可能会在 TDengine 中用下面的语句创建表结构:
create database if not exists test;
use test;
create table cars (ts timestamp, speed float) tags(id int);
create table car0 using cars tags(0);
create table car1 using cars tags(1);
create table car2 using cars tags(2);
...
然后,自己开发应用程序并使用下面的 sql 语句检测超速的车辆,再一一通知相关人员:
select avg(speed) as avgSpeed from test.cars where ts > now - 5m group by id;
这样做确实可以满足需求,但为这么简单的一个场景开发应用程序,未免有点“杀鸡有牛刀”;而且,如果规则很多,每一条都定制开发,成本也不低。
而事件报警就是为应对这类场景而生的,所以,这个功能刚刚开发完毕,我迫不及待的写出了这篇博客和大家分享。
安装
在 TDengine 的技术架构中,事件报警以单独模块的形式提供,这个模块和TDengine结合在一起,共同实现了报警功能。另外,考虑到Prometheus的AlertManager在报警管理方面很成熟,拥有庞大的用户群,报警模块目前将生成的报警信息都直接推送给了AlertManager,后续的管理工作,由用户在AlertManager上完成。
安装报警模块有两种方式:下载预编译的安装包或者从源码编译安装。
使用编译好的二进制文件
您可以从 涛思数据 官网下载最新的安装包。下载完成后,使用下面的命令解压即可:
$ tar -xzf tdengine-alert-$version-$OS-$ARCH.tar.gz
如果您之前没有安装过 TDengine 的客户端或服务端,您还需要执行下面的命令安装一下 TDengine 的动态库:
$ ./install_driver.sh
从源码安装
从源码安装需要在您用于编译的计算机上提前安装好 TDEngine 的服务端或客户端,如果您还没有安装,可以参考 TDEngine 的文档。报警模块使用 Go语言 开发,所以,编译之前,您还需要安装最新版的 Go 语言编译环境(目前是 v1.14)。这两项都准备好后,就可以用下面的命令编译了:
$ mkdir taosdata
$ cd taosdata
$ git clone https://github.com/taosdata/tdengine.git
$ cd tdengine/alert/cmd/alert
$ go build
由于墙的原因,最后一步可能会因为部分依赖包无法下载而失败,这时,您可以根据 goproxy.io 上的说明配置好 GOPROXY
再重新执行 go build
。
配置
为了让产品更好用,涛思数据一直都以“开箱即用”为目标,但具体到报警模块,因为需要 TDengine 和 AlertManager 的连接信息(这两项需分别单独安装),所以在运行它之前,需要您手工进行一些配置。
在安装后的文件夹中,有一个名为 alert.cfg 的文件,它采用的是标准 json 格式,以下是其默认内容:
{
"port": 8100,
"database": "file:alert.db",
"tdengine": "root:taosdata@/tcp(127.0.0.1:0)/",
"log": {
"level": "production",
"path": "alert.log"
},
"receivers": {
"alertManager": "http://127.0.0.1:9093/api/v1/alerts"
}
}
您可以用喜欢的文本编辑器打开它并修改其中的选项,这些选项的含义如下:
- port:报警模块支持使用
restful API
对规则进行管理,这个参数用于配置http
服务的侦听端口。 - database:报警模块将规则保存到了一个
sqlite
数据库中,这个参数用于指定数据库文件的路径(不需要提前创建这个文件,如果它不存在,程序会自动创建它)。 - tdengine:
TDEngine
的连接信息,一般来说,数据库信息应该在报警规则中指定,所以这里 不 应包含这一部分信息。 - log > level:日志的记录级别,可选
production
或debug
。 - log > path:日志文件的路径。
- receivers > alertManager:报警模块会将报警推送到
AlertManager
,在这里指定AlertManager
的接收地址。
准备好配置文件后,可使用下面的命令启动报警模块:
$ ./alert -cfg alert.cfg
编写报警规则
报警模块安装配置好后,就可以给它添加报警规则了。不过,开始前,为了便于大家更好的理解一条报警规则中要包含那些东西,我们要先来看看报警是什么:
从技术的角度,报警是指从最近一段时间的数据中筛选出符合一定条件的数据,并基于这些数据根据定义好的计算方法得出一个结果,当结果符合某个条件且持续一定时间后,触发警告并以某种形式通知用户。
仍以本文开头的监测车辆速度的场景为例,下面就是其对应的报警规则(json格式):
{
"name": "CarTooFast",
"sql": "select avg(speed) as avgSpeed from test.cars where ts > now - 5m group by id",
"expr": "avgSpeed > 100",
"period": "10s",
"for": "0s",
"labels": {
"ruleName": "CarTooFast"
},
"annotations": {
"summary": "car {{$values.id}} is too fast, its average speed is {{$values.avgSpeed}}km/h"
}
}
其中字段含义如下:
- name:用于为规则指定一个唯一的名字。
- sql:从
TDEngine
中查询数据时使用的sql
语句,查询结果中的列将被后续计算使用,所以,如果使用了聚合函数,请为这一列指定一个别名。您可能已经注意到,本例中,这条语句和本文开头的那条完全相同。 - expr:一个计算结果为布尔型的表达式,支持算数运算、逻辑运算,并且内置了部分函数,也可以引用查询结果中的列。 当表达式计算结果为
true
时,进入报警状态。 - period:规则的检查周期,默认1分钟,而在我们的例子中,是每10秒检查一次有没有车辆超速。
- for: 一个时间长度,当布尔表达式的计算结果为 true 的持续时间超过这个选项时,才会触发报警。默认为0,表示只要计算结果为 true,就触发报警。
- labels:人为指定的标签列表,标签可以在生成报警信息时引用。特别的,如果
sql
中包含group by
子句,则所有用于分组的字段会被自动加入这个标签列表中,在本例中,车辆的 id 会被自动加入标签列表。 - annotations:用于定义报警信息,使用 go template 语法,其中,可以通过
$labels.<label name>
引用标签,也可以通过$values.<column name>
引用查询结果中的列。
我们将上面的规则保存在文件 rule.json 中,然后,可以用下面的命令将规则加入报警模块:
$ curl -d '@rule.json' http://localhost:8100/api/update-rule
现在,我们尝试在TDengine中增加几条0号车的数据:
insert into car0 values(now - 4m, 90) (now - 3m, 110) (now - 2m, 120) (now - 1m, 120) (now, 100);
稍等片刻,如果一切正常,您就可以从AlertManager中看到相应报警信息了。您可以再添加一些其他车辆的数据并观察报警信息的变化。
其他
上面简单的介绍了报警模块的使用方法,更详细的信息您可以参考这个模块的文档。
另外,客观的说,报警模块目前提供的功能还不是很多,所以使用时需要结合AlertManager。但不必担心,报警管理、路由、邮件推送、微信推送、钉钉推送等功能都已经在我们的计划列表里了,如果您有任何意见和建议,也欢迎向我们反馈。