PhoenixのLogger
とりあえず、アプリが起動する状態になった。
Phoenix・Elixir をちょっとさわって思ったのは、コード上に型が現れてれていないとなにかと調べにくい、ということ。馴染みのある言語なら、型が現れてなくてもなんとかなっちゃうんだけど、馴染みのない言語だとそうはいかない。
結局コード見ててもわからないので、ログを出しまくって、どういう動きをするか、どういうデータが入力・出力されるのかを追っているところ(デバッガみたいなのはある?)。まあ、始めはログの出し方もわからなかったのだけれど。
Logger
debug, info, warn, error の4レベルがある。
使い方としてはこんな感じ(サンプルはここで作ったhello_phoenixプロジェクト)。
defmodule HelloPhoenix.PageController do use HelloPhoenix.Web, :controller require Logger def index(conn, _params) do Logger.error "Error!!!" Logger.warn "Warn!!" Logger.info "Info!" Logger.debug "Debug" render conn, "index.html" end end
ログの設定は config の下の設定ファイルで変えられる。
出力先はデフォルトで :console となっている。
ファイルに落とすにはリダイレクトするのかな...?と思って調べたら Backend
というものがあって、そこにファイルに直接ログを出力する拡張機能を追加すれば、リダイレクトは不要。標準ではファイルに落とす拡張機能は用意されていないが、logger_file_backendが公開されていたので使ってみる。
まずは mix.exs 依存関係を追加して、% mix deps.get
でダウンロードする。
--- mix.exs.orig 2015-08-15 15:12:58.149425240 +0900 +++ mix.exs 2015-08-15 15:13:18.074069599 +0900 @@ -31,6 +31,7 @@ [{:phoenix, "~> 0.16"}, {:phoenix_html, "~> 2.0"}, {:phoenix_live_reload, "~> 0.6", only: :dev}, + {:logger_file_backend, "~> 0.0.3"}, {:cowboy, "~> 1.0"}] end end
設定ファイルはこんな感じ。
--- config/dev.exs.orig 2015-08-15 15:08:00.514099611 +0900 +++ config/dev.exs 2015-08-15 15:10:06.139743337 +0900 @@ -24,4 +24,7 @@ ] # Do not include metadata nor timestamps in development logs -config :logger, :console, format: "[$level] $message\n" +config :logger, backends: [{LoggerFileBackend, :file}] +config :logger, :file, + path: "/tmp/hello_phoenix.log", + level: :debug
結果
% cat /tmp/hello_phoenix.log 15:16:29.472 [info] Running HelloPhoenix.Endpoint with Cowboy on http://localhost:4000 15:16:49.496 [info] GET / 15:16:49.510 [debug] Processing by HelloPhoenix.PageController.index/2 Parameters: %{"format" => "html"} Pipelines: [:browser] 15:16:49.526 [info] Sent 200 in 29ms
Phoenixを始めてみた
Phoenix が気になったので、さわり始めた。
Phoenix は Elixir で書かれていて、アプリを作る場合も Elixir で書く。Phoenix もElixir も今まで使ったことがなく、初めての言語、初めてのフレームワークで、いろいろとつまづくことが多そう。その反面、面白いこともありそうなわけで。
とりあえず環境を整えよう。
環境構築
Erlang, Elixir, Phoenix をインストールする。
Elang, Elixir は anyenv を使ってインストールする。
今回インストールしたバージョンは
- Erlaang/OTP 18
- Elixir 1.0.5
- Phoenix 0.16.0
OS は Ubuntu 14.04.3。
*env
anyenv のインストールはREADME.md を参照。
% anyenv install erlenv % anyenv install exenv
Erlangのインストール
Erlang は erlang-build みたいなのがないので、自分でビルドする。
% curl -O http://www.erlang.org/download/otp_src_18.0.tar.gz % tar xzf otp_src_18.0.tar.gz % cd otp_src_18.0 % ./configure --prefix=/home/ymmtmsys/.anyenv/envs/erlenv/releases/18.0 % make -j4 % make install % erlenv global 18.0
ソースは消してOK.
Elixirのインストール
% exenv install -l # 最新バージョンの確認のため % exenv install 1.0.5 % exenv global 1.0.5
Phoenix のインストール
公式ドキュメントを参照
node.js はすでに入っているので省略。
Up And Running
ここ を参考に、サンプルのアプリが起動するか確認。
% mix phoenix.new hello_phoenix % hello_phoenix % mix phoenix.server . . . [info] Running HelloPhoenix.Endpoint with Cowboy on http://localhost:4000 [warning] the :size option when configuring HelloPhoenix.Repo is deprecated, please use :pool_size instead 14 Aug 11:03:56 - info: compiled 5 files into 2 files, copied 3 in 2675ms [info] GET / [debug] Processing by HelloPhoenix.PageController.index/2 Parameters: %{"format" => "html"} Pipelines: [:browser] [info] Sent 200 in 17ms
Ok.
warning は設定ファイルのフィールド名を変えれば出なくなる。
--- config/dev.exs.orig 2015-08-14 11:21:57.671526209 +0900 +++ config/dev.exs 2015-08-14 11:22:01.059526209 +0900 @@ -32,4 +32,4 @@ username: "postgres", password: "postgres", database: "hello_phoenix_dev", - size: 10 # The amount of database connections in the pool + pool_size: 10 # The amount of database connections in the pool
mipmap
問題
R.drawable.ic_launcher
と書くと Cannot resolve symbol ic_launcher
というエラーが出る。
解決
drawable
ではなく mipmap
を使う。R.mipmap.ic_launcher
。
現在使用している Android Studio のバージョンは 1.2.2。プロジェクトのディレクトリをよくよく見ると res/drawable
の下には何もなく、res/mipmap
の下にはきちんとアイコンが用意されていた。
本に載っていたコードを写していたのだけれど、写しているだけで、そこまで見れていなかった。
Google Play services out of date
問題
Androidアプリ開発時以下のようなログが出力され、アプリが落ちることがあった。
Google Play services out of date. Requires xxxxxxx but found yyyyyyy
xxxxxxx や yyyyyyy バージョン番号。
解決
「Google Play 開発者サービス」アプリをアップデートする。
もしかしたら、アップデート後 Android Studio を再起動する必要があるかも。 なぜかというと、アップデート後 マニフェストファイルにパーミッションを追加せよ、というエラーが出力された。でも、そのパーミッションはすでに追加されていた。Android Studio を再起動したところその問題は解消されたので。
リンク
UNIXの哲学と関数型プログラミング
UNIXの哲学と関数型プログラミングは共通しているところがあるよね、というのを最近同僚と話した。
ここでいうUNIXの哲学とは
- スモール・イズ・ビューティフル
- 一つのプログラムには一つのことを うまくやらせる
- ソフトウェアの挺子を有効に活用する
など(「UNIXという考え方-その設計思想と哲学」より)。
それらと、関数型プログラミングの、一つの機能に絞った小さな関数を組み合わせ、大きな関数を作っていくという部分が似ているなと。
とりわけ強くそう思うのが、UNIXでコマンドをパイプで繋げて自分の期待する結果を得るところ。関数型プログラミングだと、関数合成にあたる。
UNIXの操作に慣れている人なら、関数型プログラムもしっくりくるのでは。
PHPのjson_encode
少数点以下の数が0の場合はコンパクトになる!
<?php echo json_encode(['foo' => 123.45, 'bar' => 658.00]) . PHP_EOL; # => {"foo":123.45,"bar":658}
これが原因か...
不正なHTTPヘッダ
リバースプロキシとしてアプリケーションの前にnginxを置いている.
あるとき, アプリケーションにリクエストヘッダが渡らないんですけど, という問い合わせがきた.
うーん, 自分が使っている分にはヘッダは渡ってきてるんだけどな...
とりあえず, どんなリクエストを投げてるのか教えてもらったので, 試してみたところ, 報告通りヘッダが渡ってこない.
nginx を通さずに直接アプリケーションにそのリクエストを投げるとヘッダが渡ってきた. 原因はnginxにあることが判明した.
どうなっているかを把握するため debug ログを出すことにした.
/etc/nginx/nginx.conf
- error_log /var/log/nginx/error.log warn; + error_log /var/log/nginx/error.log debug;
すると以下のログが出た.
2015/01/21 09:00:16 [info] 3057#0: *2 client sent invalid header line: "X-Hoge : 1234" while reading client request headers, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", host: "localhost"
client sent invalid header line
...不正なヘッダを送っているため、nginx で落とされているようだ.
rfc2616 によると Message Header は
message-header = field-name ":" [ field-value ] field-name = token
となっていて, token は
token = 1*<any CHAR except CTLs or separators> separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
となっている.
field-name と ":" の間にコントローコードやセパレータががあってはいけない.
今回は field-name と ":" の間に空白があるため, 不正なヘッダとして扱われたようだ.
nginx の設定で ignore_invalid_headers をoff にすればヘッダを落とさずにアプリケーション側に投げてくれる.
けど, まあ空白なしがRFC的に正しいので, 空白を削除してリクエストを投げてもらうことで解決.