【譯】Tim Rose 的kibana插件教程-自定義App插件

kibana官方沒有插件的開發教程,Tim Rose的教程寫的十分詳盡,也是官方推薦的。因爲這個系列的教程是英文版的,且基於kibana4,近日須要作kibana的開發,硬啃下這些教程以後,雖然這些教程比較古老,不少代碼不能用了,可是開發思想仍是通用的。記錄下來,留下個爪。因爲本人水平有限,錯漏的地方歡迎你們指出。html

原文連接:www.timroes.de/writing-kib…前端

原文標題Writing Kibana Plugins – Custom applicationsgit

你須要先讀前面基礎部分第一篇教程,才能開始本章節的學習。github

本教程系列介紹了Kibana中如何建立一個自定義應用程序。一個插件能夠包含一個應用程序,它是Kibana平臺內部的一個獨立的部分,能夠放置任何你想展現的東西。Kibana只是給你提供了一個連接到這個部分,你能夠爲所欲爲的設計這個插件。衆所周知的例子就是Elastic 的timelion插件,他就是一個app插件。chrome

在本教程中,咱們將構建一個很是簡單的Elasticsearch狀態頁面app。它列出全部索引,單擊一個將帶您到有關該索引的信息頁面。您能夠在下面的動畫中看到這個效果。json

在本教程中,咱們將學習:api

  • 建立app插件的基本結構
  • 插件如何和elasticsearch進行通訊
  • 插件中如何建立多個子頁面和頁面之間的導航

完整插件的源代碼能夠在GitHub上找到。這個插件我用了不少ECMAScript 2015 語法。Kibana使用Webpack打包插件文件並編譯成es5語法,因此您能夠放心地使用ECMAScript 2015數組

你能夠在GitHubGitHub中找到完整的代碼promise

kibana5的全新架構

或許你已經注意到了,上面看到的kibana的頁面你可能目前並不熟悉,這是kibana5的新的UI設計,到目前爲止尚未發佈,這個教程的代碼時兼容kibana4的,對於kibana4和kibana5之間的,跟開發插件相關的差別,我會指出來的。(譯者:這個已經。。。。)瀏覽器

建立插件基礎結構

之前的教程中咱們看到了index.js的結構。要註冊一個新的插件,您可使用uiExport對象的app屬性,以下所示:

export default function (kibana) {
  return new kibana.Plugin({
   require: ['elasticsearch'],

    uiExports: {
      app: {
        title: 'Indices',
        description: 'An awesome Kibana plugin',
        main: 'plugins/elasticsearch_status/app',
        icon: 'plugins/elasticsearch_status/icon.svg'
      }
    }
});
複製代碼

在require中,咱們能夠引用其餘的模塊。常見的值是kibana和elasticsearch。指定這些模塊由於kibana是在加載完這些模塊後加載咱們的插件,保證了引用的模塊加載成功。咱們在這裏引用了elasticsearch模塊,由於咱們在後面要使用elasticsearch的數據。 在uiExports中的app屬性,是一個對象,是來描述這個插件信息的。

  • title:插件的名字,會顯示在kibana的側邊欄中(在kibana5以前是在logo下的應用程序菜單中)。
  • description:簡單介紹插件信息,目前並無在其餘地方中使用。
  • icon:插件的圖標,會被顯示在kibana側邊欄的插件名字的旁邊(kibana5以前是在應用程序菜單裏),這個字段的值應該是一個字符串,功能如上所述。
  • main:插件的源碼位置。默認plugins/插件名字/js文件名,指向插件的public文件夾下的js文件,在上述例子當中,咱們的插件文件夾下應該有一個public/app.js文件,在package.json文件中,插件的id應該是elasticsearch_status

還有其餘的一些參數,好比你若是不想讓插件顯示在導航中,能夠添加參數hidden:true。(kibana 的狀態頁面就是這樣。)

建立服務器API

若是要從插件中查詢Elasticsearch,那麼最好的解決方案就是,給Kibana服務器建立一個新的API。你插件中調用這個API,它會爲你查詢Elasticsearch。

爲何不直接從您的插件中查詢Elasticsearch?固然,您也可使用Elasticsearch JavaScript客戶端直接從您的前端查詢ES。但這些調用將在用戶的瀏覽器中執行,從而致使CORS(交叉原始資源共享)問題。最好的解決方案是使用Kibana服務器。

所以,如上所述,咱們的插件將會獲取全部索引的列表,而且須要檢索特定索引的狀態。

咱們來看看第二個接口。

要向Kibana添加新的服務器API,使用init方法能夠指定:

// ...
return new kibana.Plugin({
  // ...
  init(server, options) {
    // Initialization goes here
  }
});
複製代碼

若是你不熟悉這個JavaScript語法,這只是一個快捷寫法,你也能夠寫init: function(server, options) {…}。

傳遞給該方法的服務器對象其實是一個hapiJS服務器對象。您能夠按以下方式建立新接口:

// inside your init method:
server.route({
  path: '/api/elasticsearch_status/index/{name}',
  method: 'GET',
  handler(req, reply) {
    // more to come here in the next step
    reply("Hello World");
  }
});
複製代碼

這樣,您能夠在Kibana服務器上建立一個新的GET API。你如今能夠調用該/api/elasticsearch_status/index/index名稱接口(如今也沒有作任何事情)。處理程序方法將得到兩個參數:第一個是已經建立的請求。您能夠今後處的請求中訪問不少信息(例如,使用req.params.name,你將獲取在URL中傳遞的索引的名稱)。第二個參數是回覆函數。您必須調用此函數並將其應該返回的數據傳遞給調用此API的客戶端。

有關完整的文檔,請查看官方hapi文檔的路由方法。

查詢elasticsearch

如今咱們在處理函數中,需實際處理查詢Elasticsearch以相關索引的數據。有一個實用方法來調用Elasticsearch,咱們可使用。這個方法也是咱們爲何要在index.js中,要引入elasticsearch模塊。如下代碼應放在咱們API的處理函數:

server.plugins.elasticsearch.callWithRequest(req, 'cluster.state', {
  metric: 'metadata',
  index: req.params.name
}).then(function (response) {
  reply(response.metadata.indices[req.params.name]);
});
複製代碼

咱們須要將API中的請求,做爲第一個參數傳遞給該callWithRequest方法。這種方法在Kibana服務器的調用和Elasticsearch的調用之間進行傳遞身份認證。第二個參數是咱們要調用的Elasticsearch JavaScript客戶端的函數的名稱- 在咱們的例子中,咱們要調用該cluster.state()方法,而且咱們要將索引的名稱(從請求參數讀出)傳遞給方法。

該方法返回一個Elasticsearch的響應的promise。在resolve函數中,咱們將從響應中提取咱們須要的數據(在咱們的例子中是索引stats),並返回它(經過該reply方法)。

若是你的開發工做是基於Kibana 5.2以上的,callWithRequest的使用會有輕微的變化,這個博客中有概述。

咱們建立了一個Kibana服務器API,如今能夠調用它了。若是您注意GitHub的源代碼,您將注意到,我將API生成提取到另外一個模塊,而且從init方法中調用此方法。我建議這樣作,以保持你的代碼可讀性 - 若是你有不少API你建立,你甚至可能想要使用多個模塊。

第二個服務器API(用於獲取全部索引的列表)能夠在源代碼中找到。我不會在這篇博文中詳細介紹,由於咱們已經涵蓋了全部主題,你能夠本身寫。

建立前端

咱們應該爲咱們的插件建立一個前端。咱們以前已經在index.js中註冊了一個app.js做爲主文件。如今是來寫他們的時候了。

咱們將插入文件的前兩行以下:

import 'ui/autoload/styles';
import './less/main.less';
複製代碼

若是您使用 Kibana 5,則第一行很重要,您應該始終將其放在插件中。這將使插件加載Kibana經常使用的全部樣式。若是您不導入此模塊,您的應用程序會和kibana框架看起來格格不入。若是您使用Kibana 4,此文件不存在,您沒法導入(這讓咱們回到第一篇文章中的巨大警告,關於缺乏穩定的公共API)。

第二行是可選的,是app插入本身的LESS樣式的例子。您只需導入您的LESS文件。您也可使用SASS。我建議使用相對路徑,由於這些文件也在您的public件夾,因此你每次都在路徑上寫上你的插件ID。

建立路由選項

Kibana使用AngularJS的ngRouter在頁面之間進行路由。若是您的app想要使用路由,則必須明確啓用它,並在app.js文件中配置一些路由:

import uiRoutes from 'ui/routes';

import overviewTemplate from './templates/index.html';
import detailTemplate from './templates/detail.html';

uiRoutes.enable();
uiRoutes
.when('/', {
  template: overviewTemplate,
  controller: 'elasticsearchStatusController',
  controllerAs: 'ctrl'
})
.when('/index/:name', {
  template: detailTemplate,
  controller: 'elasticsearchDetailController',
  controllerAs: 'ctrl'
});
複製代碼

若是須要使用路由,必須調用uiRoutes.enable()。以後,您可使用when和otherwise調用,就像您使用$routeProvider。在這種狀況下,咱們要配置兩個路由:一個用於基本路徑,一個用於路徑/index/:name,name是索引名稱的佔位符。能夠經過使用上面的import語句,將實際的html文件(這文件放在templates文件夾中)引入,並設置兩個路由的模板。咱們還使用兩個控制器,咱們尚未寫。

下面咱們寫控制器,咱們使用Kibana的全局模塊註冊模塊:

import uiModules from 'ui/modules';

uiModules
.get('app/elasticsearch_status')
.controller('elasticsearchStatusController', function ($http) {
  $http.get('../api/elasticsearch_status/indices').then((response) => {
    this.indices = response.data;
  });
});
複製代碼

uiModules是Kibana的核心服務,負責處理應用中的全部模塊。若是要獲取或建立一個,請使用其get方法。第一個參數是要獲取或建立的模塊的名稱。若是模塊已經存在則把存在的模塊返回,若是沒有建立它,返回該模塊。第二個參數能夠是一個模塊數組,放置模塊的依賴。若是模塊已經存在,那麼這些模塊在返回以前,將被添加到模塊的依賴關係列表中。這些模塊不存在,只需將它們添加到新建立的模塊中便可。

此行爲與angular.module方法不一樣,你建立模塊,並指定依賴關係和獲取依賴時,和不傳遞第二個參數時,都能發現。使用這個服務,Kibana也會負責處理加載咱們的Angular模塊。

上面的控制器使用$http服務,來從咱們的接口獲取索引列表,並將其存儲在控制器中。

最後一個須要補充的部分如今,是咱們的模板templates/index.html:

<div class="container">
  <div class="row">
    <div class="col-12-sm">
      <h1>Elasticsearch Status</h1>
      <ul class="indexList">
        <li ng-repeat="index in ctrl.indices">
          <a href="#/index/{{index}}">{{ index }}</a>
        </li>
      </ul>
    </div>
  </div>
</div>
複製代碼

咱們的教程中的HTML保持至關簡單。咱們只是ng-repeat用來迭代,從API中檢索全部的索引,並連接到它們。此外,咱們使用一些Bootstrap的CSS類來設計咱們的內容。詳細頁面的HTML能夠在GitHub的源代碼中找到。

在Kibana 5開始,Kibana將只提供給你側邊的導航欄連接,如上面的動圖所示。一旦你被切換到你的插件,kibana沒有提供標題欄或其餘的東西。若是你想要其餘樣式佈局,你將要本身在app中去建立它。在Kibana5以前,您仍然能夠得到一些bar,並能夠經過服務進行修改:

import chrome from 'ui/chrome';

chrome
.setNavBackground('#FF00FF') // Turns the navbar in beautiful pink
.setBrand({
  logo: '<CSS background property value for the logo>',
  smallLogo: '<CSS background property value a smaller version>'
});
複製代碼

還有其餘的一些方法來建立tabs,等。可是當你建立一個app的時候,要記住這些東西在kibana5的時候會被幹掉。那麼你的app可能就不可用了,由於你所依賴的tabs導航已經不可用了。

下一步

從這個很是簡單的app中,你已經學到了不少有用的api了,足夠去建立一個很是棒的自定義app了,因此下一個timelion app就由你來建立啦。

相關文章
相關標籤/搜索