Kibana 5.4.0 插件开发

原因

记录这篇博客原因有二:
1. 由于工作中需要使用kibana,并且有一些特殊需求需要用到百度的图标库echarts,所以就研究了下如何开发kibana的插件;
2. ElasticSearch官网上的文档以及推荐的博客等等都是较老的版本,考虑到公司内部已经开始使用5.4的版本并且在学习过程中发现版本的差异还是会有不小的影响,因此记录在此以备后用。

版本

上面说过kibana的插件开发,因为版本的不同可能会有差异,所以这里这里有必要写清楚我的开发环境:
ElasticSearch:5.4.0
Kibana:5.4.0
node:6.10.0
npm:3.10.10

系统为:
window 7 64位

由于kibana是nodejs开发的,所以需要安装nodejs,这一步在这篇博客中不做记录,从官网下载安装即可,另外npm是随node的,node安装完,npm也就自动安装完了~

开发环境搭建

下面是官网提到了一篇tutorial,可以作为参考(特别是这部分开发环境的搭建,写的还是蛮清楚的,后面的实际代码可能由于版本的原因会有一些出入,可以仅做参考):
https://www.timroes.de/2015/12/02/writing-kibana-4-plugins-basics/

开发kibana插件自然需要安装kibana,但由于kibana是从ElasticSearch中查询数据的,所以安装Kibana之前必须要安装ElasticSearch。

  • 安装ElasticSearch

    安装ElasticSearch其实很简单,到官网(上面链接)下载ElasticSearch(注意选择正确的版本,本篇使用5.4.0),解压到本地即可。如下图所示:
    下载解压ElasticSearch到本地

    解压完成后,可以进入安装目录\bin,在cmd中运行elasticsearch.bat来启动。如下图所示:
    启动elasticsearch

    启动完成后可以在浏览器中输入localhost:9200/ 来查看是否启动成功,看到以下信息则ElasticSearch已成功启动了:
    这里写图片描述

  • 安装Kibana

    • 下载开发版:https://github.com/elastic/kibana
      下载kibana的时候需要注意,从官网上下载的是正式版,并非开发版,不能作为开发插件使用的版本,需要在github上下载源码,另外,在github上下载的时候也要注意选择tag,即正确的版本。下载完成后和上面elasticsearch一样解压即可。

    • 安装依赖
      打开cmd,进入kibana的安装目录,直接运行npm install 命令安装依赖。
      安装依赖

      需要注意的是,这里npm install安装依赖的时候往往不成功,需要多次重试。什么原因我也并没有搞清楚,如果有前端大神对npm和nodejs了解深入的希望可以不吝赐教~~多谢啦

    • 启动
      安装完成后,同样在安装目录运行npm start命令启动kibana
      启动kibana

      看到如下信息,即为启动成功:
      启动成功

      此时,可以在浏览器中输入localhost:5601\ 来进入kibana的界面
      这里写图片描述
      这里写图片描述


  • 插件开发
    以上,完成后开发环境就算搭建完成了,下面可以开始插件的开发啦!
    官网上提供了一个插件生成器,本人木有用过,不知道怎么样,但是为了了解开发的过程,这篇文章没有使用这个生成器,而是纯手打,因为觉得这样印象深刻一些。

    首先进入kibana的安装目录,可以看到如下的目录结构:
    这里写图片描述

    我们的开发在plugins目录下进行。在之前的版本中(官网的那篇tutorial中介绍),是在installedPlugins下进行的,不知是不是由于版本的变动,总之,现在是在plugins中进行开发了。

首先,在plugins目录下,新建一个folder,名字就改为需要创建的插件名,比如:xx-myplugin。

  • 提醒:插件名需要唯一,比如加个前缀,公司名或者什么的,至少在plugins目录下要唯一。因为这个插件名以后会经常用到,所以同时建议取一个好写好记的名字。

进入刚新建的插件目录,新建一个package.json文件,代码如下。
这是一个npm module必须的文件,里面提供了这个模块的名称、版本等等信息,还可以在里面加入依赖的包及版本,类似于java web开发中的pom文件。

package.json

{
    "name": "xx-myplugin", // 必须与插件目录的名字一致
    "version": "5.4.0" // 必须指定版本,但在查看源码时,发现这里也可以直接写kibana,原理未知
}

然后再新建一个文件index.js。这个文件是npm module的主文件,可以理解成java文件的main函数(可能不是很恰当,但是理解那个意思就行),就是一个主要的入口。在这个文件中我们定义插件的类型并返回一个kibana插件的实例。

index.js

export default function (kibana) {
    return new kibana.Plugin({
        uiExports: {
            // 这里的visType就是kibana插件的类型,除了visTypes(视图类型)还有app(应用)等不同的类型
            visTypes: [
                'plugins/xx-myplugin/xx-myplugin' //2. 这里其实个路径,指向插件中的一个js文件,同时这个js名字也建议与插件名一致
            ]
        }
    })
}

上面注释2处提到了visTypes中配置的是js的路径,那个xx-myplugin.js是不是就在插件目录下呢?并不是,我们需要在插件目录下新建一个public目录(这也是npm模块的开发的规范),在public目录下新建这个xx-myplugin.js

xx-myplugin.js

import visTypes from 'ui/registry/vis_types';

import lineVisTypeProvider from 'plugins/xx-myplugin/line'; //这个demo.js中的内容其实可以直接写到当前文件中,但是这样写是为了以后扩展,并且符合node开发模块化的思想
// import demoVisTypeProvider from 'plugins/xx-myplugin/demo';

visTypes.register(lineVisTypeProvider); // 利用kibana注册新建的这个视图类型的插件。
//visTypes.register(demoVisTypeProvider); 

接下来在public目录下新建line.js(这个js是最主要的),在看这个文件之前,可以先到最下,看一下页面,可以直观一些

line.js

import VisVisTypeProvider from 'ui/vis/vis_type';
import VislibVisTypeVislibVisTypeProvider from 'ui/vislib_vis_type/vislib_vis_type';
import VisSchemasProvider from 'ui/vis/schemas';
import pointSeriesTemplate from 'plugins/xx-myplugin/editors/point_series.html';
//import xxTemplate from 'plugins/xx-myplugin/xxTemplate.html';
import image from './images/icon-line.svg';

export default function PointSeriesVisType(Private) {
  const VisType = Private(VisVisTypeProvider);
  const VislibVisType = Private(VislibVisTypeVislibVisTypeProvider);
  const Schemas = Private(VisSchemasProvider);

    // 这个js模块,返回视图类型插件的一个实例,这里面的配置相当丰富,按照本篇博客的代码可以实现一个空的视图类型的插件
    // 下面的配置中,params和schemas配置的是下图中1和2的位置,而point_series.html配置的则是3的位置。
    // 具体各个参数是什么意思,可以试着自己摸索一下~因为工作时间有限,并没有全部去了解。
  return new VislibVisType({
    name: 'echarts line',
    title: 'Echarts Line',
    image,
    description: 'Plugin of Echarts Line',
    category: VisType.CATEGORY.OTHER,
    requiresSearch: false,
    // template: xxTemplate, //如果这里新建了模板,可以在最下面的图中4的位置加上自己的内容,比如替换掉原来的图标,转而用echart来呈现等等
    params: { 
      defaults: {
        grid: {
          categoryLines: false,
          style: {
            color: '#fff'
          }
        },
        categoryAxes: [
          {
            id: 'CategoryAxis-1',
            type: 'category',
            position: 'bottom',
            show: true,
            style: {
            },
            scale: {
              type: 'linear'
            },
            labels: {
              show: true,
              truncate: 100
            },
            title: {}
          }
        ],
        valueAxes: [
          {
            id: 'ValueAxis-1',
            name: 'LeftAxis-1',
            type: 'value',
            position: 'left',
            show: true,
            style: {
            },
            scale: {
              type: 'linear',
              mode: 'normal'
            },
            labels: {
              show: true,
              rotate: 0,
              filter: false,
              truncate: 100
            },
            title: {}
          }
        ],
        seriesParams: [],
        addTooltip: true,
        addLegend: true,
        legendPosition: 'right',
        showCircles: true,
        interpolate: 'linear',
        scale: 'linear',
        drawLinesBetweenPoints: true,
        radiusRatio: 9,
        times: [],
        addTimeMarker: false,
        defaultYExtents: false,
        setYExtents: false
      },
      positions: ['top', 'left', 'right', 'bottom'],
      chartTypes: [{
        value: 'line',
        text: 'line'
      }, {
        value: 'area',
        text: 'area'
      }, {
        value: 'histogram',
        text: 'bar'
      }],
      axisModes: ['normal', 'percentage', 'wiggle', 'silhouette'],
      scaleTypes: ['linear', 'log', 'square root'],
      chartModes: ['normal', 'stacked'],
      interpolationModes: [{
        value: 'linear',
        text: 'straight',
      }, {
        value: 'cardinal',
        text: 'smoothed',
      }, {
        value: 'step-after',
        text: 'stepped',
      }],
      editor: pointSeriesTemplate,
      optionTabs: [
        {
          name: 'advanced',
          title: 'Metrics & Axes',
          editor: '<div><vislib-series></vislib-series><vislib-value-axes>' +
          '</vislib-value-axes><vislib-category-axis></vislib-category-axis></div>'
        },
        { name: 'options', title: 'Panel Settings', editor: pointSeriesTemplate },
      ],
    },

    schemas: new Schemas([
      {
        group: 'metrics',
        name: 'metric',
        title: 'Y-Axis',
        min: 1,
        defaults: [
          { schema: 'metric', type: 'count' }
        ]
      },
      {
        group: 'metrics',
        name: 'radius',
        title: 'Dot Size',
        min: 0,
        max: 1,
        aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality', 'top_hits']
      },
      {
        group: 'buckets',
        name: 'segment',
        title: 'X-Axis',
        min: 0,
        max: 1,
        aggFilter: '!geohash_grid'
      },
      {
        group: 'buckets',
        name: 'group',
        title: 'Split Series',
        min: 0,
        max: 1,
        aggFilter: '!geohash_grid'
      },
      {
        group: 'buckets',
        name: 'split',
        title: 'Split Chart',
        min: 0,
        max: 1,
        aggFilter: '!geohash_grid'
      }
    ])
  });
}

插件目录下新建editors,在editors中新建point_series.html文件
插件目录下新建images,在images中存放图片
editors/point_series.html

<div>
  <!-- Global settings -->
  <div class="kuiSideBarSection">
    <div class="kuiSideBarSectionTitle">
      <div class="kuiSideBarSectionTitle__text">
        Settings
      </div>
    </div>

    <div class="kuiSideBarFormRow">
      <label class="kuiSideBarFormRow__label" for="legendPosition">
        Legend Position
      </label>
      <div class="kuiSideBarFormRow__control">
        <select
          id="legendPosition"
          class="kuiSelect kuiSideBarSelect"
          ng-model="vis.params.legendPosition"
          ng-options="position for position in ['top', 'left', 'right', 'bottom']"
        ></select>
      </div>
    </div>

    <div class="kuiSideBarFormRow">
      <label class="kuiSideBarFormRow__label" for="showCursor">
        Show Tooltip
      </label>
      <div class="kuiSideBarFormRow__control">
        <input class="kuiCheckBox" id="showCursor" type="checkbox" ng-model="vis.params.addTooltip">
      </div>
    </div>

    <div class="kuiSideBarFormRow" ng-show="vis.hasSchemaAgg('segment', 'date_histogram')">
      <label class="kuiSideBarFormRow__label" for="currentTimeMarker">
        Current Time Marker
      </label>
      <div class="kuiSideBarFormRow__control">
        <input class="kuiCheckBox" id="currentTimeMarker" type="checkbox"
               ng-model="vis.params.addTimeMarker"
               ng-checked="vis.params.addTimeMarker"
        >
      </div>
    </div>

    <div class="kuiSideBarFormRow" ng-show="!vis.hasSchemaAgg('segment', 'date_histogram')">
      <label class="kuiSideBarFormRow__label" for="orderBuckets">
        Order Buckets by Sum
      </label>
      <div class="kuiSideBarFormRow__control">
        <input class="kuiCheckBox" id="orderBuckets" type="checkbox" ng-model="vis.params.orderBucketsBySum">
      </div>
    </div>

    <vislib-grid></vislib-grid>
  </div>

</div>

至此,一个简单的插件就已经开发完成了,这时候 npm start 启动kibana,点击Visualize,就可以看到新建的试图类型啦~!此外就像上面说过的,还可以新建一个app类型的插件,只需在一开始的index.js中替换掉visTypes部分:

uiExports: {
    // Register the app component of our plugin to uiExports
    app: {
        // The tite of the app(will be shown to the user)
        title: 'Indices',
        // An description of the application.
        description: 'An awesome Kibana plugin',
        // The require reference to the Javascript file for this application.
        main: 'plugins/chebada-myplugin/app',
        // The require reference to the icon of the app
        icon: 'plugins/chebada-myplugin/icon.svg'
    }
},

这里写图片描述

  • 最后

忍不住吐槽一下,kibana的文档虽然写的很多详细,但是对于插件开发来说实在是有点困难。这次的开发由于我本身是做javaweb开发的,对前端只停留在简单的jquery,所以这次学习过程还是比较痛苦的,花费了很多的时间,包括了解ELK开始,到学习nodejs,还有npm,curl等等知识,还需要了解一点less,angular的知识,整个学习成本还是非常高的。

最后在这里贴一些资料(都可以在官网上找到)
kibana插件开发官网提供的博客: https://www.timroes.de/2015/12/02/writing-kibana-4-plugins-basics/
youtube上插件开发环境搭建的视频: https://www.youtube.com/watch?v=FZEKhPz7SPQ

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jefferyqjy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值