Skip to content

Commit 69b4748

Browse files
author
José Valim
committed
Merge pull request #2609 from fishcakez/logger_ansi_console
Add ANSI support to console logger
2 parents 284e75d + 212b204 commit 69b4748

File tree

3 files changed

+102
-8
lines changed

3 files changed

+102
-8
lines changed

lib/logger/lib/logger.ex

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,30 @@ defmodule Logger do
139139
* `:metadata` - the metadata to be printed by `$metadata`.
140140
Defaults to an empty list (no metadata)
141141
142+
* `:colors` - a keyword list of coloring options.
143+
144+
The supported keys in the `:colors` keyword list are:
145+
146+
* `:enabled` - boolean value that allows for switching the
147+
coloring on and off. Defaults to: `false`
148+
149+
* `:debug` - color for debug messages. Defaults to: `:magenta`
150+
151+
* `:info` - color for info messages. Defaults to: `:normal`
152+
153+
* `:warn` - color for warn messages. Defaults to: `:yellow`
154+
155+
* `:error` - color for error messages. Defaults to: `:red`
156+
157+
See the `IO.ANSI` module for a list of colors and attributes.
158+
142159
Here is an example on how to configure the `:console` in a
143160
`config/config.exs` file:
144161
145162
config :logger, :console,
146163
format: "$date $time [$level] $metadata$message\n",
147-
metadata: [:user_id]
164+
metadata: [:user_id],
165+
colors: [enabled: true]
148166
149167
You can read more about formatting in `Logger.Formatter`.
150168

lib/logger/lib/logger/backends/console.ex

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ defmodule Logger.Backends.Console do
3030
## Helpers
3131

3232
defp configure(options) do
33-
console = Keyword.merge(Application.get_env(:logger, :console, []), options)
33+
env = Application.get_env(:logger, :console, [])
34+
console = configure_merge(env, options)
3435
Application.put_env(:logger, :console, console)
3536

3637
format = console
@@ -39,11 +40,41 @@ defmodule Logger.Backends.Console do
3940

4041
level = Keyword.get(console, :level)
4142
metadata = Keyword.get(console, :metadata, [])
42-
%{format: format, metadata: metadata, level: level}
43+
colors = configure_colors(console)
44+
%{format: format, metadata: metadata, level: level, colors: colors}
4345
end
4446

45-
defp log_event(level, msg, ts, md, %{format: format, metadata: metadata}) do
46-
:io.put_chars :user,
47-
Logger.Formatter.format(format, level, msg, ts, Dict.take(md, metadata))
47+
defp configure_merge(env, options) do
48+
env_colors = Keyword.get(env, :colors, [])
49+
opts_colors = Keyword.get(options, :colors, [])
50+
colors = Keyword.merge(env_colors, opts_colors)
51+
52+
Keyword.merge(env, options)
53+
|> Keyword.put(:colors, colors)
54+
end
55+
56+
defp configure_colors(console) do
57+
colors = Keyword.get(console, :colors, [])
58+
debug = Keyword.get(colors, :debug, :magenta)
59+
info = Keyword.get(colors, :info, :normal)
60+
warn = Keyword.get(colors, :warn, :yellow)
61+
error = Keyword.get(colors, :error, :red)
62+
enabled = Keyword.get(colors, :enabled, false)
63+
%{debug: debug, info: info, warn: warn, error: error, enabled: enabled}
64+
end
65+
66+
defp log_event(level, msg, ts, md, %{colors: colors} = state) do
67+
ansidata = format_event(level, msg, ts, md, state)
68+
chardata = color_event(level, ansidata, colors)
69+
:io.put_chars(:user, chardata)
4870
end
71+
72+
defp format_event(level, msg, ts, md, %{format: format, metadata: metadata}) do
73+
Logger.Formatter.format(format, level, msg, ts, Dict.take(md, metadata))
74+
end
75+
76+
defp color_event(level, data, %{enabled: enabled} = colors) do
77+
IO.ANSI.format([Map.fetch!(colors, level) | data], enabled)
78+
end
79+
4980
end

lib/logger/test/logger/backends/console_test.exs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ defmodule Logger.Backends.ConsoleTest do
44

55
setup do
66
on_exit fn ->
7-
:ok = Logger.configure_backend(:console, [format: nil, level: nil, metadata: []])
7+
:ok = Logger.configure_backend(:console,
8+
[format: nil, level: nil, metadata: [], colors: [enabled: false]])
89
end
910
end
1011

@@ -49,4 +50,48 @@ defmodule Logger.Backends.ConsoleTest do
4950
Logger.debug("hello")
5051
end) == ""
5152
end
52-
end
53+
54+
test "can configure colors" do
55+
Logger.configure_backend(:console, [format: "$message", colors: [enabled: true]])
56+
57+
assert capture_log(fn ->
58+
Logger.debug("hello")
59+
end) == IO.ANSI.magenta() <> "hello" <> IO.ANSI.reset()
60+
61+
Logger.configure_backend(:console, [colors: [debug: :cyan]])
62+
63+
assert capture_log(fn ->
64+
Logger.debug("hello")
65+
end) == IO.ANSI.cyan() <> "hello" <> IO.ANSI.reset()
66+
67+
assert capture_log(fn ->
68+
Logger.info("hello")
69+
end) == IO.ANSI.normal() <> "hello" <> IO.ANSI.reset()
70+
71+
Logger.configure_backend(:console, [colors: [info: :cyan]])
72+
73+
assert capture_log(fn ->
74+
Logger.info("hello")
75+
end) == IO.ANSI.cyan() <> "hello" <> IO.ANSI.reset()
76+
77+
assert capture_log(fn ->
78+
Logger.warn("hello")
79+
end) == IO.ANSI.yellow() <> "hello" <> IO.ANSI.reset()
80+
81+
Logger.configure_backend(:console, [colors: [warn: :cyan]])
82+
83+
assert capture_log(fn ->
84+
Logger.warn("hello")
85+
end) == IO.ANSI.cyan() <> "hello" <> IO.ANSI.reset()
86+
87+
assert capture_log(fn ->
88+
Logger.error("hello")
89+
end) == IO.ANSI.red() <> "hello" <> IO.ANSI.reset()
90+
91+
Logger.configure_backend(:console, [colors: [error: :cyan]])
92+
93+
assert capture_log(fn ->
94+
Logger.error("hello")
95+
end) == IO.ANSI.cyan() <> "hello" <> IO.ANSI.reset()
96+
end
97+
end

0 commit comments

Comments
 (0)