• 67
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Norikraも0.1になり、この内容もかなり古くなりました。
Norikra0.1にあわせて新しく書き直しているので下記内容をご参照ください!
Norikra 0.1を使ってみた

Norikraで遊んでみた。

RubyKaigiで@tagomorisさんが発表していたNorkraをとりあえず手元で動かしてみた。すごく簡単に説明するとFluentdみたいなデータストリームをSQLライクな言語でごにょごにょできるものである。
NorikraのスライドはSlideShareにあるので是非見ておこう。

この記事はおそらく一瞬で古くなると思うが、環境は次のような感じだ。

product version
CRuby(MRI) 2.0.0-p195
JRuby 1.7.4
Norikra v0.0.4
Norikra::Client v0.0.3

CRuby、JRubyはrbenvとruby-buildを使ってインストールしている。

JRubyとNorikraをインストールする

$ rbenv install jruby-1.7.4
$ rbenv shell jruby-1.7.4 # このシェルだけJRubyに切り替える
$ ruby -v 
jruby 1.7.4 (1.9.3p392) 2013-05-16 2390d3b on Java HotSpot(TM) 64-Bit Server VM 1.6.0_45-b06-451-11M4406 [darwin-x86_64]

$ gem install norikra
# …snip…
Successfully installed norikra-client-jruby-0.0.3-java
Successfully installed norikra-0.0.4-java
15 gems installed

こんなかんじでインストールできた。JRubyはいっこいっこのコマンドがすごくもっさりなので注意だ。

とりあえず起動する

$ rbenv rehash # 一旦rehashを叩く
$ norikra start
log4j:WARN No appenders could be found for logger (com.espertech.esper.core.service.EPServiceProviderImpl).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
"Norikra server started."

norikra-clientを使ってみる

起動したようなので別のシェルからnorikra-clientを叩いてみる。
JRubyだとうまく動かなかったけど、requireが異なるから起こってただけだったのでさくっと書き換えた。

--- .rbenv/versions/jruby-1.7.4/lib/ruby/gems/shared/gems/norikra-client-jruby-0.0.3-java/lib/norikra/client.rb.original        2013-06-04 10:22:08.000000000 +0900
+++ .rbenv/versions/jruby-1.7.4/lib/ruby/gems/shared/gems/norikra-client-jruby-0.0.3-java/lib/norikra/client.rb 2013-06-04 10:12:44.000000000 +0900
@@ -1,6 +1,6 @@
 require "norikra/client/version"

-require 'msgpack-rpc-over-http'
+require 'msgpack-rpc-over-http-jruby'

これで動くようになった。CRubyだとこの問題起こらないし、動作さくさくなので普通にCRubyにnorikra-client入れた方が良い。

$ norikra-client
Commands:
  norikra-client event CMD ...ARGS   # send/fetch events
  norikra-client field CMD ...ARGS   # manage target field/datatype definitions
  norikra-client help [COMMAND]      # Describe available commands or one specific command
  norikra-client query CMD ...ARGS   # manage queries
  norikra-client target CMD ...ARGS  # manage targets

Options:
  [--host=HOST]
                 # Default: localhost
  [--port=N]
                 # Default: 26571

Norikraでは所謂テーブルの事をtarget、テーブルのカラムのことをfield、クエリのことをquery、入力するログや出力される結果のことをeventと呼ぶ。

とりあえずnorikra-clientで、適当なtargetを作ってみる。

$ norikra-client target open access user:string path:string
$ norikra-client target list
TARGET
access
1 targets found.

で、適当なqueryを書いて登録する。NorikraのクエリはEsperのEPLというSQLライクな言語を使って書く。

$ norikra-client query add access_count "SELECT user, count(*) AS access_count FROM access.win:time_batch(10 sec) GROUP BY user"

あとは適当なeventを流す。

$ echo '{"user":"kame", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"kame", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"kame", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | norikra-client event send access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | norikra-client event send access

で、てきとうに結果のeventを見てみる。

$ norikra-client event fetch access_count
{"time":"2013/06/04 10:50:20","user":"kame","access_count":3}
{"time":"2013/06/04 10:50:20","user":"usagi","access_count":4}
$ norikra-client event fetch access_count
{"time":"2013/06/04 10:50:30","user":"kame","access_count":0}
{"time":"2013/06/04 10:50:30","user":"usagi","access_count":0}

こんな感じで結果が返ってくるのがわかる。こんなかんじでSQLライクなクエリでGROUP BYとかが簡単に行えるのである。

Fluentdからログを流したい

実際に使うのであればFluentdからログを流したい。Norikraはfluent-plugin-norikra
を使うことでFluentdとメッセージのやりとりができる。

$ gem install fluent-plugin-norikra

fluent.confに直接Norikraのクエリを記述することもできるが、直接クエリを書いてしまうと変更する度にFluentdを再起動しなくてはいけなくなる。できるのであればFluentdの設定には、データをNorikraに流して結果を受け取ることだけを書きたい。

これを実現できる機能がEvent sweepingのようだ。<event>セクションを記述することでこれが実現できる。

fluent.conf
<source>
  type forward # listen port 24224
</source>

<match input.*>
  type copy

  <store>
    type stdout # 標準出力で確認できるように
  </store>

  <store>
    type norikra
    norikra localhost:26571 # デフォルト設定

    target_map_tag yes      # tagをtarget名に使う
    remove_tag_prefix input # tagのprefixを除去する

    <event>
      method sweep
      tag    query_name        # query名をタグにする
      tag_prefix norikra.event # tag: norikra.event.QUERYNAME
      sweep_interval 5s        # 出力間隔
    </event>
  </store>
</match>


<match norikra.**>
  type stdout # 結果も標準出力で確認する
</match>

fluent-plugin-norikraにはNorikraを自動起動する設定とかも書けるが、裏側でエラーが出てないか確認したかったので、とりあえず最低限の設定だけ書いている。Norikraは起動したままでFluentdを起動する。

$ fluentd -c fluent.conf
# …snip…
2013-06-04 10:55:22 +0900 [info]: adding source type="forward"
2013-06-04 10:55:22 +0900 [info]: adding match pattern="input.*" type="copy"
2013-06-04 10:55:22 +0900 [info]: adding match pattern="norikra.**" type="stdout"
2013-06-04 10:55:22 +0900 [info]: listening fluent socket on 0.0.0.0:24224

起動したら別のシェルを開いて、fluent-catからデータを流してみる。流すデータは先程と同じだ。

$ echo '{"user":"kame", "path":"http://example.com/"}' | fluent-cat input.access
$ echo '{"user":"kame", "path":"http://example.com/"}' | fluent-cat input.access
$ echo '{"user":"kame", "path":"http://example.com/"}' | fluent-cat input.access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | fluent-cat input.access
$ echo '{"user":"usagi", "path":"http://example.com/"}' | fluent-cat input.access
2013-06-05 10:58:42 +0900 input.access: {"user":"kame","path":"http://example.com/"}
2013-06-05 10:58:46 +0900 input.access: {"user":"kame","path":"http://example.com/"}
2013-06-05 10:58:51 +0900 input.access: {"user":"kame","path":"http://example.com/"}
2013-06-05 10:58:53 +0900 norikra.event.access_count: {"user":"kame","access_count":3}
2013-06-05 10:58:55 +0900 input.access: {"user":"usagi","path":"http://example.com/"}
2013-06-05 10:58:56 +0900 input.access: {"user":"usagi","path":"http://example.com/"}
2013-06-05 10:59:03 +0900 norikra.event.access_count: {"user":"kame","access_count":0}
2013-06-05 10:59:03 +0900 norikra.event.access_count: {"user":"usagi","access_count":2}

こんなかんじで結果セットをFluentdに流すことができた!

まとめ

ということで、出たばかりのNorikraを使ってみた。Norikra使うとSQLライクな感じでログをフィルタできて楽しいし、なにより動的にクエリを追加したり削除したりできるのが嬉しい。

まだまだ、登録したqueryの削除が実装されてないとか、上記以外の動作だと結構エラー出たりとか実用するにはちょっと足りてなさそうだけど、今後に期待である。