Logger messages must start with "#{__MODULE__}: " and wrap every interpolated
value in inspect/1.
A bare #{value} crashes at runtime whenever the value has no String.Chars
implementation — a tuple, a map, a pid. inspect/1 renders anything. The
__MODULE__ prefix attributes every log line to the module that wrote it.
# BAD — crashes when reason is a tuple like {:error, :timeout}
Logger.error("failed: #{reason}")
# BAD — safe, but the log line has no source module
Logger.error("failed: #{inspect(reason)}")
# GOOD
Logger.error("#{__MODULE__}: request failed, reason: #{inspect(reason)}")The message must literally start with the __MODULE__ interpolation — it has
to be the very first segment of the string. A literal before it, as in
"[worker] #{__MODULE__}: started", is flagged.
Both the direct string form and the lazy zero-arity function form are checked:
Logger.debug(fn -> "#{__MODULE__}: state: #{inspect(state)}" end)Messages the check cannot see into — a variable, a module attribute, a function call, a function body that is not a string literal — are skipped, since their content cannot be verified statically.
A renamed alias (alias Logger, as: Log) is not resolved, and import Logger
followed by a bare info/1 is not detected.