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:

Derive and Inspect in Elixir - using `@derive` [0]
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!

Conclusion

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]

Links

Thanks for reading!