目次
第2回から少し間が空いてしまいましたが、templateで作成したプラグインのディレクトリ構成とどういう流れでデータがやり取りされるかについてみていきます。 (2018/02月時点で作成したディレクトリ構成にしたがって説明します) ちなみに、JavaScriptの優れた開発者ではないので、誤解している点や、効率の悪い書き方などがあるかもしれません。見つけた場合は、連絡をいただければと思います。
では、まずは作成したディレクトリ構成についてみていきましょう。
ディレクトリ構成
simple-sample-kibana-plugin
がプラグインのプロジェクトのトップディレクトリになります。このディレクトリに次のような構成でサブディレクトリが存在します(なお、画像はIntelliJに取り込んだ後のディレクトリになっているので、.iml
など、不要なファイル/ディレクトリが存在しています)。
主要なディレクトリ、ファイルについて簡単に一覧で説明します(順不同)。
ファイル/ディレクトリ名 | 説明 |
---|---|
index.js | プラグインの本体。Kibanaはこのファイルのオブジェクトを読み込みプラグインを起動。設定などの読み込みもこちら。 |
package.json | npm/yarnのパッケージに関する情報を定義するファイル |
README.md | README。プラグインの説明などを記載する。インストール方法なども記載すると便利 |
public | ブラウザ側に配布されるプログラムや画像一式 |
public/less/main.less | LESS用のファイル。アプリ固有のスタイルなどを記載 |
public/app.js | ブラウザ側で読み込まれるプラグインのモジュールなど。 |
public/template/index.html | HTMLのテンプレート。ブラウザ上での描画に利用 |
server/routes | Kibanaサーバー側で動作するプラグイン。hapi.jsを利用してREST APIを実装する |
重要なファイルについて少しだけ説明します。
package.json
npmやyarnでビルドなどをするときに使用するパッケージ情報を記載するためのファイルです。 プラグインの名前、バージョン、説明などを記載します。 Kibanaのバージョンについてもこちらで管理します。この情報を また、ライブラリなどの依存関係についてもこちらで記載しています。 以下、抜粋。
{
"name": "simple-sample-kibana-plugin",
"version": "0.0.0",
"description": "Sample plugin for explaining how to make kibana app",
"main": "index.js",
"kibana": {
"version": "6.2.1",
"templateVersion": "7.2.4"
},
"scripts": {
"lint": "eslint **/*.js",
...
},
"devDependencies": {
"@elastic/eslint-config-kibana": "^0.14.0",
"@elastic/eslint-import-resolver-kibana": "^0.9.0",
"@elastic/plugin-helpers": "^7.1.3",
...
"expect.js": "^0.3.1"
}
}
ちなみに私は、version
などをリリースするたびに変更しています。
index.js
最初にKibanaに読み込まれるオブジェクトになります。 Kibanaのアプリの名前や、必要なモジュールなどを記載します。
また、kibana.yml
から設定など読み込む処理なども書くことができます。
2行目のexampleRoute
はサーバー側のAPIとして利用するhapi.js用のファイルのパスになります。
uiExports
はこのアプリの画面に関する設定などの記載になります。
app
の部分が実際にアプリの情報で、
main
があとで説明するこのプラグインのUIのためのJavaScriptファイル(public/app.js)になります。mainですので、最初に読み込まれる処理が記載されているものを指定します。app.js
というファイル名を変更する場合は、こちらのapp
の部分を変更したファイルに合わせましょう。
config(Joi)
の関数が設定ファイルの読み込みなどの処理を記載する場所です。
init(server, options)
の関数が初期化処理を記載する場所になります。
このサンプルアプリでは、2行目のimport
で読み込んだhapi.js用のファイルの関数を呼び出しています。引数で渡しているserver
がhapi.jsのserver
オブジェクトになります。
route
メソッドを使用して作成しているプラグイン用のREST APIを追加しています。
import { resolve } from 'path';
import exampleRoute from './server/routes/example';
export default function (kibana) {
return new kibana.Plugin({
require: ['elasticsearch'],
name: 'simple-sample-kibana-plugin',
uiExports: {
app: {
title: 'Simple Sample Kibana Plugin',
description: 'Sample plugin for explaining how to make kibana app',
main: 'plugins/simple-sample-kibana-plugin/app'
},
...
},
config(Joi) {
return Joi.object({
enabled: Joi.boolean().default(true),
}).default();
},
init(server, options) {
// Add server routes and initialize the plugin here
exampleRoute(server);
}
});
};
public/app.js
画面用のモジュールです。
uiRoutes
という機能を使用して、アプリの呼び出しURLを定義します。テンプレートで作成したばかりの場合は、/
というURLが追加されるのみです。
実際に画面を表示する際に動くコントローラーの部分はその下の
uiModules.controller
に指定してあるfunctionが画面描画の
処理を書く部分になります。
templateで作成したプラグインでは、“title"など表示に必要なデータを$scope
というオブジェクトに詰め込んでいます。
これはAngularJS(1系)でのモデルオブジェクトになります。
import moment from 'moment';
import { uiModules } from 'ui/modules';
import uiRoutes from 'ui/routes';
import 'ui/autoload/styles';
import './less/main.less';
import template from './templates/index.html';
uiRoutes.enable();
uiRoutes
.when('/', {
template,
resolve: {
...
}
});
uiModules
.get('app/simple-sample-kibana-plugin', [])
.controller('simpleSampleKibanaPluginHelloWorld', function ($scope, $route, $interval) {
$scope.title = 'Simple Sample Kibana Plugin';
$scope.description = 'Sample plugin for explaining how to make kibana app';
...
$scope.$watch('$destroy', unsubscribe);
});
server/routes/example.js
hapi.jsというNode.jsのためのサーバーフレームワークです。 このフレームワークをKibanaは使っており、Kibanaのサーバーとブラウザとのやり取りに使用するREST APIを記述するために使用しています。 例えば、Elasticsearchとのやり取りを実際に行うAPIなどをこのREST API内部で記述します。
export default function (server) {
server.route({
path: '/api/simple-sample-kibana-plugin/example',
method: 'GET',
handler(req, reply) {
reply({ time: (new Date()).toISOString() });
}
});
}
path
の部分がブラウザ側からアクセスするURLになります。
実際にElasticsearchとやり取りする処理の書き方については、次回の記事で説明します。
アーキテクチャ(簡易版)
ざっくりですが、ファイルやディレクトリについて説明しました。 簡単なデータのやり取りについての流れを説明します。
Kibana自体はNode.jsで実装されサーバーとして動作していますが、ブラウザでアクセスすることで画面を描画しています。 簡単なコンポーネントを並べるとデータのやり取りはこのような形です。
すごく簡易で大雑把な絵ですが。。。
実際のプラグインとしては大きく、2つの処理があります。
- ブラウザ上の処理
- クリックなどのイベント処理
- HTMLなどのレンダリング処理
- Kibanaサーバー上の処理(Elasticsearchなどとの通信が必要な場合)
- 外部との通信処理
- ブラウザ上では重い処理
絵に記載しましたが、ブラウザ上の処理についてはAngularJSが主なフレームワークで、サーバー上の処理についてはhapi.jsがフレームワークとなっています。
まとめ
ということで、今回はディレクトリ構造とファイルの説明、どういったフレームワークが使われ、データのやり取りがどのように行われているか説明しました。
次回からは、実際に私が作成したAnalyze UIを元にElasticsearchとのデータのやり取りなどについて紹介していきます。
comments powered by Disqus
See Also by Hugo
- Querqyの調査(その2:アーキテクチャ)
- 第3章終了(言語処理100本ノック2020)
- 第2章の10から11まで(言語処理100本ノック2020)
- Analyze UIとKibanaのプラグインの作成方法(第2回)
- Lucene Kuromoji for NEologdで指定した品詞の単語を抜き出すIngest Pluginを書いてみた #elasticsearchjp