PHPからElasticsearchへbulkインポートする

PHPからElasticsearchへデータを投入するサンプルがググってもサクっと見つからなかったので ドキュメントなどを見ながら実装してみたメモ。

ライブラリは本家のPHP用クライアントライブラリを使用。

http://www.elasticsearch.org/guide/en/elasticsearch/client/php-api/current/

composer.jsonにこんな感じで追加。

{
    "require": {
        "elasticsearch/elasticsearch": "1.2.*"
    }
}

Elasticsearch\Clientクラスのbulkメソッドには以下のようなコメントが記述してあるのですが、

    /**
     * $params['index']       = (string) Default index for items which don't provide one
     *        ['type']        = (string) Default document type for items which don't provide one
     *        ['consistency'] = (enum) Explicit write consistency setting for the operation
     *        ['refresh']     = (boolean) Refresh the index after performing the operation
     *        ['replication'] = (enum) Explicitly set the replication type
     *        ['body']        = (string) Default document type for items which don't provide one
     *
     * @param $params array Associative array of parameters
     *
     * @return array
     */
    public function bulk($params = array())

ElasticsearchのbulkAPIは、ほかのAPIとは違い、送信データ本体に以下のような配列を与える必要があるので、
[インデックス、タイプ、ID],
[データ本体],
.....

$es = new \Elasticsearch\Client([
    'hosts' => ['localhost:9200'],
]);
$params = ['index' => '', 'type' => '', 'body' => []];
for(....){
    $index = 'logstash-' . $date->format('Y.m.d');
    $type = ....;
    $id = ....;
    $params['body'][] = ['index' => ['_index'=>$index, '_type' => $type, '_id' => $id]];
    $params['body'][] = $log;
}
$res = $es->bulk($params);
if($res['errors']){
    throw new Exception('elasticsearch import error');
}

こんな感じで、bodyにデータをセットしてbulkAPIを呼ぶ必要があるようです。

こんな感じでデータベース上に保持してあるログデータをcronでelasticsearchに投入してカジュアルに集計、可視化できる環境を構築中。

JMeter自分用メモ

たまにしか使わなくて、使うたびに忘れててググる必要あるからメモっておく。

CUIで起動オプションで変数定義

${__P(hoge,1)}  

こんな感じでJMX内で定義して以下のように実行する
jmeter -n -t access.jmx -Jhoge=fuga

ファイルから変数にロード

[前処理]-[ユーザーパラメータ]を追加して、繰り返しごと更新をチェック
${__StringFromFile(hoge.txt)}

共通パラメータ

[設定エレメント]-[HTTPリクエスト初期設定]で設定しておく。
サーバ名、ポート、共通パラメータなど。(opensocial_系パラメータとかね)
※自動リダイレクトがONの場合、リダイレクトしたときに初期設定で指定したパラメータは付与されない!

レスポンスに応じて次のリクエストでパラメータ等を変化させる

[後処理]-[正規表現抽出]でレスポンスボディやレスポンスヘッダから情報を取得する。
Locationヘッダを受け取るなら以下のような感じで。
このとき、[リスナー]-[結果をツリーで表示]を追加しておくと、レスポンスの内容が確認できる。

デバッグ

なんかうまくいかない場合、変数などをLogViewerに出力してプリントデバッグする
[リスナー]-[BeanShellListener]を追加して、script部分に以下のように記述しておく。 ${__log("hoge = ${hoge}",WARN)}

・・・・

MessagePack for Scalaでシリアライズ

RedisにScalaのオブジェクトを保存するため、MessagePackでシリアライズしてみる。 QuickStartを参考に書いてみる。

import org.msgpack.ScalaMessagePack._
import org.msgpack.annotation.Message
@Message
case class Test(hoge:Int, fuga:Int)

val v = Test(1,2)
val binary = write(v)

すると、こんなエラーが。

[MessageTypeException: org.msgpack.template.builder.TemplateBuildException: org.msgpack.MessageTypeException: Can't find plain constructor or companion object]

引数なしのコンストラクタが必要らしい・・・。 ということで、こんな感じに。

import org.msgpack.ScalaMessagePack._
import org.msgpack.annotation.Message
@Message
case class Test(var hoge:Int, var fuga:Int){
  def this() = this(0,0)
}

val v = Test(1,2)
val binary = write(v)
val test = read[Test](binary)

とりあえず、これでcase classなインスタンスシリアライズできるようになりました。 これで、Redisに書き込む準備ができました。

flex-falconであそんでみる(2)

前回ビルドしてできた「compiler.jar」を使ってSWFをパースしてみる。

compiler.jarは、antでビルドしたときにダウンロードしてきた以下のライブラリに依存している。

  • antlr.jar
  • guava.jar
  • jburg.jar
  • lzma-sdk.jar
  • commons-cli.jar
  • commons-io.jar

とりあえず、Mavenリポジトリが見つかったライブラリはリポジトリから。それ以外はローカルのjarを使うようにPOMを書いてプロジェクトを作成。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>falcon-test</groupId>
  <artifactId>falcon-test</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <configuration>
          <encoding>UTF-8</encoding>
          <source>1.6</source>
          <target>1.6</target>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

  <dependencies>
      <dependency>
          <groupId>antlr</groupId>
          <artifactId>antlr</artifactId>
          <version>2.7.7</version>
      </dependency>
      <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.4</version>
      </dependency>
      <dependency>
          <groupId>commons-cli</groupId>
          <artifactId>commons-cli</artifactId>
          <version>1.2</version>
      </dependency>
      <dependency>
          <groupId>com.google.guava</groupId>
          <artifactId>guava</artifactId>
          <version>13.0.1</version>
      </dependency>
      <dependency>
          <groupId>lzma-sdk</groupId>
          <artifactId>lzma-sdk</artifactId>
          <version>1.0.0</version>
          <scope>system</scope>
          <systemPath>${basedir}/lib/lzma-sdk.jar</systemPath>
      </dependency>
      <dependency>
          <groupId>jburg</groupId>
          <artifactId>jburg</artifactId>
          <version>1.0.0</version>
          <scope>system</scope>
          <systemPath>${basedir}/lib/jburg.jar</systemPath>
      </dependency>
      <dependency>
          <groupId>flex-falcon</groupId>
          <artifactId>flex-falcon</artifactId>
          <version>1.0.0</version>
          <scope>system</scope>
          <systemPath>${basedir}/lib/compiler.jar</systemPath>
      </dependency>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.10</version>
          <scope>test</scope>
      </dependency>
  </dependencies>
</project>

一通り、バイナリのパーサ、タグの実装がそろっているので、SWFファイルの読み込みがこんなに簡単に。

SWFReader reader = new SWFReader();
ISWF swf = reader.readFrom(is, fileName);
int frameCount = swf.getFrameCount();
for(int i = 0; i < frameCount; i++){
    SWFFrame frame = swf.getFrameAt(i);
}

画像系のタグもパースされてJavaで扱いやすくなってるのかなーと思ったけど、そこまでは実装されていないようで・・・・、ヘッダ部分以外はバイナリがそのまま byte[] に突っ込まれている。

ひとまず、DefineBitsJPEG2タグをJPEGファイルに変換できるように実装してみた。 ソースはこちらに https://github.com/taka7646/falcon-sample

この調子で、画像+JSONに変換するコンバータに仕上げていきたい。

flex-falconで遊んでみる(1)

先日参加したSWF研究会#2のLTで紹介されていたflex-falconコンパイラを使って なにができるか試してみよう。

バイナリが配布されてないので、コンパイラをビルドするところから。

ビルドするためには、JDK(1.6以上),Ant,JFlex1.4.3が必要なので用意する。

git clone https://github.com/apache/flex-falcon.git

または、ZIPをダウンロードしてくる。

上記を適当なディレクトリに展開する。(今回は d:\tools 以下に展開)
環境変数を設定してビルドする。

set PATH=%PATH%;d:\tools\apache-ant-1.8.4\bin
set JFLEX_JAR=d:\Tools\jflex\lib\JFlex.jar
ant main

これでOKかと思ったら、しばらく待ってJavadoc生成時に「OutOfMemory」が発生したので、 build.xmlにメモリ設定を変更追加して再チャレンジ!
タグに以下の設定を追加
additionalparam="-J-Xmx512m"
再ビルド

ant main
........
BUILD SUCCESSFUL
Total time: 2 minutes 36 seconds

これで、compiler/generated/dist/sdk/lib/compiler.jar にライブラリJARファイルができています。 次回以降でこの「compiler.jar」使って遊びたい。

Hatena Engineer Seminarに行ってきた

9/26に開催されたHatena Engineer Seminar(http://developer.hatenastaff.com/entry/2012/09/11/141559)にいってきました。

イベントの内容についてはレポート上げてる人がたくさんいるので、感想などを。

  • 当初定員30人だったので、まぁ当選しないだろーなーって感じでカジュアルに申し込んだのに当たってしまった。
  • エンジニアセミナーとなっているけど、技術的なところは詳解程度で、わりとリクルート色の強いイベントだったような気がする。
  • あと、HatenaユーザーOFF会的な。技術的な話を期待していった自分はすごくアウェーな感じだった。
  • はてなのサービスまだあんま使ってないんですよねーって言ったら「なにしに来たのw」って言われたし。
  • TrelloとSolrはどこかで試してみよう。
  • 変化の速いWeb業界で10年続いているサービスを持っているというのはスゴイ事だと思った。ソシャゲ界隈はまだ2年ちょっとぐらいだからな。

聞けばよかったなーって事

  • ioDriveを使ってるって言ってたけど、どの辺に使ってるのか。
  • ioDriveなんかも仮想化したホストから使っているのかな。

SWF研究会#2に行ってきた

SWF 研究会#2@東京に参加してきたので、メモ。
http://connpass.com/event/979/
まとめきれてないけど、ひとまずあげとく。

SWFの情報要素とバイナリの読み方

http://www.slideshare.net/yoyayoya1/how-to-read-swf
GREEの @yoya さん
GREE Engineer'sBlogの「SWFバイナリ編集のススメ」の人でした。 いきなりバイナリDUMPがでてくるスライドでイベントの濃さがでていた。

Shapeの基礎の基礎

http://ken39arg.github.com/swfstudy/
カヤックの @ken39arg さん
Shapeのデータをパースした後に、パスをどうやって描画するかという話。 AS3とJavaScriptでの実装例。 fillStyle0とfillStyle1でパスの左右の塗りを同時に指定してるって話。

アクションスクリプト実行処理系

CyberAgentの @kohei_april20 さん
アクションスクリプトを実行するためには、VM(スタックマシン)を実装する必要がある。 評価順など、詳細仕様は公開されてないため、フレームレートを落とすなどして正しく再生できているか検証しているらしい。

FlashRuntimeEngineの実装

DeNAの @tkihira さん

ExGameのような既存のSWFを再生するプレイヤーは、本家FlashPlayerのバグ(っぽい)挙動も再現しなければならない。
※Flash職人の方々は、そのバグっぽい挙動を巧みに使ってアニメーションを作っていたりするため。

LT

感想

とても濃い内容ばかりで、楽しいイベントだった。 各発表者ごとに、ハマりどころなどこれから実装する人のための情報が盛り込んであり、これを聞いたらある程度のところまでは、実装できるような気がしてくる。 あと、LTで聞いた「SWFInvestigator」が便利。 オープンソースになったfalconコンパイラ(https://github.com/apache/flex-falcon)でSWFの読み書きができるっぽいので、これを使ってSWF->JSONのコンバータを作るのがいいのかも。