Boring Days as tech

金に生きるは下品にすぎる、 恋に生きるは切なすぎ、 出世に生きるはくたびれる。 とかくこの世は一天地六。 命ぎりぎり勝負をかける。 仕事はよろず引き受けましょう。 大小遠近男女は問わず、委細面談、仕事屋稼業。

素のfluent-plugin-elasticsearch使ってkibanaで描画するだけではちょっと使うの難しい

"実践"としてかっちょいい監視ツールを利用したい

かっちょいい監視ツールにあこがれて fluentd - elasticsearch - kibana を使ってみたので実際に使えるようになるまでのポイントを幾つか。

そんなtype想定してない

fluent-plugin-elasticsearchだと読み込んだログを基本的に全部文字列として構造化してしまうので、各所最適化されたmappingができない。type:integerで入って欲しいが、文字列なのでtype:stringでmappingされたりする。そこでplugin自体をカスタマイズして数値型としてmappingすると、今度はtype:longでmappingされてしまう。type:ipとかを利用したくても同様の結果になる。

勝手にexpireして欲しい

ログ監視なので一定期間過ぎたindexは自動で消えてくれるといいんだけど、なかなかそういう設定ができない。なのでelasticsearchのTTL機能などを使おうとする。しかしfluent-plugin-elasticsearchはmappingが自動的にされるので各documentやindexに対してTTLを設定することができない。また、設定してもdocumentにTTLに設定してもindexのmappingを_ttl:{enabled:true}にしなければTTLは動かない。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-ttl-field.html

加えて、このelasticsearchのTTL機能についてはパフォーマンスが落ちるので好ましくないとのことが公式で以下に載っている。なのでcronで定期的にindexを削除するといいよ、という話。結局cron頼みになるのかな?

http://www.elasticsearch.org/tutorials/using-elasticsearch-for-logs/

検索パフォーマンス

analyzerちゃんと設定しないといけませんよね?
documentを構成するデータに合わせたanalyzerを設定できてる?

elasticsaerch自体のパフォーマンス

デフォルト設定ではそもそも性能に限界がある。
その辺りのパフォーマンスチューニングはデータストアとして切っても切れないので、
利用用途と現状に合わせたチューニングが必要。

template機能

fluentdでデータを投げる前にちゃんとデータ構造を定義して明示的に最適化されたmappingでelasticsaerchにdocumentを保持するべき。analyzerも設定しなければならない。そのためにtemplate機能。これを設定すると指定の条件のindexに対して設定したtemplateをベースにdocumentを生成保存してくれる。結局全く何も考慮せずにデータを突っ込むといのは危険ということ。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html

まとめ

素のプラグインでlogを収集して素で突っ込むだけでは結局使えない。
要は実践で使うにはやはり色々考慮しないといけない。まる。
特にmappingはきっちりやること。そのためのtemplate。
analysisとかtokenizerととelasticsaerch自体のパフォーマンスチューニングはまた今度。

apacheでwordpressとpassenger/railsを共存させる

railsをルートとしてwordpressを入れ込む形での共存はよく見かけたけども逆のパターン(wordpressの下部にrailsを入れ込む)がなかなか見つからなかったのでメモっとく。

1.
railsのプロジェクトをapacheのユーザー権限が届く位置に設置する
たとえばapacheユーザがuser_1だった場合、/home/user_2/*に置いても参照されない
なので/home/user_1/*とかに置く

2.
DocumentRoot(ここでは/home/user_1/localhost)配下にrailsプロジェクト(publicディレクトリ)のシンボリックリンクを貼る

ln -s /home/user_1/rails/public /home/user_1/localhost/utils

3.
あとはapacheのconfig設定。
ここではvconf.d/hoge.confのような例を示す

# railsの基本設定
RackEnv production
RackBaseURI /utils

# wordpress
<VirtualHost *:8081>
  ServerName localhost
  ServerAdmin root@localhost
  DocumentRoot /home/user_1/hogehoge.public_html
  ErrorLog /var/log/httpd/localhost/error_log
  CustomLog /var/log/httpd/localhost/access_log combined
  ErrorDocument 404 /404.html
  DirectoryIndex index.php

  # wordpress内はpassengerを動かさない
  PassengerEnabled off
  PassengerResolveSymlinksInDocumentRoot On

</VirtualHost>

# wordpressのディレクトリディレクティブ
<Directory "/home/user_1/localhost">
  Options FollowSymLinks MultiViews ExecCGI
  AllowOverride All
  Order allow,deny
  Allow from all
</Directory>

# railsのディレクトリディレクティブ
<Directory "/home/user_1/localhost/utils">
  PassengerEnabled on
  Options FollowSymLinks -MultiViews
  AllowOverride All
  Order allow,deny
  Allow from all

  # URI書き換えによってrailsディレクトリ以下はrailsのルーティングに入るようにする
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.php$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !utils
  RewriteRule . /index.php [L]
</Directory>

Arrayを__proto__で機能拡張したときのfor inの注意点

昔書いてたメモ。

たとえばArrayオブジェクトを以下のように拡張する。
すると普通にArrayオブジェクトからemptyメソッドが使えるようになる。

Array.prototype.__proto__ ={
  empty : function(){return "emptyが呼ばれたよ!";}
}

var ary = [];
alert(ary.empty()); //"emptyが呼ばれたよ!"

そしてfor inをしたときには以下のようになる。

Array.prototype.__proto__ ={
  empty : function(){return "emptyが呼ばれたよ!";}
}

var ary = ["1","2","3"];
var str = "";
alert(ary.length); // "3"←3つの値を配列として保持させたのでlengthは勿論3となる
for(var i in ary){
  str += i;
}
alert(str); // "012empty"←lengthが3なので"012"となることを期待したが…

このようにlengthは初期化した時の3のままなのに、
何故か4つめが存在していてしかもその4つめが拡張したemptyとなっている。
これはjavascriptの以下の性質の為と思われる。

var obj ={
  test0 : "",
  test1 : function(){},
  test2 : function(){}
}

var str="";
for(var i in obj){
 str+=i;
}
alert(str); // "test0test1test2"←オブジェクトも連想配列として認識する為にobj配下にあるプロパティを呼んでいる。

このようにjavascriptのfor in文はオブジェクト配下のプロパティすべてを走査するため、
__proto__による拡張したメソッドまでループの中で呼び出されてしまう。
まあfor..inは連想配列に対して行うということですね。

GCMまでの流れ〜GoogleDevelopersConsoleの設定編〜

この記事は2014年1月27日時点の設定です。
GCM(Google Cloud Messaging)を利用するにあたりGCM側の設定をしなければなりません。
で、C2DMからGCMに変わり、API ConsoleからGoogle Dev Consoleになったので、
設定周りが多少変わっており、整理のために個人的なメモとして残しておきます。

プロジェクトの作成

GoogleDevelopersConsoleにアクセス
トップのCreateProjectをクリックし任意のプロジェクトを作成する
Projectsに作成したプロジェクトが追加される。

APIの有効化

作成したプロジェクトをクリックしプロジェクト詳細に遷移。
ここのoverviewに表示されるproject numberAndroidアプリでregistration idを発行するときに必要な値。
APIs & authのAPIsから「Google Cloud Messaging for Android」を見つけ有効化(ON)にする

API keyの作成

CredentialsからPublic API accessのcreate new keyをクリック。
Server keyと進みserver側のAPI Keyを作成する。
使用するサーバー側のIPを制限したい場合はここでIP指定をする。
同じようにcreate new keyから今度はAndroid keyと進みclient側のAPI Keyを作成する。
こちらはAndroid applicationsの指定をする。アプリに使ったキーの「SHA1;パッケージ名」を組み合わせる。
キーのSHA1値は以下のコマンドで表示される。

keytool -list -v -keystore {キーストアのパス}
注意点

API keyはAndroidアプリ側とサーバー側両方作らないといけないよ!
サーバー側がGCMサーバーにリクエストするときに使うAPI keyはサーバー側のAPI keyだよ。
両方作るとか考えずにAndroidアプリ側のAPI keyをGCMのリクエストの値として使って動かない、みたいなのでハマってましたorz

RSR2011タイムテーブルライブ壁紙公開

RSR2011タイムテーブルライブ壁紙を公開しました。
https://market.android.com/details?id=boringdays.jp&feature=search_result


Rising Sun Rock Festival 2011 in Ezoで
Android携帯で簡単にタイムテーブルの確認ができたらいいのになぁ、
と思ったので簡単に作ってみました。
タイムテーブルの上下スクロールや日程の簡単切り替えができます。
つまり大した機能とかは全然無いです。
本番までに拡張するかもしれないけれどw
ご了承ください。


なお、なかったので作ってみた非公式勝手アプリですのでご注意を。
石狩でライジングサン見れたらいいナ!

WeakHashMap なるものがあるのね

SoftReferenceといふもの

久々にAndroid記事を書いてみるw
画像のメモリーに対する圧迫はAndroidアプリ開発のよくつっかかるポイントだと思うけれど、
そこで活躍するのは往往にしてSoftReferenceっつうクラスだと思う。
メモリーリークしそうになるとGC側が優先してSoftReferenceが持つオブジェクトを開放して、
メモリーの節約をさせるという形。
なのでたとえば、画像を相当数リスト表示する場合、オンメモリーにある画像を参照する場合、
このSoftReferenceを介することで、画面上に表示されない画像はGC側が優先的に破棄し、
相当数の画像リスト表示にも耐えられる実装となる。
結果メモリー管理も楽になれるという形。

//実装
SoftReference ref = new SoftReference<Bitmap>(bitmap);
//取得
Bitmap image = ref.get();
//解放
ref.clear();

http://developer.android.com/reference/java/lang/ref/SoftReference.html

SoftReferenceでの問題点

じゃあ、それで解決じゃんって話なんだけども、
これはSoftRefenrenceインスタンスの内部に持つObjectが解放される仕組みであって、
SoftReferenceインスタンス自体は解放されない。
なので、上記の画像のリスト表示なども、画面上に表示される画像オブジェクトは破棄されるのだが、
その画像を持っていたSoftReferenceインスタンスはメモリー上に残ったままなのである。
実際、残ってしまう空のSoftReferenceはメモリ圧迫には殆ど影響を及ぼさない量なのだけれど、
たとえば画像リスト表示を1000件以上だとかする場合、
1000個の空のSoftReferenceインスタンスがメモリー上に残ってしまう可能性がある。
こうなってくるとちょっと無視できなくなる。
そこでSoftReferenceインスタンスのリストが増えるたびに空のSoftReferenceインスタンスがないかチェックして、
あればそれを削除する、といった自前の実装が必要になってしまう。
しかしこれはメンドイ。

HashMap<string, SoftReference<Bitmap>> cache = new HashMap<string, SoftReference<Bitmap>>();

//空のインスタンスならリストから削除する
private void cleanCache(){
	for(string key : cache.keySet())
	{
		if(cache.get(key).get()==null){cache.remove(key);}
	}
}

WeakHashMap

そこでWeakHashMapの出番!
これはWeakReferenceというクラスに基づいて作られている拡張HashMapみたいなもの。
メモリーに対して一定の負荷がかかった時に内部で参照されてないオブジェクトがあった場合、
それをアイテムごと破棄してくれるというちょっと便利なモノ。
GCの判断で破棄されるのではなく、一定の負荷係数に応じて呼び出されるっぽい動き。
なので、空のインスタンスがメモリーに残ることはなく、
キャッシュの際などに大量のリスト状データが必要な場合はWeakHashMapの方が実装上楽に管理することが出来るでしょう。

//宣言するだけで後の処理は全部WeakHashMapにお任せ!
WeakHashMap<string, Bitmap> cache = new WeakHashMap<string, Bitmap>();

http://developer.android.com/reference/java/util/WeakHashMap.html



…というわけで、
WeakHashMapはふつーに昔からある代物だそうです。。。
でもSoftReferenceを使ったWeakHashMapなんてものはないみたい。

知らなかったー。

IntentService

先日のGoogleDeveloperDays2010JapanでAndroidの高速化の際に出てきてたクラス。
気になってググったらやっぱり日本語の説明があんまりないのでメモ的に簡単に説明。

ServiceをオーバーライドしたIntentService

任意の特定の処理をメインスレッドとは別のスレッドで非同期で行うためのクラス。
このサービスは通常メインスレッドでハンドリングしないような処理を行うためのものらしい
呼び出し方はサービス的だけれども同一プロセス内で別スレッドを立ち上げて処理する。
実際に実装するには、IntentServieを拡張しonHandleIntent内に特定の処理を記述する。

IntentService拡張

サービスとしてのクラスなのでインナークラスでの記述は不可能

public class CustomIntentService extends IntentService{
	private static final String name="TEST";

	public CustomIntentService() {
		super(name);
	}
	@Override
	protected void onHandleIntent(Intent intent) {
		//ここに時間のかかる重い処理を記述
	}
}
Activity側での呼び出し
    @Override
    public void onResume(){
    	super.onResume();
    	Intent intent = new Intent(Intent.ACTION_SYNC,null,this,CustomIntentService.class);
    	this.startService(intent); //ここからスタート!
    }
ちゃんとAndroidManifest.xmlにも記述
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        ・
        ・
        ・
    <service android:name="CustomIntentService"></service> //先ほどの拡張クラスを明記!
    </application>

そんなIntentServiceの中身

中身はHandlerThreadを1つ作ってそのループにキューを投げるというだけっぽいので、
たとえば同時に複数回startServiceメソッドを呼び出したとしてもここで要求される全てのリクエストは、
サービスを開始した順に同一プロセス内でシングルスレットで一つずつ処理される。
すべてのキューが終了したら通常のスレッドと同じように破棄される、という流れなのかな。
とはいえ、AsyncTaskと違うのはIntentServiceはService自身をスタートさせたActivityに依存せずに処理が続く。
AsyncTaskのように元Activityの生き死にで処理の中断などはされない。