Current section

Files

Jump to
bc_utils lib logger_filters.ex
Raw

lib/logger_filters.ex

defmodule BCUtils.LoggerFilters do
@moduledoc """
Custom logger filters for reducing noise from commonly verbose libraries.
This module provides pre-configured filters that can be used to reduce
log noise from libraries like Swarm, LibCluster, and others while still
allowing important error messages through.
"""
@doc """
Filter function to reduce Swarm logging noise.
This filter allows only :error level messages from Swarm modules to pass through,
filtering out :info, :debug, and :warning messages that create noise.
## Usage
Add to your logger configuration:
config :logger, :console,
format: "$time [$level] $message\\n",
metadata: :all,
filters: [swarm_filter: {BCUtils.LoggerFilters, :filter_swarm}]
"""
def filter_swarm(%{meta: %{mfa: {module, _function, _arity}}, level: level} = log_event) do
case {is_swarm_module?(module), level} do
{true, :error} -> log_event # Allow Swarm errors through
{true, _} -> :stop # Filter out non-error Swarm messages
{false, _} -> log_event # Allow all non-Swarm messages
end
end
# Handle log events without MFA metadata
def filter_swarm(%{level: _level} = log_event), do: log_event
@doc """
Filter function to reduce LibCluster logging noise.
Similar to filter_swarm/1 but for LibCluster modules.
"""
def filter_libcluster(%{meta: %{mfa: {module, _function, _arity}}, level: level} = log_event) do
case {is_libcluster_module?(module), level} do
{true, :error} -> log_event # Allow LibCluster errors through
{true, _} -> :stop # Filter out non-error LibCluster messages
{false, _} -> log_event # Allow all non-LibCluster messages
end
end
def filter_libcluster(%{level: _level} = log_event), do: log_event
@doc """
Combined filter for both Swarm and LibCluster noise.
## Usage
config :logger, :console,
filters: [verbose_libs: {BCUtils.LoggerFilters, :filter_verbose_libs}]
"""
def filter_verbose_libs(%{meta: %{mfa: {module, _function, _arity}}, level: level} = log_event) do
cond do
is_swarm_module?(module) and level != :error -> :stop
is_libcluster_module?(module) and level != :error -> :stop
true -> log_event
end
end
def filter_verbose_libs(%{level: _level} = log_event), do: log_event
@doc """
Filter that only allows error and warning messages from specified modules.
## Usage
config :logger, :console,
filters: [
errors_only: {BCUtils.LoggerFilters, :errors_and_warnings_only}
]
"""
def errors_and_warnings_only(%{meta: %{mfa: {module, _function, _arity}}, level: level} = log_event) do
case {is_noisy_module?(module), level} do
{true, level} when level in [:error, :warning] -> log_event
{true, _} -> :stop
{false, _} -> log_event
end
end
def errors_and_warnings_only(%{level: _level} = log_event), do: log_event
## Private Functions
# Check if a module is part of Swarm
defp is_swarm_module?(module) when is_atom(module) do
module_string = Atom.to_string(module)
String.starts_with?(module_string, "Elixir.Swarm") or
module == Swarm.Logger # Handle Swarm.Logger specifically
end
defp is_swarm_module?(_), do: false
# Check if a module is part of LibCluster
defp is_libcluster_module?(module) when is_atom(module) do
module_string = Atom.to_string(module)
String.starts_with?(module_string, "Elixir.Cluster") or
String.starts_with?(module_string, "Elixir.LibCluster")
end
defp is_libcluster_module?(_), do: false
# Check if a module is generally known to be noisy
defp is_noisy_module?(module) when is_atom(module) do
is_swarm_module?(module) or
is_libcluster_module?(module) or
is_other_noisy_module?(module)
end
defp is_noisy_module?(_), do: false
# Add other commonly noisy modules here
defp is_other_noisy_module?(module) when is_atom(module) do
module_string = Atom.to_string(module)
# Add patterns for other noisy libraries
String.starts_with?(module_string, "Elixir.Phoenix.PubSub") or
String.starts_with?(module_string, "Elixir.Ranch") or
String.starts_with?(module_string, "Elixir.Cowboy")
end
defp is_other_noisy_module?(_), do: false
end