【译】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就由你来建立啦。

相关文章
相关标签/搜索