Ectoのカスタムロガー
3.0-rc.1がもっぱら話題のEctoですが、ロガーを追加する方法をたまたま見つけたので書いておきます。Ecto.Repo
をuse
するときにloggers
っていうオプションを渡します。
defmodule MyApp.Repo do use Ecto.Repo, otp_app: :my_app, loggers: [ {Ecto.LogEntry, :log, []}, {MyApp.CustomLogger, :log, []} ] end
loggers
のデフォルト値は[{Ecto.LogEntry, :log, []}]
なので、今の挙動を変えたくないときはこんな風に追加するとよさそ。試しにこんなlog/1
で動かしてみると、
defmodule MyApp.CustomLogger do def log(entry) do IO.inspect entry, structs: false end end
[debug] QUERY OK source="nippoes" db=8.3ms SELECT n0."id", n0."date", n0."content", n0."user_id", n0."inserted_at", n0."updated_at" FROM "nippoes" AS n0 WHERE (n0."date" = $1) ORDER BY n0."inserted_at" DESC [{2018, 10, 17}] %{ __struct__: Ecto.LogEntry, ansi_color: :cyan, caller_pid: #PID<0.599.0>, connection_pid: nil, decode_time: 11000, params: [{2018, 10, 17}], query: "SELECT n0.\"id\", n0.\"date\", n0.\"content\", n0.\"user_id\", n0.\"inserted_at\", n0.\"updated_at\" FROM \"nippoes\" AS n0 WHERE (n0.\"date\" = $1) ORDER BY n0.\"inserted_at\" DESC", query_time: 8328995, queue_time: 68000, result: {:ok, %{ __struct__: Postgrex.Result, columns: ["id", "date", "content", "user_id", "inserted_at", "updated_at"], command: :select, connection_id: 15165, num_rows: 0, rows: [] }}, source: "nippoes" }
こんなログが出ました。引数はEcto.LogEntry
の構造体ですね。query_time
(ナノ秒)を見て、時間かかってたらLogger.warn
したりとか良いんじゃないでしょうか。本番環境だとNewRelicだなんだありますけど、開発環境とかテストとかで。
ExUnitAssertMatchっていうパッケージを書いた
伝わる人には伝わる言い方をすると、https://github.com/r7kamura/rspec-json_matcherみたいなことがしたい。
例えばPhoenixのコントローラのテストとかで、レスポンスのJSONの形式をテストしたいときに
assert json["user"]["name"] == "John" assert json["user"]["age"] == 28 assert json["user"]["orgs"][0]["name"] |> is_binary()
とか全部書くのダルいし、もうちょいどんなJSONを求めてるのかわかるようにしたかった。あとElixirのパッケージ最近書いてなくて、リハビリしたかったというのもモチベーションの1つ。最初はマクロで実装しようと考えて書き始めたけど、そのまま機能追加してメンテしていく自信がなくなったのでやめて、以下のようになりました。
alias ExUnitAssertMatch, as: Match expected = Match.map(%{ "user" => Match.map(%{ "name" => Match.literal("John"), "age" => Match.literal(28), "orgs" => Match.list_of( Match.map(%{ "name" => Match.binary(), }) ), }), }) Match.assert expected, json
気をつけた点としては
use
させない- Configつかわない
です。マクロやめたのでuse
はまぁしないっしょというのはありつつ、他のパッケージのコードにuse
が入ってると結構コード読みづらくなるなーという実感があるので、自分がつくるものではやらんようにしよーというもの。Configややこしい問題はhttps://elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302とかhttps://elixiroutlaws.com/1でも言われていて、徐々に解決されていきそうだけど避けるようにしている。今回のパッケージはテストのときのためのものなので大して関係ないけど、設定っぽいものは引数で渡せるようにしてます。ex_unit_assert_match
って名前は長いなと思ったけど、https://hex.pm/docs/publish#naming-your-packageに従ってこうしてます。
趣味プロジェクトで使いながら、色々追加してこうと思います。