今回はblackbird pluginの書き方第一弾ってことで、blackbirdのデータ送信の仕組みについてお話をします!
同時にblackbird自体の起動シーケンシャルについてもお話できればなーと思ってます。
ではざっくり概要編逝きます。
plugin方式
blackbirdはデータ(各ミドルウェアのMetricなので厳密にはデータとは呼ばないかもしれませんが)の取得部分も、送信部分もplugin形式を採用しています。
取得するPluginは特定の基底クラスを継承したクラスを実装することで、Pluginとして成立します。
そのため、基本的にはsnipetレベルのPythonファイルをひとつ書くだけで実装できます。
起動シーケンシャル
全体のながれとしては、
- blackbirdコマンドライン(rpmでインストールすると/usr/bin/blackbird)からの起動
- blackbird.sr71.Blackbirdインスタンスの生成
- Main関数(blackbird.sr71.main)の呼び出し
- 設定ファイルの読み込み
- 取得及び送信プラグイン用にThreadを個別に作成
- 各Threadをkick
- 各ThreadがMetric用のQueueに格納及びQueueからの読み込み
というながれになってます。
2. blackbirdインスタンスの生成
blackbirdインスタンスは生成時に(__init__
メソッド呼び出し時に)configのcheckを行います。
その際root config fileといいますか、blackbird --config=CONFIG_FILE
のように--config
オプションで指定したファイルを読み込みます。
そして、include_dir
ディレクティブで指定したpathを確認して、includeされる各ファイルを読み込んでいきます。
同時に、configのparseとvalidationも行っており、この段階でvalidation errorが発生した場合、起動に失敗します。
notes:
ここでいうvalidation errorとはint型を期待しているディレクティブに対してstr型が入っていたり(int()
メソッドがValueErrorを吐くとも言い換えられます)、
必須のディレクティブが指定されていなかったりという具合です。
5. 各種plugin用にThreadを生成
各Threadには名前(名前自身には意味はありませんが、debug時の透過性をあげてくれたり、名前つきで起動されることで異なる設定で複数のpluginを読み込むことが可能になります)がつけられます。
Thread名にはconfig内のセクション名(後述)を用います。
ここでいうセクション名とは
[SECTION_NAME]
directive_001 = XXXXX
directive_002 = ABC012
上記の_SECTION_NAME_を意味します。つまり、この場合SECTION_NAMEという名前のThreadが生成されます。
6. 各Threadをkick
blackbird.sr71.BlackbirdインスタンスがMainのプロセスとなりこのプロセスが各Threadのrun
メソッドを呼び出し、run
メソッドが各pluginのデータを収集するメソッドを呼び出す仕組みです。
7. 各ThreadがMetric用のQueueに格納及びQueueからの読み込み
各ThreadはMetric用(データ用)のQueueにアイテムを投げ、また、どこかにsendするplugin用のpluginはQueueからアイテムを取り出し、データを送信します。
今までの内容を図に表すとこんな感じ
------------------------------------------
| blackbird Main process |
------------------------------------------
| | |
-- Tharead001 -- Thread002 -- Thread003 ...
---------
|-------|
|-------|
| Queue |
|-------|
|-------|
---------
# QueueはMainのprocess内に生成されるます
っで??
っで、結局なにが言いたいかって言うと、plugin書くだけならすげえ簡単で、データやMetricsを取得する部分を書いて、基底クラスのenqueueメソッドを呼び出してやれば基本的には終了です。
pluginの書き方の詳細については、次回で詳しく説明しますね。