diff --git a/lib/ex_json_logger.ex b/lib/ex_json_logger.ex index a5981f5..a3ccad6 100644 --- a/lib/ex_json_logger.ex +++ b/lib/ex_json_logger.ex @@ -47,7 +47,9 @@ defmodule ExJsonLogger do | metadata(metadata) ]) rescue - _e -> + e -> + IO.inspect(e) + encode([ {"level", "error"}, {"time", format_timestamp(timestamp)}, @@ -82,6 +84,10 @@ defmodule ExJsonLogger do defp format_metadata({drop, _}) when drop in [:msg, :time, :level, :report_cb, :gl], do: nil + defp format_metadata({_, nil} = kv), do: kv + defp format_metadata({_, string} = kv) when is_binary(string), do: kv + defp format_metadata({_, number} = kv) when is_number(number), do: kv + defp format_metadata({key, pid}) when is_pid(pid) do {key, unsafe_fragment(["#PID", :erlang.pid_to_list(pid)])} end @@ -113,5 +119,13 @@ defmodule ExJsonLogger do {list_key, List.to_string(list)} end - defp format_metadata({_k, _v} = other), do: other + defp format_metadata({k, %_struct{} = v} = kv) do + cond do + impl = String.Chars.impl_for(v) -> {k, impl.to_string(v)} + Jason.Encoder.impl_for(v) != Jason.Encoder.Any -> kv + true -> {k, inspect(v)} + end + end + + defp format_metadata(other), do: other end diff --git a/mix.exs b/mix.exs index dcfc774..ee03dcb 100644 --- a/mix.exs +++ b/mix.exs @@ -10,6 +10,7 @@ defmodule ExJsonLogger.Mixfile do name: "ex_json_logger", version: @version, elixir: ">= 1.14.0", + elixirc_paths: elixirc_paths(Mix.env()), elixirc_options: [warnings_as_errors: true], build_embedded: Mix.env() == :prod, start_permanent: Mix.env() == :prod, @@ -34,6 +35,9 @@ defmodule ExJsonLogger.Mixfile do [extra_applications: [:logger]] end + defp elixirc_paths(:test), do: ["lib", "test/support"] + defp elixirc_paths(_env), do: ["lib"] + defp deps do [ {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, diff --git a/test/ex_json_logger_test.exs b/test/ex_json_logger_test.exs index 791a898..35d33d5 100644 --- a/test/ex_json_logger_test.exs +++ b/test/ex_json_logger_test.exs @@ -114,13 +114,7 @@ defmodule ExJsonLoggerTest do Logger.debug("this is a message", level: :error, msg: "this is metadata") end) - assert %{ - "level" => "debug", - "msg" => "this is a message", - "time" => time - } = Jason.decode!(message) - - refute String.starts_with?(time, "1970") + assert %{"level" => "debug", "msg" => "this is a message"} = Jason.decode!(message) end test "metadata can override :time" do @@ -134,4 +128,39 @@ defmodule ExJsonLoggerTest do assert %{"time" => "1970" <> _} = Jason.decode!(message) end end + + describe "protocols" do + test "String.Chars" do + Logger.configure_backend(:console, metadata: :all) + + message = + capture_log(fn -> + Logger.debug("this is a message", some_key: %StringCharsValue{message: "hello"}) + end) + + assert %{"some_key" => "StringCharsValue says: hello"} = Jason.decode!(message) + end + + test "Jason.Encoder" do + Logger.configure_backend(:console, metadata: :all) + + message = + capture_log(fn -> + Logger.debug("this is a message", some_key: %JasonEncoderValue{message: "hello", secret: "password"}) + end) + + assert %{"some_key" => %{"message" => "hello"}} = Jason.decode!(message) + end + + test "Inspect" do + Logger.configure_backend(:console, metadata: :all) + + message = + capture_log(fn -> + Logger.debug("this is a message", some_key: %InspectValue{message: "hello", secret: "password"}) + end) + + assert %{"some_key" => "#InspectValue"} = Jason.decode!(message) + end + end end diff --git a/test/support/protocols.ex b/test/support/protocols.ex new file mode 100644 index 0000000..6235032 --- /dev/null +++ b/test/support/protocols.ex @@ -0,0 +1,19 @@ +defmodule StringCharsValue do + defstruct [:message] + + defimpl String.Chars do + def to_string(%{message: message}) do + "StringCharsValue says: " <> message + end + end +end + +defmodule JasonEncoderValue do + @derive {Jason.Encoder, only: [:message]} + defstruct [:message, :secret] +end + +defmodule InspectValue do + @derive {Inspect, only: [:message]} + defstruct [:message, :secret] +end