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
完整插件的源代码能够在GitHub上找到。这个插件我用了不少ECMAScript 2015 语法。Kibana使用Webpack打包插件文件并编译成es5语法,因此您能够放心地使用ECMAScript 2015数组
你能够在GitHubGitHub中找到完整的代码promise
或许你已经注意到了,上面看到的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属性,是一个对象,是来描述这个插件信息的。
public/app.js
文件,在package.json
文件中,插件的id应该是elasticsearch_status
还有其余的一些参数,好比你若是不想让插件显示在导航中,能够添加参数hidden:true。(kibana 的状态页面就是这样。)
若是要从插件中查询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,咱们可使用。这个方法也是咱们为何要在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就由你来建立啦。