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.js
,package.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
對象,咱們須要傳一個數組做爲構造函數的參數,數組的每一個對象定義了一個你所須要的聚合數據,每一個聚合對象有以下屬性:
metrics
或者buckets
二選一,定義了這個對象所屬的聚合數據類型這裏也還有其餘的一些字段你可使用的,可是在本例中不會被用到。
你能夠聲明的維度聚合的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上能夠找到這一步的代碼。
爲了給咱們的可視化插件天價一些邏輯,咱們會再次須要一個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.js
和tagcloud.html
中。
tag雲是是一個很簡單的讀取數據的插件。他只有一個維度數據和一個桶數據,沒有多維度,也沒有內嵌的聚合,等等。在一個更復雜的插件中你會遇到上述的所有情況,那咱們如今就來試試處理這些複雜的數據:
$scope.vis.aggs
對象來獲取配置的可視化對象,下面的bySchemaName
,bySchemaGroup
,byTypeName
(例如,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']
獲取數據,而不是僅僅獲取第一個。