Packages
file_only_logger
0.2.3
0.2.70
0.2.69
0.2.65
0.2.64
0.2.63
0.2.62
0.2.61
0.2.60
0.2.59
0.2.58
0.2.57
0.2.56
0.2.55
0.2.54
0.2.53
0.2.52
0.2.51
0.2.50
0.2.49
0.2.48
0.2.47
0.2.45
0.2.44
0.2.43
0.2.42
0.2.41
0.2.40
0.2.39
0.2.38
0.2.37
0.2.36
0.2.35
0.2.34
0.2.33
0.2.31
0.2.30
0.2.29
0.2.28
0.2.27
0.2.26
0.2.25
0.2.24
0.2.23
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
0.2.17
0.2.16
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.1.58
0.1.57
0.1.55
0.1.54
0.1.53
0.1.52
0.1.51
0.1.50
0.1.49
0.1.47
0.1.46
0.1.45
0.1.44
0.1.43
0.1.42
0.1.41
0.1.40
0.1.39
0.1.38
0.1.37
0.1.36
0.1.35
0.1.34
0.1.33
0.1.32
0.1.31
0.1.30
0.1.28
0.1.27
0.1.26
0.1.25
0.1.24
0.1.23
0.1.22
0.1.21
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.0
A simple logger that writes messages to log files only (not to the console).
Current section
Files
Jump to
Current section
Files
lib/file/only/logger/proxy.ex
defmodule File.Only.Logger.Proxy do
@moduledoc """
Implements logging messages to files only (not to the console).
"""
use PersistConfig
require Logger
@levels get_env(:levels)
@lib Mix.Project.config()[:app]
@line_length get_env(:line_length)
@padding get_env(:padding)
@typedoc "Message to be logged"
@type message :: String.t() | iodata | fun | keyword | map
@doc """
Returns `true` if `value` is a positive integer, otherwise `false`.
"""
defguard is_pos_integer(value) when is_integer(value) and value > 0
@doc """
Writes `message` to the configured log file of logging level `level`.
## Examples
iex> alias File.Only.Logger.Proxy
iex> Proxy.log(:debug, "*** String message ***")
:ok
iex> alias File.Only.Logger.Proxy
iex> Proxy.log(:debug, ['*** Improper ', 'List ' | 'Message ***'])
:ok
iex> alias File.Only.Logger.Proxy
iex> Proxy.log(:debug, fn -> "*** Function message ***" end)
:ok
iex> alias File.Only.Logger.Proxy
iex> Proxy.log(:debug, %{'first' => 'Map', 'last' => 'Message'})
:ok
iex> alias File.Only.Logger.Proxy
iex> Proxy.log(:debug, first: 'Keyword', last: 'Message')
:ok
"""
@spec log(Logger.level(), message) :: :ok
def log(level, message) when level in @levels do
Logger.configure(level: level())
Logger.configure_backend(:console, level: :none)
:ok = Logger.log(level, message)
Logger.configure_backend(:console, level: Logger.level())
:ok
end
@doc """
Returns string "<module>.<function>/<arity>" e.g. "My.Math.sqrt/1" from the
given `env` (`Macro.Env`).
## Examples
iex> defmodule My.Math do
iex> alias File.Only.Logger.Proxy
iex> def sqrt(_number) do
iex> Proxy.fun(__ENV__)
iex> end
iex> end
iex> My.Math.sqrt(9)
"File.Only.Logger.ProxyTest.My.Math.sqrt/1"
"""
@spec fun(Macro.Env.t()) :: String.t()
def fun(%Macro.Env{function: {name, arity}, module: module} = _env) do
if to_string(name) |> String.contains?(" "),
do: "#{inspect(module)}.'#{name}'/#{arity}",
else: "#{inspect(module)}.#{name}/#{arity}"
end
def fun(%Macro.Env{function: nil}), do: "'not inside a function'"
@doc ~S'''
Will prefix `string` with "\n<padding>" if `string` is longer than
`<line_length>` - `offset` where `<padding>` and `<line_length>` are
respectively the `:padding` and `:line_length` options.
## Options
* `:line_length` (positive integer) - the preferred line length of messages
sent to the log files. Defaults to 80.
* `:padding` (string) - Filler inserted after the line break. Defaults to
"\s\s".
## Examples
iex> alias File.Only.Logger.Proxy
iex> supercal = 'supercalifragilisticexpialidocious'
iex> """
...> • Feeling: #{inspect(supercal) |> Proxy.maybe_break(11)}
...> """
"""
• Feeling: 'supercalifragilisticexpialidocious'
"""
iex> alias File.Only.Logger.Proxy
iex> supercal = "supercalifragilisticexpialidocious"
iex> supercal! = "#{supercal}ly #{supercal}!"
iex> """
...> • Feeling: #{String.capitalize(supercal!) |> Proxy.maybe_break(11)}
...> """
"""
• Feeling:\s
Supercalifragilisticexpialidociously supercalifragilisticexpialidocious!
"""
iex> import File.Only.Logger.Proxy, only: [maybe_break: 3]
iex> supercal = 'supercalifragilisticexpialidocious'
iex> msg = "Today I'm feeling astonishingly #{supercal}..."
iex> """
...> -- Message: #{inspect(msg) |> maybe_break(12, padding: "\s\s\s")}
...> """
"""
-- Message:\s
"Today I'm feeling astonishingly supercalifragilisticexpialidocious..."
"""
'''
@spec maybe_break(String.t(), pos_integer, keyword) :: String.t()
def maybe_break(string, offset, options \\ [])
when is_binary(string) and is_pos_integer(offset) and is_list(options) do
line_length =
case options[:line_length] do
length when is_pos_integer(length) -> length
_other -> @line_length
end
padding =
case options[:padding] do
filler when is_binary(filler) -> filler
_other -> @padding
end
if String.length(string) > line_length - offset,
do: "\n#{padding}#{string}",
else: string
end
@doc """
Returns the application for the current process or module.
Returns `:undefined` if the current process does not belong to any
application or the current module is not listed in any application spec.
## Examples
iex> alias File.Only.Logger.Proxy
iex> Proxy.app
:file_only_logger
"""
@spec app :: atom
def app do
case :application.get_application() do
{:ok, app} -> app
:undefined -> Application.get_application(__MODULE__) || :undefined
end
end
@doc """
Returns the current library name.
## Examples
iex> alias File.Only.Logger.Proxy
iex> Proxy.lib
:file_only_logger
"""
@spec lib :: atom
def lib, do: @lib
@doc """
Returns the given `module` as a string.
## Examples
iex> alias File.Only.Logger.Proxy
iex> Proxy.mod(__MODULE__)
"File.Only.Logger.ProxyTest"
iex> alias File.Only.Logger.Proxy
iex> Proxy.mod(Elixir.Date.Range)
"Date.Range"
"""
@spec mod(module) :: String.t()
def mod(module), do: inspect(module)
@doc ~S'''
Returns a formatted heredoc to trace a message from the given `env`
(`Macro.Env`).
## Examples
iex> alias File.Only.Logger.Proxy
iex> heredoc = """
...> • App: file_only_logger
...> • Library: file_only_logger
...> • Function:\s
...> File.Only.Logger.ProxyTest.
...> """
...> |> String.trim_trailing()
iex> Proxy.from(__ENV__) =~ heredoc
true
'''
@spec from(Macro.Env.t()) :: String.t()
def from(env) do
"""
• App: #{app()}
• Library: #{lib()}
• Function: #{fun(env) |> maybe_break(12)}
"""
|> String.trim_trailing()
end
@doc ~S'''
Returns a formatted heredoc to trace a message from the given `env`
(`Macro.Env`) and `module`.
## Examples
iex> alias File.Only.Logger.Proxy
iex> heredoc = """
...> • App: file_only_logger
...> • Library: file_only_logger
...> • Module: File.Only.Logger.ProxyTest
...> • Function:\s
...> File.Only.Logger.ProxyTest.
...> """
...> |> String.trim_trailing()
iex> Proxy.from(__ENV__, __MODULE__) =~ heredoc
true
'''
@spec from(Macro.Env.t(), module) :: String.t()
def from(env, module) do
"""
• App: #{app()}
• Library: #{lib()}
• Module: #{mod(module)}
• Function: #{fun(env) |> maybe_break(12)}
"""
|> String.trim_trailing()
end
## Private functions
@spec level :: Logger.level() | :all | :none
defp level, do: get_env(:level, :all)
end