CData Software Blog

クラウド連携のCData Software の技術ブログです。

Logstash を使って、JIRAのデータを Elasticsearch へ連携:CData JDBC Driver

f:id:sugimomoto:20200716230611p:plain

こんにちは。CData Software Japanリードエンジニアの杉本です。

前回は Apache全文検索エンジン、SolrでのCData JDBC Driver利用方法を紹介しました。

www.cdatablog.jp

でも、Apache Solrを紹介したからには、Elasticsearchも外せないですね。

今回の記事ではCData JDBC Driver、そしてLogstash を使って Elasticsearchへデータを転送する方法を紹介したいと思います。

LogStashとは?

LogStash は分散処理マルチテナント対応検索エンジン「ElasticSeach」などを提供するElastic社がオープンソースで開発・提供しているデータ処理パイプラインツールです。

www.elastic.co

f:id:sugimomoto:20200716230557p:plain

様々なフォーマット、サービス、ログなどのデータをElasticSeachへ転送することによく利用されているツールですが、柔軟なPlugin機能により、ログやElasticSeach以外にも数多くのInput・Output先に対応しています。

f:id:sugimomoto:20200716230604p:plain

そんなLogstashではJDBC Driverを利用できるPluginが提供されており、MySQLPostgreSQLなどのRDBデータを転送することも可能になっています。

今回はそのJDBC 用のPluginとCData JDBC Driverを組み合わせて、ElasticSeachへデータを取り込む方法を紹介します。

本記事のシナリオ

今回取り込む対象のデータソースは Atlassian が提供する課題 & プロジェクト追跡ソフトウェアのJIRAとしました。

Logstashは前述の通り、様々なInput Pluginが提供されており、多種多様なサービスからデータを取り込むことが可能ですが、現在JIRAはデータソースとして対応していません。

https://www.elastic.co/guide/en/logstash/current/input-plugins.html

f:id:sugimomoto:20200716232754p:plain

もちろん、Elasticsearch に取り込むので、Elasticsearch のREST APIとJIRA の REST APIを組み合わせて実装することも可能ですが、各APIへの連携実装や保守・メンテナンスのコストが多くかかってしまいます。

そこでこの記事では Logstash がもともと備えているJDBCのインターフェースを利用することでこのボトルネックを解消します。

CData Software では SalesforceやKintone、JIRAなどに接続することができる各種JDBC Driverを200種類ほど提供しています。

https://www.cdata.com/jp/jdbc/#drivers

f:id:sugimomoto:20200702152837p:plain

この各種JDBC Driverを用いることで、各APIの仕様を意識せず Logstash からのデータ取り込みを実行でき、シームレスに Elasticsearch へJIRAのデータを転送できるようになります。

f:id:sugimomoto:20200716230611p:plain

手順

必要なもの

  • Elasticsearch
  • Logstash
  • Kibana
  • JIRA アカウント(JIRA Core)
  • CData JIRA JDBC Driver

Elasticsearch・Logstash・Kibana はそれぞれ7.8.0 を使用しました。予めWindows版をダウンロードして、ZIPファイルを解凍した状態になっています。

また、この記事ではJDBC Input Pluginを利用して、CData JDBC Driverからデータを取り込みます。

https://www.elastic.co/guide/en/logstash/5.4/plugins-inputs-jdbc.html

JDBC Pluginは最新のLogstashだとデフォルトでついてきますが、バージョンによっては追加する必要があります。

JIRA JDBC Driver のインストール

最初にJIRAからデータを取得するためのインターフェースとなるJDBC Driverをインストールします。トライアルは以下のURLから入手できます。

https://www.cdata.com/jp/drivers/jira/jdbc/

f:id:sugimomoto:20200716230619p:plain

ダウンロード後、exeファイルを実行し、セットアップを進めます。

f:id:sugimomoto:20200716230625p:plain

CData JIRA JDBC Driver のインストールが完了すると、「C:\Program Files\CData\CData JDBC Driver for JIRA 2019J\lib\」フォルダにJDBC Driverの本体であるjarファイルが生成されます。

そして下記2つのファイルを

C:\Program Files\CData\CData JDBC Driver for JIRA 2019J\lib\cdata.jdbc.jira.jar

C:\Program Files\CData\CData JDBC Driver for JIRA 2019J\lib\cdata.jdbc.jira.lic

f:id:sugimomoto:20200716230631p:plain

Logstashの「/logstash-core/lib/jars/」に移動します。

f:id:sugimomoto:20200716230638p:plain

JIRAに接続するためのAPIトークンを取得

次にJIRAへAPIアクセスを行うためのAPIトークンを取得します。APIトークンの取得方法については下記URLを参照してみてください。

https://ja.confluence.atlassian.com/cloud/api-tokens-938839638.html

Elasticsearch・Kibanaの起動

今回はJiraからElasticsearchにデータを取り込むので、予めElasticsearchを起動しておきましょう。また後ほどKibana上で動作確認をするので、こちらも立ち上げておきます。

> Elasticsearch-7.8.0\bin\Elasticsearch

> kibana-7.8.0-windows-x86_64\bin\kibana

起動後、「http://localhost:9200/」を参照して、Elasticsearchにアクセスできることを確認します。

f:id:sugimomoto:20200716230646p:plain

http://localhost:5601/」でKibanaにもアクセスできました。

f:id:sugimomoto:20200716230652p:plain

Logstash用のconfファイルの作成

それでは、Logstashでデータ転送を行うための設定ファイルを作成していきたいと思います。

今回はJIRAの課題(Issue)データをElasticsearchに転送します。

f:id:sugimomoto:20200716231010p:plain

まず取得するデータを確認しましょう。

CData JIRA JDBC DriverはJIRAのAPISQLで実行できるようにしている製品なので、以下のヘルプにあるように各APIリソース毎にスキーマを提供しています。

http://cdn.cdata.com/help/BJE/jp/jdbc/pg_alltables.htm

JIRAのIssueが取れるのは「Issues」テーブルなので、これを取得するクエリを記述します。Logstashだけだとちょっとどんなデータが取れるかわかりづらいので、JDBCSQLを手軽に実行できるDbVizualizerで少し見てみましょう。

接続手順は以下のURLを参照してみてください。

https://www.cdata.com/jp/kb/tech/jira-jdbc-dbv.rst

以下のように「SELECT * FROM Issues」のSQLを実行することで、JIRA API経由でデータを取得できます。

またWhere句も「SELECT *,Updated as TrackingColumn FROM Issues WHERE Updated >= '2020-07-16 11:06:00.224000';」といった形で使用できます。

f:id:sugimomoto:20200716230701p:plain

このクエリを元にLogstashのデータ処理定義である「logstash.conf」ファイルを以下のように作成しました。InputはJDBC、OutputはElasticsearchになっていて、30秒ごとに最新のデータを取得する設定にしています。

input {
  jdbc {
    jdbc_driver_library => "../logstash-core/lib/jars/cdata.jdbc.jira.jar"
    jdbc_driver_class => "Java::cdata.jdbc.jira.JIRADriver"
    jdbc_connection_string => "jdbc:jira:Url=https://XXXXX.atlassian.net;APIToken=XXXXX;User=XXXX@XXXX.com;"
    jdbc_user => ""
    jdbc_password => ""
    schedule => "*/30 * * * * *"
    statement => "SELECT * FROM Issues WHERE Updated >= :sql_last_value"
    last_run_metadata_path => "../.logstash_jdbc_last_run"
  }
}

filter {
  mutate {
    copy => { "id" => "[@metadata][_id]"}
    remove_field => ["id"]
  }
}

output {
  Elasticsearch {
      index => "jira_issues"
      document_id => "%{[@metadata][_id]}"
  }
}

いくつかのパラメータについて解説しますと

  • jdbc_driver_library:対象となるJDBC jarファイルを指定します。先の手順で「/logstash-core/lib/jars/」に配置した「cdata.jdbc.jira.jar」を指定してください。
  • jdbc_driver_class:JDBC Driverのクラス名を指定します。ここでは「Java::cdata.jdbc.jira.JIRADriver」と指定します。Driver Class 名だけでなく、頭に「Java::」が必要です。
  • jdbc_connection_string:JIRA Driverに接続するための各種認証情報を接続文字列として入力します。先の手順で取得したAPI Tokenと接続先のJIRA URL、ログインユーザーIDを指定してください。
  • jdbc_user & jdbc_password:CData JDBC Driverでは利用しませんが、LogstashのConfigファイルの仕様上必須なので、空文字を指定します。
  • schedule:CRON式でデータの取得間隔を指定します。今回は30秒ごととしました。
  • statement:データを取得するためのSQLを指定します。「:sql_last_value」には前回の実行時間が入力されるので、それを元に差分だけ取得するSQLにしています。
  • last_run_metadata_path:前回の実行時間が入力されるファイルの場所を指定します。「:sql_last_value」で使用される値です。

Class名や接続文字列などは JIRA Driver のヘルプが参考になります。

「filter」では取得したJIRAのIdをMetadataフィールドに格納しています。

「output 」ではElasticsearchに転送する先となるIndex名と予め「filter」でコピーしておいたIdをElasticsearchのdocument_idとして指定しました。

以上で「logstash.conf」ファイルの作成は完了です。

Logstashの実行

それでは作成した「logstash.conf」ファイルを元にLogstashを実行してみます。

> logstash-7.8.0\bin\logstash -f logstash.conf

実行後、以下のようなログが出ていれば、処理が実行されています。

[2020-07-16T22:25:08,593][INFO ][logstash.inputs.jdbc     ][main][56098d6447be2ed079765ec6c2c7b73d0586b7be4c608fdf52c99ca0c49b883d] (6.786616s) SELECT *,Updated as TrackingColumn FROM Issues WHERE Updated >= '1970-01-01 00:00:00.000000' ORDER BY Updated ASC
[2020-07-16T22:25:32,300][INFO ][logstash.inputs.jdbc     ][main][56098d6447be2ed079765ec6c2c7b73d0586b7be4c608fdf52c99ca0c49b883d] (1.887040s) SELECT *,Updated as TrackingColumn FROM Issues WHERE Updated >= '2020-07-16 13:25:01.173000' ORDER BY Updated ASC

一番最初のクエリはデータ全体を取得するためにデフォルト日付「1970-01-01」以上で取得していますが、2回め以降は30秒刻みで最新のデータを取得するクエリになります。

Kibanaに移動して、実際に転送されたデータも見てみましょう。

DevToolsで以下のクエリを実行してみました。

GET jira_issues/_search
{
  "query": {
    "match_all": {}
  }
}

全部で344件、全部データが格納されていました!

f:id:sugimomoto:20200716230714p:plain

ちゃんと以下のJIRAのIssueが取り込まれていることがわかります。

f:id:sugimomoto:20200716231010p:plain

おわりに

とても手軽に ElasticSeach へ JIRA のデータ取り込むことができました。

CData では JIRA 以外にも数多くの JDBC Driver を提供しています。

kintone や Sansan といった日本のクラウドサービスや SalesforceGmail などKBやナレッジが非定形で蓄積されているようなデータソースにも対応しているので、エンタープライズ検索のデータとして活用できるのではないかなと思います。

https://www.cdata.com/jp/jdbc/

f:id:sugimomoto:20200116122333p:plain

すべて30日間のトライアルがあるので、是非一度試してみてください。

参考記事

https://www.elastic.co/jp/blog/how-to-keep-Elasticsearch-synchronized-with-a-relational-database-using-logstash