监控项表达式编写
在 Node.js 性能平台的监控设置中,有两项表达式需要用户进行输入,阈值表达式和报警表达式。
监控系统会根据阈值表达式来进行是否进行报警的判定。当判定完成,决定发送警报时,会使用报警表达式来描述警报的详情。
阈值表达式
阈值表达式是由 Node.js 性能平台定义的一个报警判定DSL,出于灵活性和安全的考虑,我们定义了有限的表达方式。
每个应用的开发者可以输入一个阈值表达式,该表达式会被编译为一个等价的JavaScript函数。当监控系统收到当前类型的监控数据时,会将监控数据作为上下文,代入阈值表达式,如果表达式结果为true
,则判定需要发送警报。
一个基本的表达式由三个部分组成:属性、比较操作符、字面量。
属性
属性标识是指上下文对象的属性表示方式,形式为:@xxx
,以@
开头接一个属性名。例如:@load1
、@cpu
、@freemem
。
比较操作符
比较操作符跟普通的编程语言里的符号完全相同:==
、>=
、>
、<=
、<
、!=
。
运算符
支持+
、-
、*
、/
、%
运算符,如:@heap_used / @heap_limit
。
字面量
字面量是指基本的数值类型和字符串类型。一个基本的表达式类似这样:@load1 > 5
。
include
include关键字用于属性值中是否包含某个字符串。如:@message include "TypeError"
。
其他
其他的操作符有&&
、||
以及()
。与普通编程语言表达意思相同。如:
@cpu > 0.10 || @load1 > 5
@cpu > 0.10 && @load1 > 5
@cpu > 0.10 && (@load1 > 5 && @load5 > 5)
报警表达式
报警表达式类似于阈值表达式,但是并不用来做判定,更类似于模板语言。以下为简单例子:
I am ${@name}. I am ${@age} years old.
其格式主要由2个部分组成,${}
之外的字符串和${}
内部的表达式。假设有上下文:
{name: "Jackson Tian", age: 18}
那么最终的执行结果就是:
I am Jackson Tian. I am 18 years old.
如果有一个报警的上下文是:
{load1: 5, load5: 2, load15: 2.2}
报警表达式为:
Load1较高,高于3,为${load1},请排查。
那么结果就是:Load1较高,高于3,为5,请排查。
${}内部支持@xxx
属性的方式、简单的+-*%/
以及数值和字符串。
比如内存使用的占比表达如下:
内存占用过高,为${@freemem / @total * 100}%。
监控类型与属性
每一种监控类型的上下文并不相同。
system
@load1,1分钟的平均负载。
@load5,5分钟的平均负载。
@load15,15分钟内的平均负载。
@cpu,CPU使用率,为0-1之间的数字。
@uptime,操作系统的运行时间,单位为秒。
@freemem,空闲的内存,单位为byte。
@totalmem,总的内存,单位为byte。
@cpu_count,CPU个数。
disk_usage
@used_percent,磁盘空间占用百分比,值为0-100。
node_log
node_log类型的数据为某个进程的内核数据。
进程编号:
@pid,进程id。
内存部分:
@rss,进程所使用的内存总大小,单位为byte。
V8堆的数据:
@heap_limit,能申请的堆内存的上限值,单位为byte。
@heap_total,申请到的堆内存大小,单位为byte。
@heap_used,当前使用的堆内存大小,单位为byte。
V8堆中的详细空间:
注:V8所申请的内存堆被分配为多个内存空间。
@new_space_used,新生代空间的内存使用大小,单位为byte。
@old_space_used,老生代空间的内存使用大小,单位为byte。
@map_space_used,隐藏类空间的内存使用大小,单位为byte。
@code_space_used,代码空间的内存使用大小,单位为byte。
@lo_space_used,大对象空间的内存使用大小,单位为byte。
Node v4.0之前的版本还有以下四个空间:
@cell_space_used,老生代单元空间的内存使用大小,单位为byte。
@property_cell_space_used,老生代属性单元空间的内存使用大小,单位为byte。
@old_data_space_used,老生代数据空间的内存使用大小,单位为byte。
@old_pointer_space_used,老生代指针空间的内存使用大小,单位为byte。
上述4个空间在v4.0之后合并为old_space。
例如判断是否发生内存泄漏,可以配置表达式:@heap_used / @heap_limit > 0.8
。报警表达式为:夭寿啦,估计内存泄漏了,堆上限${@heap_limit},已使用${@heap_used}
。
GC的数据:
@gc_time_during_last_min,一分钟内的GC时间,单位ms。
@total,总的GC时间,单位ms。
libuv句柄数据:
@active_handles,活跃的句柄数。
定时器数据:
@total_timer,定时器数量。
HTTP数据:
@live_http_request,一分钟内当前正在处理的HTTP请求数。
@http_response_sent,一分钟内的HTTP响应数。
@http_request_handled,一分钟内处理的HTTP请求数。
CPU数据:
@now,Node进程当前CPU占用量。
@cpu_15,Node进程当前15s钟的CPU平均占用量。
@cpu_30,Node进程当前30s钟的CPU平均占用量。
@cpu_60,Node进程当前60s钟的CPU平均占用量。
注意:上述4个数据的值的单位为core,表示占用几个核的CPU。如:0.25。表示占用0.25个核。该数值除以CPU核数,即为占整体的CPU的百分比。
error_log
异常日志数据。
@type,异常类型。
@timestamp,发生时间,距离1970.1.1的毫秒时间。
@stack,错误堆栈。
@extra,额外数据。
例如判断是否发生uncaughtException
,可以在Node中捕获:
process.on('uncaughtException', function(err) {
err.name = "UncaughtExceptionError";
console.log('Caught exception: ' + err);
});
然后配置监控表达式:@type include 'UncaughtExceptionError'
。报警表达式为:夭寿啦,发生UncaughtExceptionError啦,堆栈是:${@stack}
。
processes_count
进程数量数据。
@node_count,Node进程数量。
如果进程数量平常为5个,那么低于5个进程数量就属于不正常。所以可以这样配置监控表达式:@node_count < 5
,报警表达式:Node进程数${@node_count}低于5,请注意
。
version
版本号数据。
@node,系统的Node版本号。为vx.x.x的格式。
最后
如果对表达式和属性有不清楚的地方,可以咨询钉钉群:11794270 来联系我们。