kibana研究

概述

Kibana是一個針對Elasticsearch的開源分析及可視化平臺,用來搜索、查看交互存儲在Elasticsearch索引中的數據。它操做簡單,基於瀏覽器的用戶界面能夠快速建立儀表板(dashboard)實時顯示Elasticsearch查詢動態。html

安裝部署kibana

kibana須要64位操做系統,而且須要先安裝Elasticsearch,運行Elasticsearch又須要先安裝javavue

參考資料:java

Elasticsearch guide
Kibana guidenode

下面以mac上安裝部署kibana爲例:react

1.安裝java。到java裏面下載對應的最新java版本,並安裝。git

2.安裝並運行elasticsearch。到download elasticsearch裏面下載對應的最新elasticsearch版本,解壓以後進入elasticsearch文件夾運行命令:./bin/elasticsearch。github

3.查看elasticsearch是否運行成功。瀏覽器打開elasticsearch默認地址:http://localhost:9200/,若是顯示以下信息則表示運行成功:chrome

{
  "name" : "Cv0Qzv6",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "LFNZ-yjkRRW4dcVyuWlbug",
  "version" : {
    "number" : "6.5.3",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "159a78a",
    "build_date" : "2018-12-06T20:11:28.826501Z",
    "build_snapshot" : false,
    "lucene_version" : "7.5.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

4.安裝並運行kibana。到download kibana裏面下載對應的最新kibana版本,解壓以後進入kibana文件夾運行命令:./bin/kibana。npm

5.查看kibana是否運行成功。在瀏覽器打開kibana默認地址:http://localhost:5601,若是可以打開kibana則表示kibana運行成功。json

6.添加數據。首次打開kibana會提示導入數據,直接倒入demo data便可。而後就能夠愉快的調教kibana了。

kibana的大體結構

kibana是開源的,可是隻能用於elastic公司的項目。從這裏能夠看到kibana的源碼:elastic/kibana

kibana的大體結構以下:

  1. 總體框架:React 和 Angular 結合使用(利用ngReact庫在Angular裏面內嵌React)。

  2. ui框架:EUI。Elastic公司本身開發的一套UI,開源,可是不是MIT協議,只能用於Elastic公司開發的產品。https://github.com/elastic/eui

  3. 可視化框架:D3和Vega。D3官網vega官網

  4. 使用的拖拽庫:react-grid-layout

  5. word cloud用的d3-cloud。優勢是可以自動把文本直接轉化爲word cloud。

  6. 實現angular裏面使用react的庫:ngreact

kibana的主要功能

  1. 主要研究kibana的visualize和dashboard兩個板塊。

  2. visualize板塊的功能:
    • 能夠增長或刪除自定義的展現圖表。
    • 能夠給這些展現圖表自定義配色方案,標題等。
    • 能夠把這個圖表分享出去或者內嵌出去。
  3. dashboard板塊的功能:
    • 自定義添加visualize裏面的圖表,或者添加saved searches數據。
    • 每一個圖表或者數據是一個panel,支持panel的自定義拖拽排序和改變大小。
    • 擁有fileters,queries,time picker三種功能,經過搭配這三種能夠實時改變panel中的展現。
    • 能夠在dashboard裏面針對具體visualization跳轉到visualize板塊修改對應的visualization。
    • 經過點擊panel中的不一樣位置,能夠快捷的實現dashboard的filters操做。
    • 能夠經過右飄窗實時查看panel裏面的數據。
    • 能夠把這個dashboard分享出去或者內嵌出去。

說明:visualization指的是visualize板塊裏面那樣的展現圖表,saved searches指的是儲存的數據,它在dashboard裏面以表格的形式展現出來。

kibana的數據結構

爲了實現上面的主要功能,kibana有以下的數據結構:

ES

經過一個index儲存這三類數據:saved searches, visualizations and dashboards。

  1. saved searches:是用戶自定義的查詢數據,能夠經過visualize板塊轉化爲圖表,也能夠在dashboards裏面查看純數據。
  2. visualizations:是用戶在visualize板塊定義的圖表數據,包括使用哪一個searches,以及自定義配色等。
  3. dashboards:是用戶在dashboards板塊定義的dashboards數據,包括dashboard標題,裏面有哪些visualizations或者saved searches。

embeddables

kibana把全部能放在dashboard上的數據都叫作embeddable,按個人理解就是visualization 和 saved searches的數據。

每一個embeddable數據包含2類數據:

  1. 一個是embeddable metadata,它是不變的,包括全部embeddable的配置部分,供用戶配置使用;
  2. 另外一個是embeddable state,它是可變的,是用戶對於某個visualization或者saved data的配置信息,好比saved object id,visualization的配色方案等。

注意:embeddable state裏面有沒有具體查詢出來的數據?我以爲應該有,還應該有相應的查詢條件。

經過embeddable state,kibana實現了2個功能:

  1. 能夠經過在url裏面添加這些state的參數的形式把visualization分享或者內嵌出去。
  2. 經過把這些state和dashboard的state進行交互:實現改變dashboard可以實時改變而且定製panel,好比說定製panel的標題。而且經過panel也能夠改變dashboard的filters。

dashboards

每一個dashboard都有2類數據:

  1. 一個是dashboard storage data,這是儲存在ES中的data,用來提供給panel進行更新,並不放在redux裏面。
  2. 另外一個是dashboard redux tree,這是dashboard的redux的data,它包含以下幾個方面:
  3. metadata。這裏修改dashboard的標題和描述。
  4. embeddables。這裏放置embeddable state裏面redux感興趣的部分數據,主要把embeddable裏面的數據傳給dashboard。
  5. panels。這裏用來刪除panel,增長panel,更新panel,修改panel標題,重置panel標題。
  6. view。這裏用來實現fileters,queries,time picker三種功能,還有開啓kibana的編輯模式,panel全屏觀看等。

dashboards和panel的數據交互

  1. 在panel方面,經過dashboard的redux提供的redux來修改dashboard的數據。
  2. 在dashboard方面,把dashboard storage data經過lodash的_cloneDeep分發給各個panel,每一個panel內部再利用lodash的_isequal來比較新舊data來肯定更不更新展現,或者利用redux tree的一部分數據來修改panel的展現。(好比自定義panel的標題等。)
  3. 對於dashboard storage data,每一個panel都有一個id,而後更新的時候dashboard會把全部panel的id聚合在一塊兒,再加上查詢條件,上傳給服務器,服務器就返回新的數據,而後經過2來更新panel。當點擊save的時候,這些數據就保存爲這個dashboard的dashboard storage data。(實際上,kibana實現了以下的包裝:savedObjects,savedDashboard,savedSearch等等)

kibana的其它功能

inspector

dashboard板塊有這麼一個功能:能夠經過右飄窗實時查看panel裏面的數據。

而從panel到右飄窗之間,kibana封裝了一層inspecter,用來處理panel數據並顯示到右飄窗上面。這之間的東西又叫作adapter。

目前kibana有2個adapter,一個用來處理visualization裏面的數據,一個用來發送http請求(saved searches須要這種處理)。

courier

因爲從dashboard到es之間的數據獲取是異步的,而且有等待時間。因此kibana封裝了一層courier來處理requests,好比說設置ß時間間距啊,中斷requests,分發fetch事件來更新panels等。

其中把requests queued up的必要性沒有看懂~

D3和Vega

kibana同時使用D3和Vega圖表庫,其中:

  1. D3主要用於常規圖表配置,用戶在界面UI的配置。
  2. Vega主要用於讓用戶使用json數據的形式配置圖表,另外Vega也支持多種數據源,用戶能夠利用URL的形式導入非ES裏面的數據源。

kibana的基本架構

目錄說明

kibana的主要目錄以下(其餘目錄有的沒有看懂,有的是服務目錄,有的是處理特定業務邏輯的目錄,就不研究了):

├── src
│   ├── core_plugins            #核心插件
│   │   ├── kibana              #kibana插件
│   │   ├── elasticsearch       #處理elasticsearch的插件
│   │   ├── table_vis           #處理table圖表的插件
│   │   └── ...                 #其餘插件
│   ├── ui                      #ui
│   │   ├── public              #主要ui模塊
│   │   │   ├── chrome          #chrome瀏覽器模塊
│   │   │   ├── draggable       #拖拽模塊
│   │   │   ├── embeddable      #embeddable模塊
│   │   │   ├── i18n            #國際化模塊
│   │   │   ├── inspector       #inspector模塊
│   │   │   ├── private         #ag模塊
│   │   │   ├── register        #ag註冊模塊
│   │   │   ├── vis             #可視化模塊
│   │   │   └── ...             #其餘模塊
│   │   ├── ui_render           #ui的render
│   │   ├── ui_setting          #ui的setting
│   │   └── ...                 #其它ui模塊
│   └── test                    #測試
│       ├── functional          #功能測試
│       ├── scripts             #封裝的js
│       ├── dev_certs           #封裝的受權js
│       └── ...                 #其餘

從上面能夠看到:

  1. kibana主要分爲core_plugins,ui和test三個模塊。
  2. kibana自身的視圖只是做爲一個插件被放在core_plugins裏面,kibana就至關於通常小型項目的src或者view文件夾。
  3. 這麼分的目的是由於,kibana項目太大,對於不少模塊都會一層層封裝,每一層會做爲一個獨立的模塊,這樣模塊就太多了,而後就考慮把部分模塊開發爲插件的形式。

下面對於core_plugins,ui和test三個模塊分別進行深刻研究。

core_plugins

core_plugins中的每個插件都至少有public文件夾,index.js和package.json。其中public文件夾進行業務處理,index.js進行導出,package.json標註這個插件的名字和版本等信息。

其中index.js的結構是這樣的:

// 以相似npm module的形式掛載模塊
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = function (kibana) {
  return new kibana.Plugin({
    id:
    require:
    config() {}
    init(){}
    uiExports: {}
  })
}

ui

ui主要包括渲染相關的模塊。其中最重要的是modules.js,它裏面導出一個uiModules來進行ag模塊加載,提取和刪除等。

其它一些模塊會根據provider和factory來進行封裝,其中利用provider來導出,利用factory以工廠模式的形式來建立模塊。部分代碼示例以下:

// 提供導出內容
const noneRequestHandlerProvider = function () {
  return {
    name: 'none',
    handler: function () {
      return new Promise((resolve) => {
        resolve();
      });
    }
  };
};

// 註冊這個模塊
VisRequestHandlersRegistryProvider.register(noneRequestHandlerProvider);

// 導出
export { noneRequestHandlerProvider };
// 獲取kibana模塊
const module = uiModules.get('kibana');

// 以工廠模式的形式封裝PersistedState
module.factory('PersistedState', ($injector) => {
  const Private = $injector.get('Private');
  const Events = Private(EventsProvider);

  // Extend PersistedState to override the EmitterClass class with
  // our Angular friendly version.
  return class AngularPersistedState extends PersistedState {
    constructor(value, path) {
      super(value, path, Events);
    }
  };
});

test

像這種大項目又是怎麼進行測試的呢?因爲測試的每一個模塊都與不少模塊關聯,因此kibana作了以下工做:

  1. 本身用node開發了一套測試方法。
  2. 把測試過程當中用到的一些方法都封裝在一塊兒,而後測試的時候就只調用這些方法便可。
  3. 全部的測試組件都導出成一個函數,而後先加載測試環境,再加載全部的測試進行測試。(因此這不是單元測試!)
  4. 對於其餘一些能進行單元測試的模塊就用jest進行單元測試。
import expect from 'expect.js';

// 接受測試環境的getService和getPageObjects做爲參數導入
export default function ({ getService, getPageObjects }) {
  const log = getService('log');
  const PageObjects = getPageObjects(['common', 'visualize']);

  describe('chart types', function () {
    before(function () {
      log.debug('navigateToApp visualize');
      return PageObjects.common.navigateToUrl('visualize', 'new');
    });

    it('should show the correct chart types', async function () {
      const expectedChartTypes = [
        'Area',
        'Controls',
        'Coordinate Map',
        'Data Table',
        'Gauge',
        'Goal',
        'Heat Map',
        'Horizontal Bar',
        'Line',
        'Markdown',
        'Metric',
        'Pie',
        'Region Map',
        'Tag Cloud',
        'Timelion',
        'Vega',
        'Vertical Bar',
        'Visual Builder',
      ];

      // find all the chart types and make sure there all there
      const chartTypes = await PageObjects.visualize.getChartTypes();
      log.debug('returned chart types = ' + chartTypes);
      log.debug('expected chart types = ' + expectedChartTypes);
      expect(chartTypes).to.eql(expectedChartTypes);
    });
  });
}

和vue項目對比

通常vue項目的目錄結構是這樣的:

├── src
│   ├── api              #api
│   ├── assets           #圖片等資源
│   ├── components       #組件
│   ├── i18n             #國際化
│   ├── plugins          #插件
│   ├── router           #路由
│   ├── store            #store
│   ├── styles           #樣式
│   ├── utils            #工具
│   ├── views            #視圖
│   │   ├── admin        #管理界面
│   │   ├── auth         #權限界面
│   │   ├── layouts      #視圖佈局
│   │   └── ...          #其餘

對於小項目來講,上面的目錄結構已經足夠了,而且比kibana的結構更加清晰(我的認爲,kibana的目錄結構有點混亂,多是由於kibana迭代過不少次的緣由)。可是隨着項目的增大,能夠考慮參考kibana的目錄結構。

另外,對於vue項目,組件通常都是.vue後綴的單文件組件,因此若是想要在這之上對組件進行封裝的話,怎麼辦?mixin和vue.extend瞭解一下。

聲明

以上純屬我的理解,因爲我本身水平和時間有限,一些理解錯誤在所不免,歡迎提出並一塊兒討論。

感覺:

  1. 有些項目就算把源碼給你看,你也不必定看得懂。(揮淚~)
  2. 能架構kibana這種項目的才能叫架構師嘛~

參考資料

Dashboard State Walkthrough

Discover Context App Implementation Notes

Discover Context App Implementation Notes

Inspector

unify the way global context is passed down to visualize

[Meta] Improve support for custom embeddable configurations at the dashboard panel level

Embeddables API

vega-vs-vegalite

Vislib general overview

相關文章
相關標籤/搜索