Very excited about this. Thanks for all your work!
I’m curious what approach you have in mind for structured logging. So far I’ve been doing it this way:
- At the call site, pass structured data via metadata:
Logger.log(level, "Processing request", method: conn.method, path: conn.request_path, ... )
- Define a custom formatter which takes all metadata:
config :logger, :file_log, path: "app.log", level: :info, format: {MyApp.Logger, :format}, metadata: :all
- In the formatter, generate JSON, roughly like:
wheredef format(level, message, timestamp, metadata) do %{ "timestamp" => format_timestamp(timestamp), "level" => level, "message" => IO.iodata_to_binary(message) } |> add_metadata(metadata) |> Jason.encode!() end
add_metadata
reads each key/value pair frommetadata
, converts the value to a printable representation, and adds it to the event map, similar to Honeybadger.JSON.
It works, but it’s not ideal - we had to reimplement functionality from the default formatter, for instance formatting time or converting PIDs to strings. OTP reports also can’t be structured, because they’re a string blob by the time they reach the formatter (not a huge deal though).
Could we achieve JSON logging more easily with the new backend, or with future development?