监控项表达式编写

在 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 来联系我们。