Kibana:使用 Kibana Timelion 进行时间序列分析

在 Kibana 的可视化工具里,有一个可视化的工具叫做 Timelion。Timelion 是Kibana 中时间序列的可视化工具。 时间序列可视化是按时间顺序分析数据的可视化。 Timelion 可用于绘制二维图,时间绘制在 x 轴上使用 Timelion,你可以在同一可视化文件中组合独立的数据源。 使用相对简单的语法,你可以执行高级数学计算,例如除以和减去指标,计算导数和移动平均值,当然还可以可视化这些计算的结果。

总共大约有五十种不同的功能(有些还在试验中),可以用来对要分析的数据集进行切片和切块。 本文将为你提供 Timelion 入门的基本知识及其函数语法。

与仅使用普通条形或线形可视化相比,有什么优势? Timelion 采用了不同的方法。 你无需使用可视化编辑器来创建图表,而是可以使用timelion 特定的语法通过将函数链接在一起来定义图表。 该语法可以实现一些经典点系列图所不具备的功能-例如将来自不同索引或数据源的数据绘制到一个图中。

本教程将首先简要介绍 Kibana 中的 timelion UI,然后说明 timelion 语法并显示一些用例,这些用例是传统 Kibana 可视化无法或仍然无法完成的。

 

准备数据

在今天的教程我们将使用 Makelogs 来生产我们的测试数据。如果大家还是对这个工具不是很熟悉的话,请参阅我之前的文章 “Logstash:运用 makelogs 创建测试日志”。我们使用如下的命令来创建测试数据:

makelogs -d 30 -c 10000

这样,我们就创建了 10000 条的测试数据,并且涵盖 30 天的数据。我们可以通过如下的命令来检查已经生成的 logstash-0 索引:

GET _cat/indices

从上面我们可以看出来,已经有10004 条数据在这个索引里了。我们必须为这个 logstash-0 来创建一个叫做 logstash-* 的索引模式(index pattern)。

 

用户界面

我们可以通过如下的方式来进入到 Timelion:

在默认的情况下,显示的是上面的界面。

窗口右边的输入框显示当前所选图形的表达式。 你将在本教程中看到的所有表达式都将插入到该文本框中。使用菜单中的 “Save” 按钮,你可以存储整个 timelion 工作表及其所有图形,也可以将当前关注的图形存储为可视化内容,并可以放置在任何仪表板上。

当前显示的数据的日期范围可能会受到页面右上方的知名日期选择器的影响。 要设置 x 轴的比例,使用表达式输入旁边的选择框。 默认情况下,它设置为 “auto”,它将根据选定的时间范围自动确定合适的刻度。 如果你想强制例如 每天一个数据点,你可以将其设置为1d。

 

Timelion expressions

最简单的表达式-也将自动用于新图形的表达式如下:

.es(*)

Timelion 函数始终以点开头,后跟函数名称,然后是包含该函数所有参数的括号(在本例中为星号)。

.es(或 .elasticsearch,如果你喜欢输入长词)功能从 Elasticsearch 收集数据并随时间绘制数据。

如果你未在表达式中指定索引(稍后将看到如何执行此操作),将查询 Elasticsearch 的所有索引以获取数据。你可以通过修改 timelion:es.default_index 设置在 “Kibana 的高级设置” 中更改此默认设置。

默认情况下,.es 函数将仅计算文档数,从而生成一个图表,显示一段时间内的文档数。

如果你输入的是简单表达式,即使你选择了一个包含数据的日期范围,也只能得到一条平线:很可能您的数据没有使用 @timestamp 作为主要时间字段的名称。你可以通过 “高级设置” 中的 timelion:es.timefield 设置更改默认名称,也可以使用 .es 函数中的 timefield 参数为单个系列进行设置。你将在下一节中看到如何设置参数。

 

Function parameters

Function 可以具有多个参数,.es 函数也可以。 每个参数都有一个名称,你可以在括号内使用它来设置其值。

参数还具有顺序,该顺序由自动完成功能。如果你未指定参数名称,则 timelion 将按顺序将值分配给参数,这些值将在文档中列出。

.es 函数的第一个参数是参数 q(用于查询),它是用于过滤此系列数据的 Query String。 你还可以通过其名称显式引用此参数,并且我总是建议您在向函数传递多个参数后立即这样做。 因此,以下两个表达式是等效的:

.es(*)
.es(q=*)

多个参数用逗号分隔。 .es 函数还有另一个称为 index 的参数,可用于为该系列指定索引模式,因此不会再次对所有索引(或将上述在高级设置更改的任何值)执行查询。

.es(q=*, index=logstash-*)

如果参数的值包含空格或逗号,则必须将值用单引号或双引号引起来。 否则,你可以省略这些引号。

.es(q='some query', index=logstash-*)

Chaining functions

许多 timelion 函数用于修改一系列数据。 你可以通过 chain 表达式中的函数来应用它们。 .label 函数就是这样的函数。  你可以使用它来更改系列的标签:

.es(q=country:de).label(Germany)

你也可以 chain 多个表达式,如本教程后面所述。

Multiple series

使用 timelion 的优点之一是能够将多个时间序列添加到一个图表中。 在表达式中,多个序列必须简单地用逗号分隔:

.es(q=de), .es(q=us)

你现在也可以在每个系列上使用 chain 功能,例如 用于指定标签:

.es(q=CN).label(China), .es(q=IN).label('India')

现在,我们介绍了有关如何使用 timelion 的基础知识,因此我们可以跳到更深入的解释几个功能以及你可以使用它们的方式。

 

Timelion functions

Data source functions

数据源功能可用于将数据加载到图形中。 我们已经看到了 .es 数据函数,该函数从 Elasticsearch 加载数据。 Timelion 提供了更多的源来加载数据,我们将在本节中对其进行说明。

Elasticsearch

在查看其他数据源函数之前,我们应该首先再次查看 .es 函数。 它提供了一些我们尚未看到的功能。

由于按行划分特定字段的值是常见的用例(可以在常规可视化中使用术语聚合来完成),因此 .es 函数具有一个名为 split 的参数。

split 参数的值必须是一个字段名,后跟一个冒号,然后是一个数值,表示应有多少个最上层的值获得一行。 以下表达式显示了示例数据中前4个国家/地区的流量(国家/地区代码存储在 geo.dest 字段中):

.es(split=geo.dest:4)

metric 参数用于控制 y 值的计算。 默认情况下,.es 函数会将文档数置于y轴上。 你可以使用 metric 参数来指定另一个指标聚合,该聚合应用于在特定时间计算值。 该值必须是单个值指标聚合的名称,后跟一个冒号,然后是要在其上计算该聚合的字段名称。

聚合的有效名称为: avg 计算一个字段的平均值,sum 求总和,cardinality 以获得一个字段中唯一值的数量,min 和 max 检索字段的最小值或最大值。

如果我们要修改上面的表达式,以显示该国家/地区中传输的最大字节数来显示前4个国家/地区(以查看哪些国家/地区负责我的带宽),则可以使用 metric 参数,如下所示:

.es(split=geo.dest:4, metric=sum:bytes)

你还可以使用多个 split 参数来创建子桶(如在可视化中一样),并使用多个 metric 参数来在每个时间点绘制多个值。

 

static/value

.static(或别名 .value)只会在给定值处绘制一条普通的水平线。 这对于在图形上绘制视觉阈值很有用。 你还可以使用参数标签直接标记系列:

.es(), .static(100, label='good visitor level')

 

偏移数据源

每个数据源函数都接受一个称为 offset 的参数。 它可以用于将数据偏移特定的时间范围。 这对于比较来自不同时间范围的数据很有用。  offset 参数以单位接受正值和负值。 有效单位是 s 表示秒,m 表示分钟,h 表示小时,d 表示天,w 表示周,M 表示月,y 表示年。 它将在绘制输入之前将输入偏移指定的偏移量。

要比较当前页面访问者(根据我们的示例数据)与一周前的访问次数进行比较,可以使用以下表达式:

 

Styling functions

Timelion 提供的一些功能主要用于样式设置。

Line style

默认情况下,timelion 将使用线条绘制数据。 有三个函数可以修改实际的图形类型:.lines,.bars 和 .points。它们每个都支持一系列参数来修改例如 线的宽度,点的大小等。要查看所有可用参数,请查看应用程序内文档。

你可以看到以下表达式中演示的一些参数:

Colors

若要手动指定特定系列的颜色,请使用 .color 函数。 它期望颜色为 HTML 颜色名称或 #rrggbb 格式的十六进制值。 以下示例说明了用法:

如果使用 split 参数,因此有多行,则可以指定用冒号分隔的多种颜色:

 

Math functions

Timelion 提供了有关时间序列的几种数学计算。如果希望 y 轴显示绝对值,则可以链接 .abs 函数。 你可以使用 .log 函数来计算所有值的对数(并可以选择指定对数底数)。

.cusum 函数可用于计算所有值的累加和,即特定时间点的值是所有先前点的总和。 请注意,累计总和仅从图表的开始时间开始计算,而不是从时间开始算起。

.derivative 函数可用于计算时间序列的导数,即曲线的斜率:

.mvavg(长 .movingaverage)函数可通过对序列应用移动平均值来平滑序列。 此函数需要其第一个参数(窗口),该参数将窗口的大小指定为一个值和一个时间单位(请参见上面的偏移量),用于计算移动平均值。

以下表达式及其结果证明了移动平均线的平滑效果:

Trend

Timelion 的另一个有用功能是可以将趋势线绘制到图形中。 你可以在任何系列上使用 .trend chain 函数,以绘制该系列的趋势线。

.es(q=CN).trend()

Different scales

在一个图表中添加多个系列有时会产生一个问题,即两个系列的值的比例完全不同。比如下面的两个索引的文档数完全不在同一个数量级上。

如果你改变 scale,那么我们很难看清楚红色的到底是多少。如果我们对实际值不感兴趣,而仅对曲线随时间变化的方式感兴趣,则可以使用 .range 函数将序列限制为新的值范围,即重写该序列的最小值和最大值, 但保持形状不变。

通过这种方式,我们现在可以看到这两个系列之间的相关性。 当然,您永远不会忘记,这种关联并不意味着因果关系。
我们可以使用 timelions 分组功能来简化上述查询,在该功能中,我们可以使用括号将多个系列分组,并将函数链接到整个组:

(.es(index=logstash-*), .es(index=metricbeat-*)).range(0,10)

由于使用范围查询会丢失实际值,因此在我们的用例中,.yaxis 函数可能更方便。 它将为不同的 y 轴分配一个序列。 你必须指定它应该使用的轴号(默认的 y 轴为1)。 它可以选择使用 min,max,label,color 和 position 参数来修改 y 轴。

现在要获得与 .range 查询相似的效果,但又不丢失实际值,可以使用以下表达式将两个系列移至不同的 y 轴。

还有另一个扩展问题,使用经典的 Kibana 虚拟化几乎无法解决。 想象一下,你正在绘制服务器日志数据的字节总数。 如果你观看整整一周的数据,则 x 轴上的每个数据点现在将代表一小时的数据,因此将一小时内传输的所有字节的总和作为一个值。 选择其他时间范围时,例如四个小时后,每个数据点现在仅代表一分钟,因此y轴值较低。 下图显示了这种情况,左图为一周的时间范围,右图为四个小时的时间范围。 如你所见,左图中的 y 轴值更高。

有时,这种行为不是您想要的,因为无论你在什么时间范围查看,你都可能希望将绝对值相互比较,或者您希望这些值对您有意义,例如 因为您想查看所有以每秒字节数为单位的值,因为您可能习惯于以该单位计算带宽。

.scale_interval 函数确实可以解决该问题。 它采用一个参数(命名间隔),该参数接受一个时间单位(如上所示)。 无论您正在寻找什么时间范围,Timelion 都会计算该时间间隔内的所有值。 要查看每秒的字节数,请指定值为 1s,要查看每分钟的字节数为 1m 值:

.es(metric=sum:bytes).scale_interval(1s)

这根本不会改变图形的形状,它只会缩放打印在 y 轴上并悬停在图形上时显示给你的实际值。

 

计算时序

Timelion 的另一个重要优点是可以按序列进行计算。 你可以通过数字甚至其他序列对序列进行加,减,乘或除。

这样的用例是将信息与其他信息相关联。 如果我们使用样本 Web 服务器数据来分析与中国相比来自印度的访问者,则可以使用以下表达式显示结果:

我们可以看到,来自中国的访问者比来自印度的访问者要多得多,但是当然,中国的人口比印度要多。 我们可以使用时间轴将每个系列除以该国的实际人口:

.es(CN).divide(14.005), .es(IN).divide(13.24)

在这里出于计算的方便,直接把中国人口写成14.0005亿,而不是真正的数值1400050000。同样印度的人口为 13.24亿。

从上面,我们可以看出来,即使按照人头来算,中国的访问者数量还是高于印度。

你可以通过 .add(或 .plus),. subtract,.multiply 和 .divide 函数使用所有基本操作。 每个都接受一个静态值或另一个系列(如上例所示)。

 

有条件的选择

Timelion 提供 .min 和 .max 函数。 这些将采用多个系列或数值的列表,并且将始终返回所有系列/数值的最小值或最大值(取决于你使用的功能)。

例如,你可以通过这种方式将图形设置为特定值:

.min(.es(), 25)

使用 .min 和 .max 的另一个用例是有条件地为图形着色。 你可以例如如果它超过了特定阈值(在这种情况下为4000),请突出显示一个序列,如下所示:

.es().bars(stack=false).color(#F44336), .min(.es(), 4000).bars(stack=false).color(#8BC34A)

这将首先将常规 .es() 数据绘制为红色的条形,然后绘制相同的数据,但将其上限设置为4000。 这样,绿色条将覆盖红色,而红色条将仅显示高于 4000 的阈值。

如果要为条件选择提供更复杂的解决方案,则可以使用 .if(或长的 .condition)函数为条件为 true 或 false 时提供条件和值。

Rashid Khan 发布了一篇很棒的博客文章,我只有一个.condition(),它详细解释了这些功能并显示了其用法的漂亮用例。