Grafana 的一些使用技巧

9,745 阅读4分钟
原文链接: zhuanlan.zhihu.com

Grafana 是一个开源的时序性统计和监控平台,支持例如 elasticsearch、graphite、influxdb 等众多的数据源,并以功能强大的界面编辑器著称。我们在前端监控方面引入 grafana 后取得了一些不错的反馈,但是很多用户由于之前没有接触过 Grafana 经常会来询问相关问题,因此希望本文对大家在 grafana 使用方面有所帮助。

Grafana 的权限分为三个等级:Viewer、Editor 和 Admin,Viewer 只能查看 Grafana 已经存在的面板而不能编辑,Editor 可以编辑面板,Admin 则拥有全部权限例如添加数据源、添加插件、增加 API KEY。

对于普通用户来说,Viewer 权限已经足够,本文接下来的内容主要和 Editor 权限有关。由于篇幅有限,本文作为范例的数据源为 graphite,同时也只介绍最常用的 Graph 图表的配置方法。

数值类型的常用指标含义

  • count_ps
    • 每秒的数量
  • count
    • 每十秒的数量
  • mean_90
    • 去除最高10%的数据后的平均值
  • upper_90
    • 去除最高10%的数据后的最高值

总量误区

这里有一个常见的 Grafana 误区,因为经常有用数值类型的 count_ps来顺便获取每秒打点数量的情况,注意在这种情况下,一段时间内的打点总量需要使用 count_ps 的 avg 平均值来乘以这段时间的秒数来计算,而不是通过界面上的 Total 直接读取。

这是因为,在界面上一条曲线能够展示的点的数量是有限的,Grafana 会根据你的窗口宽度来决定返回的点数,因为像一天这样的时间段肯定没办法在界面上展示每一秒的点,毕竟总量为86400个点就算带鱼屏也不可能挤得下。对于无法展示的点,Grafana 默认是使用 avg 平均值的行为来修正返回点的值,举个栗子,如下图:

上图时间范围是一天,上部分为曲线面板的值,下部分为 面饼图表的值,并且上部分图标的曲线为 count 类型(十秒聚一次),可以看到 avg 平均值为 683,那么总量应该为 682 乘以 6 (如果是 count_ps 这里则是60) 乘以 60 (一小时60分钟)再乘以 24 (一天24小时)得到589万,与图片中下部分的582万相近,因此上部分 total 的117万是一个完完全全让人误解的值,可以认为它毫无意义进而直接无视掉。

误差

上文中我们计算出来的589万和界面上的582万其实也有一点误差,不过这是可以接受的,因为 statsd 一般情况下是 UDP 的形式(它其实有 TCP 的形式),所以如果想要完全正确的数据,那么最好把打点相关的数据也入库,从数据库里后置查询出来的才是完全可靠。

模板变量

模板变量能够动态地控制面板中的查询语句,是十分重要的功能。经常可以在面板的左上角发现它们,如下图:

模板变量的写法

模板变量支持 $name[[name]] 的写法,针对 graphite 数据源主要使用前者,例如:stats.timers.fe.test.$key.count_ps

新建模板变量

Grafana 界面上齿轮按钮 -> Templating -> 点击 New,即可出现类似如下的界面:

本段主要介绍 Query 类型的写法。

  • Name
    • 该变量的名称,不支持特殊字符例如$
  • Refresh
    • 可选NeverOn Dashboard LoadOn Time Range Change
    • 如果该变量的值经常动态增加的话则选 On Time Range Change,否则 On Dashboard Load 就足够了,Query 类型千万不要选 Never,否则变量只会在你点进来编辑变量时才会更新
  • Query
    • 查询语句,例如 stats.timers.fe.test.*
    • 编写时 Grafana 不会触发请求,需要在输入框外面点击一下,查询到的值就会显示在下边了

模板变量中的 Query 其实也支持模板变量,例如stats.timers.fe.test.$key.* 这样的语句,会在 $key 变量变化时自动刷新值,是不是有一点 MVVM 的感觉。这个功能用来联动多个模板变量可以大幅度减少 Grafana 一次查询的时间。

模板变量的隐藏玩法

模板变量甚至可以用在 Grafana 的跳转中,这个隐藏玩法带来了很多便利。在 Link 或者 Dashboard 里 URL 中任意位置填入 $name ,那么用户点击该链接跳转时 Grafana 同样会替换该变量来让你跳到正确的链接去。这和其他系统整合起来能够做到很不错的用户体验,例如跳转到 kibana 那边去查询日志。

kibana 和 Grafana 的时间范围格式并不一样,可以使用 这篇文章 中的 chrome 插件来解决。

另外,Custom 类型的模板变量可以允许用户在变量下拉框中自行输入值,也是一个经常用到的类型,并且模板变量会和当前链接中的 querystring 部分的var-${name} 同步,配合起来可以轻松地让第三方系统和 Grafana 互相精准地跳转

Grafana 面板编辑器

以 Editor 权限的账号进入到任意面板中,点击某个图表继而点击小弹窗中的 Edit 按钮,即可进入图表的编辑器界面。对于编辑器本文只介绍图表的重要配置,Metrics,Legend 和 Display

Metrcis

  • 编辑模式
    • 上图箭头指向的 toggle editor mode 可以控制编辑模式,关闭则需要手动输入查询语句,开启则是如上图的可以在界面上动态增删改的模式。
  • 数据源
    • Panel data source 一定要选对,否则查不到对应的路径,并且很有可能冒出来 Mock 数据让人一脸懵逼。

开启动态编辑模式时可以在点击上图中每个框框,这时 Grafana 会自动加载该位置在数据源中的值,并且你也可以在这里选择模板变量来动态控制。

点击尾巴上的加号,会冒出来对应数据源的函数,可以做一些高级的功能,这个也是本文下半部分的重点,稍后再做介绍。graphite 的函数比较多,其他数据源会少一些。

Legend

Legend 主要控制曲线的名称和值的展示,比较简单,这里列出一下他们的含义

  • As Table
    • 是否以表格形式展示
  • To the right
    • 是展示在图表右边还是在下面
  • Width
    • 面板时间段内的最小值否则强制限定宽度
  • Min
    • 面板时间段内的最小值
  • Avg
    • 面板时间段内的平均值
  • Total
    • 面板时间段内的值的总量,如上文所说获取数值类型的总量时这个 Total 是一个很让人误解的参数
  • Max
    • 面板时间段内的最大值
  • Current
    • 面板时间段内的当前值

Display

Display 控制图表的点和线的展示,有一些比较重要的参数

  • Draw Modes -> Lines
    • 是否绘制点之间的线段
  • Draw Modes -> Points
    • 是否绘制点
  • Hover info -> Mode
    • 悬浮面板上展示的方式,值为 All serires(展示该时间点的所有线段的值)和 single(只展示鼠标指着的那一条线段)
  • Hover info -> Sort Order
    • 悬浮面板上线条的排序,一般选择 Decreasing
  • Stacking & Null value -> Null value
    • 这个比较重要,需要根据点的密度来动态决定,如果点少很容易让人误解两个点中间也存在点。
    • 点多时,选择 connected
    • 点少时,选择 null

高级函数

以 graphite 为例子,打点路径中的 KEY 只支持大小写字母、数字、中划线和下划线,这会导致前端的路径(经常包含 # 和 :path)存不下来,因此我们只能提前转译,例如将 # 转译为 ANCHOR,将 :path 转译为 PATH ,再将 / 转译为 -,这样在变量模板中展示的就是比较怪异的前端路径,不过好在我们有函数,可以在界面上把它替换回来。

点击编辑界面 Metrics 面板中编辑模式的加号,添加 aliaSub 函数,并依此填入上图的三种的替换规则,在界面上就可以看到如下图的正常路径了:

aliaSub 只是其中一个简单的 alias 函数,用来处理曲线的名称,更多的函数是被用来处理单个查询的聚合、多条曲线的聚合、展示不同时间线、计算和过滤,本节会介绍其中一些经常用到的函数。

聚合单个查询的多条匹配曲线的总量 Combine -> sumSeries

例如,假设 stats_count.fe.test.* 有几十个匹配值,那么这个查询就会在图表中展示几十条曲线,此时如何获取所有曲线的总值呢?

不需要在打点时多打一份总量数据,直接使用 sumSeries 函数即可,sumSeries(stats_count.fe.test.*)

时间线迁移 Transform -> timeShift

想要在这个时间段内同时展示前一天的的曲线?timeShift(Query, '-1d')即可

去除异常值 Filter -> removeAboveValue

如果数值类型中出现了异常的值,例如平均为 1秒 的情况下出现了几百万秒的情况,那么就可以通过众多的过滤函数在界面上直接过滤掉而不是去修改打点代码,removeAboveValue(Query, 10000)即可

重命名函数

  • alias
    • 直接重命名该曲线,参数为曲线名称
  • aliasByNode(4, 5, 6)
    • 将曲线命名为原名称的第4、5、6段
  • aliasSub
    • 正则替换名称中的某一段

多条曲线数值的聚合 Special -> groupByNode

sumSeries 函数只能简单地将多条数据的最终值加起来,如果不是末尾位置的就不行了,而且也不支持除了 sum 外的功能,例如 avg 平均,使用 groupByNode 就可以动态地对指定位置的多个数值类型进行聚合了,如下图:

计算多个 Query 组成的成功率 Calculate -> asPercent

假设我们有如下几条打点:

stats.timers.fe.test.error1.count
stats.timers.fe.test.error2.count
stats.timers.fe.test.error3.count
stats.timers.fe.test.success.count

此时想要计算 success 的成功比例,如何做呢?

在这种相较复杂的情况下,就不能只靠一个 Query 来解决了,首先我们创建两个 Query,如下:

stats.timers.fe.test.*.count (Query 序列号为 #A)
stats.timers.fe.test.success.count (Query 序列号为 #B)

再创建第三个 Query,值为 asPercent(#B, sumSeries(#A),顾名思义,首先将 #A 的查询聚合起来得到总值,再用 asPercent 来进行除法即可。

通过如上的几个例子,可以看到函数强大的功能,即使是很复杂的在以前需要用后端代码来实现的部分,都可以通过多条Query和多个函数的互相嵌套来在界面上简单地实现。

每个数据源都有对应的函数开发文档,例如 graphite。Grafana 正是凭借着对众多数据源以及函数的支持,才能在一个网页界面上完成这么多强大的功能。

其他

报警

Grafana 在 4.0 版本后增加了报警功能,不过 Grafana 的报警属于数据源的后置查询,实时性不大能满足需求,我们公司有一个开源的 banshee ,就是为了解决这个问题。

banshee 使用了三西格马定律,支持基于阈值和趋势的报警,同时提供开放的 API 和 webhook 并默认集成了 Slack。banshee 和数据源位于同一个位置(statsd 的后端),因此可以保证时效性,也因为报警的独立性质所以对 Grafana 版本没有任何要求。

statsd 打点的限制

Grafana 依赖的如果是时序性数据库,那么每一个 KEY 都会对应一个文件来存储数据,例如 stats.timers.fe.test.* 相当于 stats/timers/fe/test 文件夹下的所有文件,因此必须注意打点路径不要有过多的组合,比如将省份和市作为 KEY 时的组合很容易就能占到 1G 以上的数据导致磁盘爆掉。

为了避免组合过多导致路径污染,请尽量保证每个 KEY 中格式化掉点,例如替换成下划线,另外打点路径可以尽量多加一点前缀,例如将stats.timers.fe.test.* 改为 stats.timers.fe.test.v1.* ,这样一旦污染后,清理数据时可以直接把 v1 整个文件夹删除而不是删除 test 这个根路径,用以保留你的历史正常的打点数据。

后端查询 Grafana 数据

一般推荐使用 API KEY 来查询 Grafana 的数据,Admin 权限账号可以在界面中生成上文三种权限的 API KEY,不过 Grafana 默认会开启 Basic Auth,使用账号密码即可通过 Grafana 的鉴权,例如http://${account}:${password}@${grafana_host}/api/org

当然,最好是拥有数据源的读权限来直接读取数据。

匿名模式

有时候用户确实没有 Grafana 的账号,但他就是想看面板,怎么办?此时就得 Grafana 的匿名模式出马了。

Grafana 配置文件中有 auth.anonymous 配置段,enabled 控制开关,org_name 控制开启匿名模式的组织,org_role 控制匿名者的权限。组织开启匿名意味着非登录用户能够直接跳过 Grafana 无权限地查询数据源,因此请保证数据源的安全,例如限定内网访问。

最后

本文介绍了 Grafana 相对高级的一些使用技巧,除了可以看到 Grafana 的强大功能以外,也应该注意到 Grafana 只是一个时序性很强的统计监控平台,一些非时序性质的功能例如报错的聚合和报错的日志等应该交给更专业的去做,例如 sentry 和 ELK。