譯 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']獲取數據,而不是僅僅獲取第一個。

相關文章
相關標籤/搜索