Skip to content

Commit 5732283

Browse files
authored
Add :formatter to ExUnit.CaptureLog options (#14914)
Mostly modified `:log_capture_on` handler for ExUnit.CaptureServer to respect a `:formatter` option instead `Logger.default_formatter/1`. Updates were made to documentation and tests to reflect this change.
1 parent 46807cf commit 5732283

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ The type system was made possible thanks to a partnership between [CNRS](https:/
4646
* [Kernel] Warn on unused requires
4747
* [Regex] Add `Regex.import/1` to import regexes defined with `/E`
4848

49+
#### ExUnit
50+
51+
* [ExUnit.CaptureLog] Add `:formatter` option for custom log formatting
52+
4953
#### Mix
5054

5155
* [mix test] Add `mix test --dry-run`

lib/ex_unit/lib/ex_unit/capture_log.ex

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,17 @@ defmodule ExUnit.CaptureLog do
4444
@compile {:no_warn_undefined, Logger}
4545

4646
@type capture_log_opts :: [
47-
level: Logger.level() | nil
47+
{:level, Logger.level() | nil}
48+
| {:formatter, {module(), term()} | nil}
4849
]
4950

5051
@doc """
5152
Captures Logger messages generated when evaluating `fun`.
5253
5354
Returns the binary which is the captured output. The captured log
54-
messages will be formatted using `Logger.default_formatter/1`. Any
55-
option, besides the `:level`, will be forwarded as an override to
56-
the default formatter.
55+
messages will be formatted using `Logger.default_formatter/1` by
56+
default. Any option, besides `:level` or `formatter`, will be
57+
forwarded as an override to the default formatter.
5758
5859
This function mutes the default logger handler and captures any log
5960
messages sent to Logger from the calling processes. It is possible
@@ -75,6 +76,11 @@ defmodule ExUnit.CaptureLog do
7576
configured in this function, no message will be captured.
7677
The behaviour is undetermined if async tests change Logger level.
7778
79+
It is possible to use an alternative log formatter with `:formatter`,
80+
which must be provided as `{module, config}`. If `:formatter` is not
81+
provided, the formatter configuration from `Logger.default_formatter/1`
82+
will be used.
83+
7884
To get the result of the evaluation along with the captured log,
7985
use `with_log/2`.
8086
"""

lib/ex_unit/lib/ex_unit/capture_server.ex

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ defmodule ExUnit.CaptureServer do
7575
refs = Map.put(config.log_captures, ref, true)
7676

7777
{level, opts} = Keyword.pop(opts, :level)
78-
{formatter_mod, formatter_config} = Logger.default_formatter(opts)
78+
79+
{formatter_mod, formatter_config} =
80+
Keyword.get_lazy(opts, :formatter, fn -> Logger.default_formatter(opts) end)
81+
7982
true = :ets.insert(@ets, {ref, string_io, level || :all, formatter_mod, formatter_config})
8083

8184
if map_size(refs) == 1 do

lib/ex_unit/test/ex_unit/capture_log_test.exs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,44 @@ defmodule ExUnit.CaptureLogTest do
143143
end
144144
end
145145

146+
defmodule CustomFormatter do
147+
def new do
148+
{_, opts} =
149+
Logger.Formatter.new(
150+
format: "$metadata| $message",
151+
metadata: [:id],
152+
colors: [enabled: false]
153+
)
154+
155+
{__MODULE__, opts}
156+
end
157+
158+
def format(event, config) do
159+
event
160+
|> wrap()
161+
|> Logger.Formatter.format(config)
162+
end
163+
164+
defp wrap(event) do
165+
msg =
166+
event
167+
|> Logger.Formatter.format_event(:infinity)
168+
|> to_string()
169+
170+
%{event | msg: {:string, ["[CUSTOM]", msg, "[/CUSTOM]"]}}
171+
end
172+
end
173+
174+
test "uses the formatter from the `:formatter` option" do
175+
log =
176+
capture_log([formatter: CustomFormatter.new()], fn ->
177+
Logger.info("hello", id: 123)
178+
2 + 2
179+
end)
180+
181+
assert log == "id=123 | [CUSTOM]hello[/CUSTOM]"
182+
end
183+
146184
defp wait_capture_removal() do
147185
if ExUnit.CaptureServer in Enum.map(:logger.get_handler_config(), & &1.id) do
148186
Process.sleep(20)

0 commit comments

Comments
 (0)