译 Tim Rose 的kibana插件教程-消费数据的可视化插件

kibana官方没有插件的开发教程,Tim Rose的教程写的十分详尽,也是官方推荐的。因为这个系列的教程是英文版的,且基于kibana4,近日须要作kibana的开发,硬啃下这些教程以后,虽然这些教程比较古老,不少代码不能用了,可是开发思想仍是通用的。记录下来,留下个爪。因为本人水平有限,错漏的地方欢迎你们指出。css

原文连接:www.timroes.de/writing-kib…html

原文标题:Writing Kibana 4 Plugins – Visualizations using Datawebpack

简单可视化插件

你须要先阅读基础篇,才能阅读本文。git

在前面的章节(在阅读本文前,必定要先阅读),你已经学会了如何建立一个简单的可视化插件,但并不从elasticsearch获取 任何数据。在这一章,咱们将写另一个插件,像其余插件同样,须要消费elasticsearch的数据。github

咱们将写一个很简单的标签云插件,咱们会把桶的名称做为标签展现出来,度量聚合数据的大小将决定这个标签字体的大小。若是你对桶和度量还不是很熟悉,能够参考一下我这篇k4v教程。web

这篇教程的源码能够在GitHub找到json

在整个教程当中,我会用tr-k4p-tagcloud这个名字。你须要用一个全局惟一的名字来替代他。数组

标签云可视化插件

首先咱们要想一想,咱们须要以何种方式来可视化何种数据,这意味着,咱们须要考虑,咱们的视化插件,会呈现什么桶和什么度量的数据。浏览器

咱们会尽可能保持插件的简单性,因此只采用了一个桶和一个度量。桶聚合决定了什么标签会被展现出来(一个桶就是一个标签),维度聚合决定了标签的大小,即聚合的度量结果越高,所显示的标签就会越大。bash

决定用多少维度和桶的聚合数据是很重要的,若是你能内嵌聚合,你一会还要再插件中定义。

定义和注册插件

跟前面章节的同样,第一步是建立index.jspackage.json,和注册一个简单的可视化provider。下面咱们只展现主要的provider代码片断(你能够在public/tagclouc.js中找到):

function TagcloudProvider(Private) {
  var TemplateVisType = Private(require('ui/template_vis_type/TemplateVisType'));

  return new TemplateVisType({
    name: 'trTagcloud', // The internal id of the visualization (must be unique)
    title: 'Tagcloud', // The title of the visualization, shown to the user
    description: 'Tagcloud visualization', // The description of this vis
    icon: 'fa-cloud', // The font awesome icon of this visualization
    template: require('plugins/tr-k4p-tagcloud/tagcloud.html')
  });
}

require('ui/registry/vis_types').register(TagcloudProvider);
复制代码

跟前面的教程相比较,这里又两个不同的地方:

  • 咱们在定义模块的时候,丢弃了define()函数(AMD 模块定义)。就像前面说的,这个是非必要的,因为咱们使用了webpack做为打包工具,这也意味着你再也不须要在模块中返回provider函数。
  • 咱们去除了requiresSearch: false选项,咱们的tagcloud插件须要从elasticsearch中获取数据,因此咱们的插件就能够像其余使用数据的插件同样来进行查询。因为requiresSearch: true是默认选项,因此咱们去掉这个选项就好了。

如今咱们须要来建立public/tagcloud.html,如今可让他置空。第一部分的代码能够在在github的tag0.1.0找到。

定义数据结构

一个须要使用聚合数据的插件,你须要明确的指出,你的插件须要什么样的聚合数据,或者说,什么样的数据是被个人插件接受的。这所谓的数据结构须要在插件定义的时候给出,咱们来修改一下插件定义:

function TagcloudProvider(Private) {
  var TemplateVisType = /* ... */;

  // Include the Schemas class, which will be used to define schemas
  var Schemas = Private(require('ui/Vis/Schemas'));

  return new TemplateVisType({
    /* every attribute shown above */,
    schemas: new Schemas([
      {
        group: 'metrics',
        name: 'tagsize',
        title: 'Tagsize',
        min: 1,
        max: 1,
        aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality', 'std_dev']
      },
      {
        group: 'buckets',
        name: 'tags',
        title: 'Tags',
        min: 1,
        max: 1,
        aggFilter: '!geohash_grid'
      }
    ])
  });
}
复制代码

为了定义数据结构,咱们须要实例化一个Schemas对象,咱们须要传一个数组做为构造函数的参数,数组的每一个对象定义了一个你所须要的聚合数据,每一个聚合对象有以下属性:

  • group metrics或者buckets二选一,定义了这个对象所属的聚合数据类型
  • name 这个聚合数据的名字(id)。之后你能够用这个属性来引用不一样的聚合数据
  • title 这个是展现给用户看的,当他添加一个单项聚合的时候,这个会告诉他,这个数据将会被怎么使用,再本例中,桶数据会被用做标签,维度数据则影响的是标签的字体大小
  • min/max 用户可以添加的此聚合的范围,例如,用户添加一个直方图,一个桶聚合的名称叫“图列”。这个是没有限制的,即没有最大值限制,就像用户想要有多少个直方图的条数,就能有多少个。在本例中,咱们各类数据只容许一个聚合数据,因为咱们的插件的工做方式。
  • 过滤器 决定了哪一种聚合数据是合法的。他的值是一个这里所容许的聚合类型的数组(下面能够看见),或者是一个所不容许的聚合类型的数组(每个必定要以一个下划线为前缀),在接下来的场景中,其余的聚合类型是容许的。若是这个数组只有一个值,那你也能够把他声明称一个字符串(正如桶聚合所示)。

这里也还有其余的一些字段你可使用的,可是在本例中不会被用到。

你能够声明的维度聚合的aggFilter类型有:svg, cardinality, count, max, median, min, percentileranks, percentiles, stddev, sum

桶聚合的aggFilter的类型有:** datehistogram, daterange, filters, geohashgrid, histogram, iprange, range, significant_terms, terms**

在github的tag0.2.0上能够找到这一步的代码。

编辑控制器controller

为了给咱们的可视化插件天价一些逻辑,咱们会再次须要一个angular的controller。与以前不一样的是,咱们会把这个controller放在一个单独的文件下(由于他会变得大一点),所以,咱们须要在tancloud.js中添加以下代码:

require('plugins/tr-k4p-tagcloud/tagcloudController')

复制代码

如今咱们须要建立一个新文件public/tagcloudController.js,先写上一个空白的controller:

var module = require('ui/modules').get('tr-k4p-tagcloud');
module.controller('TagcloudController', function($scope) {
  // Your logic will go here
});
复制代码

在模板中加载控制器(public/tagcloud.html)

<div ng-controller="TagcloudController"></div>
复制代码

如今插件的模板就能够加载控制器了。

获取数据

咱们须要从angular的scope中继承两个变量,一个是从以前章节就知道的vis,这个变量包含了插件的信息,和用户的设置信息。另一个变量就是esResponse,这变量保存了Elasticsearch 的返回数据,kibana'会自动请求elasticsearch,带上当前的query和filters,以及用户的聚合信息。

咱们的插件须要把返回数据和用户的设置,经过可视化的方式展现出来,咱们能够访问$scope.esResponse.aggregations变量来获取咱们的查询所返回数据。咱们须要获取聚合数据中的id,为了获取指定聚合数据的id,咱们须要$scope.vis.aggs中的一些方法来找到is。

在咱们的场景中,首先咱们须要获取所有的桶数据(就是全部的tag名称),咱们能够经过以下方式,来获取tags聚合的id

$scope.vis.aggs.bySchemaName['tags'][0].id
复制代码

bySchemaName 对象包含一个聚合数据设置的名字(在schema中指定的)的映射,tags属性是一个用户输入的所有聚合设置的数组,因为咱们已经把这个属性的最大值和最小值都设置成了1,咱们如今也只有一个对象能够获取他的id了。咱们用这个id在esResponse中查找咱们须要的数据。

咱们通常是设置一个watch来监听esResponse的变化来更新数据,如今咱们来把这个tag当成一个list展现出来:

$scope.$watch('esResponse', function(resp) {
  if (!resp) {
    $scope.tags = null;
    return;
  }

  // Retrieve the id of the configured tags aggregation
  var tagsAggId = $scope.vis.aggs.bySchemaName['tags'][0].id;
  // Get the buckets of that aggregation
  var buckets = resp.aggregations[tagsAggId].buckets;
  // Transform all buckets into tag objects
  $scope.tags = buckets.map(function(bucket) {
    return {
      label: bucket.key
    };
   });
});

复制代码

这样咱们的$scope.tags就是一个数组,数组里的对象是有一个属性为label,值是bucket.key。相应的,咱们也要修改tagcloud.html

<div ng-controller="TagcloudController">
  <span ng-repeat="tag in tags">{{tag.label}}</span>
</div>
复制代码

完整的代码(包括一些css)能够在GitHub仓库的0.3.0

获取维度聚合数据相对来讲要简单一点,但也遵循这一样的步骤。首先,咱们须要要拿到的桶数的维度聚合数据的一个引用:

var metricsAgg = $scope.vis.aggs.bySchemaName['tagsize'][0];
复制代码

注意:咱们并无读取id,反而读取了整个聚合对象,一样的咱们也只是读取了数组中的第一个元素,由于咱们只容许配置一个维度聚合。咱们能够来完善刚刚的桶数据,给桶数据加上维度数据:

$scope.tags = buckets.map(function(bucket) {
  return {
    label: bucket.key,
    value: metricsAgg.getValue(bucket)
  };
});
复制代码

咱们能够调用维度聚合对象上的getValue方法,参数是桶bucket,返回值就是这个桶数据想对应的维度数据了。以后咱们就能够拿到一个tags的数组,里面的对象都是一个label和一个值。如今剩下的事情就是为咱们每一个tag计算一个font-size,首选须要统计tag的最大值和最小值,在收集tags数组的时候,咱们会设定一个最大的font-size和最小的font-size,而后计算出每一个tag相应的字体大小,因为这个跟kibana没有直接关联,只是angular的controller的一些东西,就不在这里展现了,咱们会放在GitHub的0.4.0中的tagcloudController.jstagcloud.html中。

数据累加

tag云是是一个很简单的读取数据的插件。他只有一个维度数据和一个桶数据,没有多维度,也没有内嵌的聚合,等等。在一个更复杂的插件中你会遇到上述的所有情况,那咱们如今就来试试处理这些复杂的数据:

  • 能够经过$scope.vis.aggs对象来获取配置的可视化对象,下面的bySchemaNamebySchemaGroupbyTypeName(例如,count,terms等等),这些属性去获取,scheme里配置的不一样name的聚合数据
  • 聚合对象的getValue方法能够获取bucket对象的数据。

通常来讲,还有不少其余的方法,来适应更加复杂的可视化场景,(例如你可使用聚合对象的getKey方法来获取key或者bucket)。这些方法须要等一等,在官方的插件开发文档中找到。阅读源码,常常是最好的方法,在开发的过程当中打个断点,而后在浏览器的dev-tool上面观察这些对象。

点击过滤

最后一个咱们想添加的功能就是tags过滤,当用户点击tag的时候,仪表盘上应该添加一个该tag的值的过滤器。

第一步,咱们要建立一个过滤器来实现过滤服务,咱们会使用Private服务(这个服务是负责为须要的模块实例化angular服务,在前面章节已经说过了),来实例化一个filter服务,controller中须要作以下修改:

module.controller('TagcloudController', function($scope, Private) {
  var filterManager = Private(require('ui/filter_manager'));
  // ...
});
复制代码

filter manger有一个add方法,能够调用来实现添加过滤器,首先咱们修改HTML来当用户点击一个标签的时候,调用一个方法:

<span ng-click="filter(tag)" ng-repeat="tag in tags" ...>
复制代码

完整的filter方法:

$scope.filter = function(tag) {
  // Add a new filter via the filter manager
  filterManager.add(
    // The field to filter for, we can get it from the config
    $scope.vis.aggs.bySchemaName['tags'][0].params.field,
    // The value to filter for, we will read out the bucket key from the tag
    tag.label,
    // Whether the filter is negated. If you want to create a negated filter pass '-' here
    null,
    // The index pattern for the filter
    $scope.vis.indexPattern.title
  );
};
复制代码

这一步的完整代码能够在GitHub的0.5.0找到。

接下来

如今你已经能够写一个展现来自elasticsearch数据的可视化插件了。写插件的时候,要时刻注意,什么样的scheme是你想展现的,要保证只容许配置你代码中处理了的scheme。因此,若是你容许多个bucket聚合,那你就要把每个bucket都要在代码中进行处理,这样的话,你就须要从$scope.vis.aggs.bySchemaName['foobar']获取数据,而不是仅仅获取第一个。

相关文章
相关标签/搜索