寫Kibana插件——自定義應用程序


Writing Kibana Plugins – Custom applications

  在閱讀本教程之前,您需要閱讀第1部分 - 基礎知識

  本部分教程系列介紹了Kibana中定制應用程序的創建。一個應用程序是插件中的一個可能的組件,它在Kibana平台內部有自己完整的部分,可以放置任何你想要的東西。Kibana只是提供你一個鏈接到這個部分,你可以隨你的感覺設計。其中一個很好的例子是Elastic的timelion插件。

  在本教程中,我們將構建一個非常簡單的Elasticsearch狀態頁面應用程序。它將只列出所有索引,單擊一個將帶您到有關該索引的統計信息的頁面。您可以在下面的動畫中看到最終結果。

   在本教程中,我們將學習:

  • 如何創建應用程序插件的基本結構
  • 如何從elasticsearch 正確地與插件進行通信
  • 如何在應用程序中創建多個子頁面並在它們之間進行導航

   完整插件的源代碼可以在GitHub上找到。這個插件我用了很多ECMAScript 2015 Syntax。Kibana使用Webpack將您的插件文件捆綁在一起,所以您可以安全地使用ECMAScript 2015,它將被Kibana折疊到ES 5 JavaScript。

  GitHub源碼:https://github.com/timroes/elasticsearch_status

New Kibana 5 design

  你可能已經注意到,上面Kibana的設計可能看起來很少見(但是)。這是Kibana 5的新UI,尚未發布。教程中的所有內容也適用於Kibana 4,我將在本教程中展示與插件開發相關的舊設計與新設計之間的差異。

Creating the basic structure

  我們已經看到了本系列前幾部分的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對象內,您可以指定應用程序鍵,該鍵本身也是描述應用程序的對象。

  title鍵是此應用程序的可讀名稱。這是在Kibana的側欄中顯示的(或在Kibana 5之前的應用程序菜單中的圖標下方)。description是對應用程序的描述。這個目前不在任何地方使用。

  main鍵是您的應用程序的主要javascript的必須字符串。它將始終以plugins/<your plugin id>/開頭,后跟插件中public文件夾中JavaScript的名稱。例如在上面的示例中,您的插件中應該有一個public / app.js文件,而package.json中的plugin id應該是elasticsearch_status。

  icon鍵是指此應用程序的圖標。這將顯示在側面導航中的名稱旁邊(或應用程序菜單中的Kibana 5之前)。它又是一個將被解決的字符串,與上述相同。

  您可以為應用程序指定幾個其他鍵,上面沒有顯示。你可以將hidden設置為true,如果您不希望應用程序顯示在導航中(例如,Kibana狀態頁面是這樣的應用程序)。

Creating a new Server 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){...}的一個快捷方式。

  傳遞給該方法的server對象實際上是一個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 / <some index name here>接口(也沒有做任何事情)。handler 程序方法將獲得兩個參數:第一個是已經創建的請求。您可以從此處的請求中訪問很多(例如,使用req.params.name,您將獲得在URL中傳遞的索引的名稱)。第二個參數是回復函數。您必須調用此函數並將其應該返回的數據傳遞給調用此API的客戶端。

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

Querying 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的響應解決的承諾。在解析函數中,我們將從響應(在我們的例子中為索引統計)提取我們需要的數據,並返回它(通過回復方法)。

  如果您正在開發Kibana 5.2,在本博客中概述的callWithRequest的使用會有輕微的變化。

  這樣我們創建了我們的第一個Kibana服務器API,現在可以調用它了。如果您注意GitHub的源代碼,您將注意到,我提取API以生成另一個模塊,並且從init方法中調用此方法。我建議這樣做,以保持你的代碼可讀 - 如果你有很多創建的API,你甚至可能想要在多個模塊中使用它們。

  第二個服務器API(用於獲取所有索引的列表)可以在源代碼中找到。我不會在這篇博文中詳細介紹,因為我們已經涵蓋了所有主題,你可以自己寫。

Creating the frontend

  最后但並非最不重要的是,我們應該為應用程序創建實際的前端。我們之前已經將index.js中的特定app.js注冊為主文件。現在是創建它的時間了,並填寫一些內容。

import 'ui/autoload/styles';
import './less/main.less';

  如果您使用Kibana 5,則第一行很重要,您應該始終將其放在應用程序插件中。這將使Kibana加載其通常具有的所有樣式。如果您不導入(或要求,如果您喜歡ES5語法)此模塊,您的應用程序周圍的Kibana框架將在用戶進入應用程序時看起來像壞的。如果您使用Kibana 4,此文件不存在,您無法導入(這讓我們回到第一篇文章中的巨大警告,關於缺少穩定的公共API)。

  第二行是可選的,並顯示如何為您的應用程序插入自己的LESS樣式。您只需導入您的LESS文件。您也可以使用SASS替代。我建議使用相對路徑,這些文件也在您的公共文件夾,所以你不需要一遍又一遍重復你的插件ID。

Creating routing options

  Kibana使用AngularJS'ngRouter在頁面之間進行路由。如果您的應用程序想要使用路由,則必須明確啟用它,並在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和其它的調用,就像你從$ routeProvider中使用的一樣。在這種情況下,我們要配置兩條路由:一個是基本路徑,一個是/ index /:name路徑,該名稱是索引名稱的占位符。可以通過使用上面的import語句將實際的html文件(在我們的例子中都放置在模板文件中)設置為兩個路由的模板。我們還使用兩個控制器,我們還沒有寫。

  所以我們僅僅使用全局Angular模塊注冊正在運行的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的核心服務,負責應用中的所有Angular模塊。如果要獲取或創建一個,請使用其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 5之前,您仍然可以獲得標題欄,並可以通過服務進行修改:

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>'
});

  有更多的方法來創建制表符等。但是當您開發應用程序組件時,請記住,這些內容在Kibana 5(截至今天)中已經消失,您的應用程序可能無法使用,因為您缺少依賴的選項卡導航。

What’s next?

   通過這個非常簡單的應用程序組件,我們覆蓋了您構建自己的awesome應用程序組件插件所需的大量API。所以現在由你來構建下一個timelion。

 

原文地址:https://www.timroes.de/2016/02/21/writing-kibana-plugins-custom-applications/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM