Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add <formatter>.new/1 #145

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ Then, enable the formatter in your `config.exs`:

```elixir
config :logger, :default_handler,
formatter: {LoggerJSON.Formatters.Basic, []}
formatter: LoggerJSON.Formatters.Basic.new(metadata: [:request_id])
```

or during runtime (eg. in your `application.ex`):

```elixir
:logger.update_handler_config(:default, :formatter, {Basic, []})
ruslandoga marked this conversation as resolved.
Show resolved Hide resolved
formatter = LoggerJSON.Formatters.Basic.new(metadata: :all)
:logger.update_handler_config(:default, :formatter, formatter)
```

You might also want to format the log messages when migrations are running:
Expand All @@ -65,13 +66,14 @@ For example in `config.exs`:

```elixir
config :logger, :default_handler,
formatter: {LoggerJSON.Formatters.GoogleCloud, metadata: :all, project_id: "logger-101"}
formatter: LoggerJSON.Formatters.GoogleCloud.new(metadata: :all, project_id: "logger-101")
```

or during runtime:

```elixir
:logger.update_handler_config(:default, :formatter, {LoggerJSON.Formatters.Basic, %{metadata: {:all_except, [:conn]}}})
formatter = LoggerJSON.Formatters.Basic.new(%{metadata: {:all_except, [:conn]}})
:logger.update_handler_config(:default, :formatter, formatter)
```

## Docs
Expand Down
14 changes: 9 additions & 5 deletions lib/logger_json.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,25 @@ defmodule LoggerJSON do
Then, enable the formatter in your `config.exs`:

config :logger, :default_handler,
formatter: {LoggerJSON.Formatters.Basic, []}
formatter: LoggerJSON.Formatters.Basic.new(metadata: :all)

or during runtime (eg. in your `application.ex`):

:logger.update_handler_config(:default, :formatter, {Basic, %{}})
formatter = LoggerJSON.Formatters.Basic.new(metadata: :all)
:logger.update_handler_config(:default, :formatter, formatter)

## Configuration

Configuration can be set using 2nd element of the tuple of the `:formatter` option in `Logger` configuration.
For example in `config.exs`:

config :logger, :default_handler,
formatter: {LoggerJSON.Formatters.GoogleCloud, metadata: :all, project_id: "logger-101"}
formatter: LoggerJSON.Formatters.GoogleCloud.new(metadata: :all, project_id: "logger-101")

or during runtime:

:logger.update_handler_config(:default, :formatter, {Basic, %{metadata: {:all_except, [:conn]}}})
formatter = LoggerJSON.Formatters.Basic.new(metadata: {:all_except, [:conn]})
:logger.update_handler_config(:default, :formatter, formatter)

### Shared Options

Expand Down Expand Up @@ -81,6 +83,8 @@ defmodule LoggerJSON do
Formatters may encode the well-known metadata differently and support additional metadata keys, see the documentation
of the formatter for more details.
"""

# TODO: replace with `Logger.levels()` once LoggerJSON starts depending on Elixir 1.16+
@log_levels [:error, :info, :debug, :emergency, :alert, :critical, :warning, :notice]
@log_level_strings Enum.map(@log_levels, &to_string/1)

Expand Down Expand Up @@ -111,6 +115,6 @@ defmodule LoggerJSON do
do: Logger.configure(level: level)

def configure_log_level!(level) do
raise ArgumentError, "Log level should be one of 'debug', 'info', 'warn', 'error' values, got: #{inspect(level)}"
raise ArgumentError, "Log level should be one of #{inspect(@log_levels)} values, got: #{inspect(level)}"
end
end
3 changes: 2 additions & 1 deletion lib/logger_json/formatter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ defmodule LoggerJSON.Formatter do
| {atom(), term()}
]

@callback format(event :: :logger.log_event(), opts :: opts()) :: iodata()
@callback new(opts) :: {module, :logger.formatter_config()}
@callback format(:logger.log_event(), :logger.formatter_config()) :: iodata()
end
12 changes: 11 additions & 1 deletion lib/logger_json/formatters/basic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,22 @@ defmodule LoggerJSON.Formatters.Basic do
conn]a

@impl true
def format(%{level: level, meta: meta, msg: msg}, opts) do
def new(opts) do
opts = Keyword.new(opts)
encoder_opts = Keyword.get(opts, :encoder_opts, [])
metadata_keys_or_selector = Keyword.get(opts, :metadata, [])
metadata_selector = update_metadata_selector(metadata_keys_or_selector, @processed_metadata_keys)
redactors = Keyword.get(opts, :redactors, [])
{__MODULE__, %{encoder_opts: encoder_opts, metadata: metadata_selector, redactors: redactors}}
end

@impl true
def format(%{level: level, meta: meta, msg: msg}, config) do
%{
encoder_opts: encoder_opts,
metadata: metadata_selector,
redactors: redactors
} = config

message =
format_message(msg, meta, %{
Expand Down
14 changes: 12 additions & 2 deletions lib/logger_json/formatters/datadog.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,24 @@ defmodule LoggerJSON.Formatters.Datadog do
@processed_metadata_keys ~w[pid file line mfa conn]a

@impl true
def format(%{level: level, meta: meta, msg: msg}, opts) do
def new(opts) do
opts = Keyword.new(opts)
encoder_opts = Keyword.get(opts, :encoder_opts, [])
redactors = Keyword.get(opts, :redactors, [])
hostname = Keyword.get(opts, :hostname, :system)

metadata_keys_or_selector = Keyword.get(opts, :metadata, [])
metadata_selector = update_metadata_selector(metadata_keys_or_selector, @processed_metadata_keys)
{__MODULE__, %{encoder_opts: encoder_opts, metadata: metadata_selector, redactors: redactors, hostname: hostname}}
end

@impl true
def format(%{level: level, meta: meta, msg: msg}, config) do
%{
encoder_opts: encoder_opts,
metadata: metadata_selector,
redactors: redactors,
hostname: hostname
} = config

message =
format_message(msg, meta, %{
Expand Down
14 changes: 12 additions & 2 deletions lib/logger_json/formatters/elastic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,23 @@ defmodule LoggerJSON.Formatters.Elastic do
otel_trace_id trace_id
conn]a

@impl LoggerJSON.Formatter
def format(%{level: level, meta: meta, msg: msg}, opts) do
@impl true
def new(opts) do
opts = Keyword.new(opts)
encoder_opts = Keyword.get(opts, :encoder_opts, [])
metadata_keys_or_selector = Keyword.get(opts, :metadata, [])
metadata_selector = update_metadata_selector(metadata_keys_or_selector, @processed_metadata_keys)
redactors = Keyword.get(opts, :redactors, [])
{__MODULE__, %{encoder_opts: encoder_opts, metadata: metadata_selector, redactors: redactors}}
end

@impl LoggerJSON.Formatter
def format(%{level: level, meta: meta, msg: msg}, config) do
%{
encoder_opts: encoder_opts,
metadata: metadata_selector,
redactors: redactors
} = config

message =
format_message(msg, meta, %{
Expand Down
22 changes: 21 additions & 1 deletion lib/logger_json/formatters/google_cloud.ex
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ defmodule LoggerJSON.Formatters.GoogleCloud do
conn]a

@impl true
def format(%{level: level, meta: meta, msg: msg}, opts) do
def new(opts) do
opts = Keyword.new(opts)
encoder_opts = Keyword.get(opts, :encoder_opts, [])
redactors = Keyword.get(opts, :redactors, [])
Expand All @@ -108,6 +108,26 @@ defmodule LoggerJSON.Formatters.GoogleCloud do
metadata_keys_or_selector = Keyword.get(opts, :metadata, [])
metadata_selector = update_metadata_selector(metadata_keys_or_selector, @processed_metadata_keys)

{__MODULE__,
%{
encoder_opts: encoder_opts,
redactors: redactors,
service_context: service_context,
project_id: project_id,
metadata: metadata_selector
}}
end

@impl true
def format(%{level: level, meta: meta, msg: msg}, config) do
%{
encoder_opts: encoder_opts,
redactors: redactors,
service_context: service_context,
project_id: project_id,
metadata: metadata_selector
} = config

message =
format_message(msg, meta, %{
binary: &format_binary_message/1,
Expand Down
9 changes: 6 additions & 3 deletions lib/logger_json/redactors/redact_keys.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ defmodule LoggerJSON.Redactors.RedactKeys do
It takes list of keys to redact as an argument, eg.:
```elixir
config :logger, :default_handler,
formatter: {LoggerJSON.Formatters.Basic, redactors: [
{LoggerJSON.Redactors.RedactKeys, ["password"]}
]}
formatter:
LoggerJSON.Formatters.Basic.new(
redactors: [
{LoggerJSON.Redactors.RedactKeys, ["password"]}
]
)
```

Keep in mind that the key will be converted to binary before sending it to the redactor.
Expand Down
2 changes: 1 addition & 1 deletion test/logger_json/ecto_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule LoggerJSON.EctoTest do
require Logger

setup do
formatter = {LoggerJSON.Formatters.Basic, metadata: :all}
formatter = LoggerJSON.Formatters.Basic.new(metadata: :all)
:logger.update_handler_config(:default, :formatter, formatter)
end

Expand Down
12 changes: 6 additions & 6 deletions test/logger_json/formatters/basic_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule LoggerJSON.Formatters.BasicTest do
require Logger

setup do
formatter = {Basic, metadata: :all}
formatter = Basic.new(metadata: :all)
:logger.update_handler_config(:default, :formatter, formatter)
end

Expand Down Expand Up @@ -158,7 +158,7 @@ defmodule LoggerJSON.Formatters.BasicTest do
}
} = log

formatter = {Basic, metadata: {:all_except, [:struct]}}
formatter = Basic.new(metadata: {:all_except, [:struct]})
:logger.update_handler_config(:default, :formatter, formatter)

log =
Expand All @@ -181,7 +181,7 @@ defmodule LoggerJSON.Formatters.BasicTest do
}
} = log

formatter = {Basic, metadata: [:node]}
formatter = Basic.new(metadata: [:node])
:logger.update_handler_config(:default, :formatter, formatter)

log =
Expand Down Expand Up @@ -243,7 +243,7 @@ defmodule LoggerJSON.Formatters.BasicTest do
end

test "passing options to encoder" do
formatter = {Basic, encoder_opts: [pretty: true]}
formatter = Basic.new(encoder_opts: [pretty: true])
:logger.update_handler_config(:default, :formatter, formatter)

assert capture_log(fn ->
Expand All @@ -254,7 +254,7 @@ defmodule LoggerJSON.Formatters.BasicTest do

test "reads metadata from the given application env" do
Application.put_env(:logger_json, :test_basic_metadata_key, [:foo])
formatter = {Basic, metadata: {:from_application_env, {:logger_json, :test_basic_metadata_key}}}
formatter = Basic.new(metadata: {:from_application_env, {:logger_json, :test_basic_metadata_key}})
:logger.update_handler_config(:default, :formatter, formatter)

Logger.metadata(foo: "foo")
Expand All @@ -274,7 +274,7 @@ defmodule LoggerJSON.Formatters.BasicTest do

test "reads metadata from the given application env at given path" do
Application.put_env(:logger_json, :test_basic_metadata_key, metadata: [:foo])
formatter = {Basic, metadata: {:from_application_env, {:logger_json, :test_basic_metadata_key}, [:metadata]}}
formatter = Basic.new(metadata: {:from_application_env, {:logger_json, :test_basic_metadata_key}, [:metadata]})
:logger.update_handler_config(:default, :formatter, formatter)

Logger.metadata(foo: "foo")
Expand Down
12 changes: 6 additions & 6 deletions test/logger_json/formatters/datadog_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule LoggerJSON.Formatters.DatadogTest do
require Logger

setup do
formatter = {Datadog, metadata: :all}
formatter = Datadog.new(metadata: :all)
:logger.update_handler_config(:default, :formatter, formatter)
end

Expand Down Expand Up @@ -91,7 +91,7 @@ defmodule LoggerJSON.Formatters.DatadogTest do
assert log["syslog"]["hostname"] == :inet.gethostname() |> elem(1) |> IO.chardata_to_string()

# static value
formatter = {Datadog, hostname: "foo.bar1"}
formatter = Datadog.new(hostname: "foo.bar1")
:logger.update_handler_config(:default, :formatter, formatter)

log =
Expand All @@ -103,7 +103,7 @@ defmodule LoggerJSON.Formatters.DatadogTest do
assert log["syslog"]["hostname"] == "foo.bar1"

# unset value
formatter = {Datadog, hostname: :unset}
formatter = Datadog.new(hostname: :unset)
:logger.update_handler_config(:default, :formatter, formatter)

log =
Expand Down Expand Up @@ -456,7 +456,7 @@ defmodule LoggerJSON.Formatters.DatadogTest do
end

test "passing options to encoder" do
formatter = {Datadog, encoder_opts: [pretty: true]}
formatter = Datadog.new(encoder_opts: [pretty: true])
:logger.update_handler_config(:default, :formatter, formatter)

assert capture_log(fn ->
Expand All @@ -467,7 +467,7 @@ defmodule LoggerJSON.Formatters.DatadogTest do

test "reads metadata from the given application env" do
Application.put_env(:logger_json, :test_datadog_metadata_key, [:foo])
formatter = {Datadog, metadata: {:from_application_env, {:logger_json, :test_datadog_metadata_key}}}
formatter = Datadog.new(metadata: {:from_application_env, {:logger_json, :test_datadog_metadata_key}})
:logger.update_handler_config(:default, :formatter, formatter)

Logger.metadata(foo: "foo")
Expand All @@ -485,7 +485,7 @@ defmodule LoggerJSON.Formatters.DatadogTest do

test "reads metadata from the given application env at given path" do
Application.put_env(:logger_json, :test_datadog_metadata_key, metadata: [:foo])
formatter = {Datadog, metadata: {:from_application_env, {:logger_json, :test_datadog_metadata_key}, [:metadata]}}
formatter = Datadog.new(metadata: {:from_application_env, {:logger_json, :test_datadog_metadata_key}, [:metadata]})
:logger.update_handler_config(:default, :formatter, formatter)

Logger.metadata(foo: "foo")
Expand Down
8 changes: 4 additions & 4 deletions test/logger_json/formatters/elastic_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule LoggerJSON.Formatters.ElasticTest do
require Logger

setup do
formatter = {Elastic, metadata: :all}
formatter = Elastic.new(metadata: :all)
:logger.update_handler_config(:default, :formatter, formatter)
end

Expand Down Expand Up @@ -490,7 +490,7 @@ defmodule LoggerJSON.Formatters.ElasticTest do
end

test "passing options to encoder" do
formatter = {Elastic, encoder_opts: [pretty: true]}
formatter = Elastic.new(encoder_opts: [pretty: true])
:logger.update_handler_config(:default, :formatter, formatter)

assert capture_log(fn ->
Expand All @@ -501,7 +501,7 @@ defmodule LoggerJSON.Formatters.ElasticTest do

test "reads metadata from the given application env" do
Application.put_env(:logger_json, :test_elastic_metadata_key, [:foo])
formatter = {Elastic, metadata: {:from_application_env, {:logger_json, :test_elastic_metadata_key}}}
formatter = Elastic.new(metadata: {:from_application_env, {:logger_json, :test_elastic_metadata_key}})
:logger.update_handler_config(:default, :formatter, formatter)

Logger.metadata(foo: "foo")
Expand All @@ -519,7 +519,7 @@ defmodule LoggerJSON.Formatters.ElasticTest do

test "reads metadata from the given application env at given path" do
Application.put_env(:logger_json, :test_elastic_metadata_key, metadata: [:foo])
formatter = {Elastic, metadata: {:from_application_env, {:logger_json, :test_elastic_metadata_key}, [:metadata]}}
formatter = Elastic.new(metadata: {:from_application_env, {:logger_json, :test_elastic_metadata_key}, [:metadata]})
:logger.update_handler_config(:default, :formatter, formatter)

Logger.metadata(foo: "foo")
Expand Down
Loading