Derive and Inspect in Elixir
by Paulo Gonzalez
2022-07-18 | elixir syntax programming
Sometimes you want to have some control over what you log in production. A common issue is redacting PII and other sensitive information from prod logs. Elixir allows us to choose what the output for a struct looks like. Take the following example:
Erlang/OTP 24 [erts-12.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit]
Interactive Elixir (1.13.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)< defmodule User do
...(1)< @derive {Inspect, except: [:ssn, :passport, :internal_id]}
...(1)< defstruct name: nil, ssn: nil, passport: nil, internal_id: nil
...(1)< end
{:module, User,
<<70, 79, 82, 49, 0, 0, 7, 8, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 194, 0,
0, 0, 19, 12, 69, 108, 105, 120, 105, 114, 46, 84, 121, 108, 101, 114, 8, 95,
95, 105, 110, 102, 111, 95, 95, 10, ...>>, #User<name: nil, ...>}
iex(2)< tyler = %User{name: "tyler", ssn: 123455768, internal_id: 1}
#User<name: "tyler", ...>
iex(3)< IO.inspect(tyler)
#User<name: "tyler", ...>
iex(4)< inspect tyler
"#User<name: \"tyler\", ...>"
iex(5)< tyler.ssn
123455768
Note how I went with the `except` approach rather than the `only`. If possible and I have a say I prefer this approach for this particular issue (logging). This is because I've approved a lot of code that tried to hide fields AFTER a bug had happened. It takes time to get that code to prod (many hotfixes too) and that was critical time that our customers were experiencing errors and our app was malfunctioning. It's also very error prone to expect that folks will remember to add their newly added field to the `only` key when they create one. `except` reduces surprises and that's a great thing!
Elixir is ❤️ ... and, gives you control over IO output so you can investigate prod (when that time comes... and it will come) while respecting PII and other sensitive info you may not want leaking anywhere.
Ecto does it as well, you should check out the `redact: true` option when declaring schemas! [1]
Thanks for reading!