logi_ex v0.1.1 Logi

Logger Interface.

This module mainly provides logger related functions. A logger has own headers, metadata, filter and can issue log messages to a destination channel.

It is an Elixir interface of the Erlang logi library.

Examples

Basic usage:

iex> require Logi

# Installs a sink to the default channel
iex> Logi.Channel.install_sink(Logi.BuiltIn.Sink.IoDevice.new(:foo), :info)
{:ok, :undefined}

iex> Logi.info "hello world"
#OUTPUT# 2016-12-04 20:04:44.308 [info] nonode@nohost <0.150.0> nil:nil:3 [] hello world

Summary

Types

The headers of a log message

Options for log/4 and related macros

A logger

The ID of a saved logger instance (see: save/2)

A logger instance

The map representation of a logger

The metadata of a log message

Options for new/1

Severity of a log message

Functions

Returns the default logger

Deletes headers which associated with keys

Deletes metadata which associated with keys

Returns the logger instance associated to logger

Returns the saved loggers and deletes them from the process dictionary

Returns the logger associated with logger_id and deletes it from the process dictionary

Aggregates loggers into a logger instance

Creates a new logger instance from map

Loads a logger which associated with the ID logger_id from the process dictionary

Equivalent to Logi.load(Logi.default_logger)

Returns true if x is a logger, otherwise false

Creates a new logger instance

Saves logger with the ID logger_id to the process dictionary

Equivalent to Logi.save(Logi.default_logger, logger)

Sets headers of the logger

Sets metadata of the logger

Returns the available severity list

Returns true if x is a severity, otherwise false

Returns the level of severity

Flattens the nested logger

Converts logger into a map form

Returns the ID list of the saved loggers

Macros

Equivalent to Logi.log :alert, format, data, options

Equivalent to Logi.log :critical, format, data, options

Equivalent to Logi.log :debug, format, data, options

Equivalent to Logi.log :emergency, format, data, options

Equivalent to Logi.log :error, format, data, options

Equivalent to Logi.log :info, format, data, options

Issues a log message to the destination channel

Equivalent to Logi.log :notice, format, data, options

Equivalent to Logi.log :warning, format, data, options

Types

headers()
headers() :: %{}

The headers of a log message.

Headers are intended to be included in the outputs written by sinks.

log_options()
log_options() :: [logger: logger, location: Logi.Location.location, headers: headers, metadata: metadata, timestamp: :erlang.timestamp]

Options for log/4 and related macros.

logger

  • The logger of interest
  • Default: Logi.default_logger

location

  • The log message issued location
  • Default: Logi.Location.current_location

headers

  • The headers of the log message
  • They are merged with the headers of the logger (the former has priority when key collisions occur)
  • Default: %{}

metadata

  • The metadata of the log message
  • They are merged with the metadata of the logger (the former has priority when key collisions occur)
  • Default: %{}

timestamp

  • The log message issued time
  • Default: :os.timestamp
logger()
logger() :: logger_id | logger_instance

A logger.

logger_id()
logger_id() :: atom

The ID of a saved logger instance (see: save/2).

If such a logger instance does not exist, the ID will be regarded as an alias of the expression new([{:channel, logger_id}]).

logger_instance()

A logger instance.

logger_map_form()
logger_map_form() :: %{channel: Logi.Channel.id, headers: headers, metadata: metadata, filter: Logi.Filter.filter, next: logger_instance}

The map representation of a logger.

filter and next fields are optional (e.g. If a logger has no filter, the filter field is omitted from the corresponding map).

metadata()
metadata() :: %{}

The metadata of a log message

Metadata are not intended to be included directly in the outputs written by sinks. The main purpose of metadata is to provide means to convey information from the log issuer to filters or sinks.

new_options()
new_options() :: [channel: Logi.Channel.id, headers: headers, metadata: metadata, filter: Logi.Filter.filter, next: logger_instance]

Options for new/1.

channel

  • The destination channel
  • The log messages issued by the created logger will (logically) send to the channel
  • Default: Logi.Channel.default_channel

headers

  • The headers of the created logger
  • Default: ${}

metadata

  • The metadata of the created logger
  • Default: %{}

filter

  • A log message filter
  • Default: none (optional)

next

  • A next logger
  • An application of the some function (e.g. log/4) to the created logger is also applied to the next logger
  • Default: none (optional)
severity()
severity ::
  :debug |
  :info |
  :notice |
  :warning |
  :error |
  :critical |
  :alert |
  :emergency

Severity of a log message.

It follwed the severities which are described in RFC 5424.

Functions

default_logger()
default_logger() :: logger_id

Returns the default logger.

The default channel Logi.Channel.default_channel/0 which corresponds to the logger is started automatically when logi_ex application was started.

delete_headers(keys, options \\ [])
delete_headers([any], options) :: logger_instance when options: [{:logger, logger}]

Deletes headers which associated with keys.

If the logger has nested loggers, the function is applied to them recursively.

Examples

iex> logger = Logi.new [headers: %{:a => 1, :b => 2}]
iex> Logi.to_map Logi.delete_headers([:a], [logger: logger])
%{channel: :logi_default_log, headers: %{b: 2}, metadata: %{}}
delete_metadata(keys, options \\ [])
delete_metadata([any], options) :: logger_instance when options: [{:logger, logger}]

Deletes metadata which associated with keys.

If the logger has nested loggers, the function is applied to them recursively.

Examples

iex> logger = Logi.new [metadata: %{:a => 1, :b => 2}]
iex> Logi.to_map Logi.delete_metadata([:a], [logger: logger])
%{channel: :logi_default_log, metadata: %{b: 2}, metadata: %{}}
ensure_to_be_instance(logger)
ensure_to_be_instance(logger) :: logger_instance

Returns the logger instance associated to logger.

Examples

iex> Logi.ensure_to_be_instance :unsaved
{:logi_logger, :unsaved, %{}, %{}, :undefined, :undefined}

iex> Logi.save :saved, Logi.new([channel: :foo])
iex> Logi.ensure_to_be_instance :foo
{:logi_logger, :foo, %{}, %{}, :undefined, :undefined}

iex> Logi.ensure_to_be_instance Logi.new([channel: :bar])
{:logi_logger, :bar, %{}, %{}, :undefined, :undefined}
erase()
erase() :: [{logger_id, logger_instance}]

Returns the saved loggers and deletes them from the process dictionary.

Examples

iex> Logi.save :foo, Logi.new

iex> Logi.erase
[foo: {:logi_logger, :logi_default_log, %{}, %{}, :undefined, :undefined}]

iex> Logi.erase
[]
erase(logger_id)
erase(logger_id) :: logger_instance | :undefined

Returns the logger associated with logger_id and deletes it from the process dictionary.

Returns :undefined if no logger is associated with logger_id.

Examples

iex> Logi.save :foo, Logi.new
iex> Logi.erase :foo
{:logi_logger, :logi_default_log, %{}, %{}, :undefined, :undefined}

iex> Logi.erase :foo
:undefined
from_list(loggers)
from_list([logger]) :: logger_instance

Aggregates loggers into a logger instance.

The head logger in loggers becomes the root of the aggregation. e.g. from_list([new, new, new]) is equivalent to new([next: new([next: new])]).

from_map(map)

Creates a new logger instance from map.

Default Values

  • channel: Logi.Channel.default_channel
  • headers: %{}
  • metadata: %{}
  • filter: none (optional)
  • next: none (optional)

Examples

iex> Logi.to_map(Logi.from_map(%{}))
%{channel: :logi_default_log, headers: %{}, metadata: %{}}
load(logger_id)
load(logger_id) :: {:ok, logger_instance} | :error

Loads a logger which associated with the ID logger_id from the process dictionary.

Examples

iex> :error = Logi.load :foo_log

iex> Logi.save :foo_log, Logi.new
iex> {:ok, _} = Logi.load :foo_log
load_default()
load_default() :: {:ok, logger_instance} | :error

Equivalent to Logi.load(Logi.default_logger).

logger?(x)
logger?(any) :: boolean

Returns true if x is a logger, otherwise false.

new(options \\ [])

Creates a new logger instance.

save(logger_id, logger)
save(logger_id, logger) :: logger_instance | :undefined

Saves logger with the ID logger_id to the process dictionary.

If logger_id already exists, the old logger instance is deleted and replaced by logger and the function returns the old instance. Otherwise it returns :undefined.

In the process, a saved logger instance can be referred by the ID.

Examples

iex> require Logi

iex> logger = Logi.new
iex> Logi.save :sample_log, logger

# The following two expression is equivalent.
iex> Logi.info "hello world", [], [logger: logger]  # referred by instance
iex> Logi.info "hello world", [], [logger: :sample_log] # referred by ID
save_as_default(logger)
save_as_default(logger) :: logger_instance | :undefined

Equivalent to Logi.save(Logi.default_logger, logger).

set_headers(headers, options \\ [])
set_headers(headers, options) :: logger_instance when options: [logger: logger, if_exists: :ignore | :overwrite | :supersede]

Sets headers of the logger.

If the logger has nested loggers, the function is applied to them recursively.

Options

logger

  • The logger to which the operation applies.
  • Default: Logi.default_logger

if_exists

  • If the value is :supersede, the existing headers are deleted and replaced by headers.
  • If the value is :overwrite, the existing headers and headers are merged and the rear has priority when a key collision occurs.
  • If the value is :ignore, the existing headers and headers are merged and the former has priority when a key collision occurs.
  • Default: :overwrite

Examples

iex> logger = Logi.new([headers: %{:a => 10, :b => 20}])
iex> set = fn (hs, ie) -> l = Logi.set_headers(hs, [logger: logger, if_exists: ie]); Logi.to_map(l)[:headers] end

iex> true = %{:a => 0,            :c => 30} == set.(%{:a => 0, :c => 30}, :supersede)
iex> true = %{:a => 0,  :b => 20, :c => 30} == set.(%{:a => 0, :c => 30}, :overwrite)
iex> true = %{:a => 10, :b => 20, :c => 30} == set.(%{:a => 0, :c => 30}, :ignore)
set_metadata(metadata, options \\ [])
set_metadata(metadata, options) :: logger_instance when options: [logger: logger, if_exists: :ignore | :overwrite | :supersede]

Sets metadata of the logger.

If the logger has nested loggers, the function is applied to them recursively.

Options

See documentation for set_headers/2.

severities()
severities() :: [severity]

Returns the available severity list.

The list are ordered by the their severity level (see: severity_level/1).

severity?(x)
severity?(any) :: boolean

Returns true if x is a severity, otherwise false.

severity_level(severity)
severity_level(severity) :: 1..8

Returns the level of severity.

The higher the severity is, the lower the level is.

to_list(logger)
to_list(logger) :: [logger_instance]

Flattens the nested logger.

The nested loggers are collected as a flat list. The next fields of the resulting loggers are removed.

Examples

iex> logger0 = Logi.new
iex> logger1 = Logi.new([next: logger0])
iex> logger2 = Logi.new([next: logger1])
iex> [^logger0] = Logi.to_list(logger0)
iex> [^logger0, ^logger0] = Logi.to_list(logger1)
iex> [^logger0, ^logger0, ^logger0] = Logi.to_list(logger2)
to_map(logger)
to_map(logger) :: logger_map_form

Converts logger into a map form.

The optional entries (i.e. filter and next) will be omitted from the resulting map if the value is not set.

Examples

iex> Logi.to_map(Logi.new)
%{channel: :logi_default_log, headers: %{}, metadata: %{}}

iex> Logi.to_map(Logi.new([next: Logi.new]))
%{channel: :logi_default_log, headers: %{}, metadata: %{},
next: {:logi_logger, :logi_default_log, %{}, %{}, :undefined, :undefined}}
which_loggers()
which_loggers() :: [logger_id]

Returns the ID list of the saved loggers.

Examples

iex> Logi.save :foo, Logi.new
iex> Logi.which_loggers
[:foo]

Macros

alert(format, data \\ [], options \\ [])
alert(term, :io.format, [any], log_options) :: logger_instance

Equivalent to Logi.log :alert, format, data, options.

critical(format, data \\ [], options \\ [])
critical(term, :io.format, [any], log_options) :: logger_instance

Equivalent to Logi.log :critical, format, data, options.

debug(format, data \\ [], options \\ [])
debug(term, :io.format, [any], log_options) :: logger_instance

Equivalent to Logi.log :debug, format, data, options.

emergency(format, data \\ [], options \\ [])
emergency(term, :io.format, [any], log_options) :: logger_instance

Equivalent to Logi.log :emergency, format, data, options.

error(format, data \\ [], options \\ [])
error(term, :io.format, [any], log_options) :: logger_instance

Equivalent to Logi.log :error, format, data, options.

info(format, data \\ [], options \\ [])
info(term, :io.format, [any], log_options) :: logger_instance

Equivalent to Logi.log :info, format, data, options.

log(severity, format, data \\ [], options \\ [])
log(term, severity, :io.format, [any], log_options) :: logger_instance

Issues a log message to the destination channel.

If the logger has a filter, the message will be passed to it. And if the message has not been discarded by a filter, the logger will (logically) send it to the destination channel. Finally, the message will be consumed by the sinks which are installed to the channel. But the sinks which does not satisfy specified condition are ignored.

iex> require Logi

# Installs a sink to the default channel
iex> {:ok, _} = Logi.Channel.install_sink(Logi.BuiltIn.Sink.IoDevice.new(:sample), :info)

iex> Logi.log :debug, "hello world", [], []  # There are no applicable sinks (the severity is too low)
iex> Logi.log :info, "hello world", [], []   # The log message is consumed by the above sink
#OUTPUT# 2016-12-04 23:04:17.028 [info] nonode@nohost <0.150.0> nil:nil:19 [] hello world

If the logger has nested loggers, the function is applied to them recursively.

# Installs a sink to the default channel
iex> {:ok, _} = Logi.Channel.install_sink(Logi.BuiltIn.Sink.IoDevice.new(:sample), :info)
iex> logger = Logi.from_list([Logi.new([headers: %{:id => :foo}]), Logi.new([headers: %{:id => :bar}])])
iex> Logi.log :info, "hello world", [], [logger: logger]
#OUTPUT# 2016-12-04 23:08:51.778 [info] nonode@nohost <0.150.0> nil:nil:24 [id=foo] hello world
#OUTPUT# 2016-12-04 23:08:51.778 [info] nonode@nohost <0.150.0> nil:nil:24 [id=bar] hello world
notice(format, data \\ [], options \\ [])
notice(term, :io.format, [any], log_options) :: logger_instance

Equivalent to Logi.log :notice, format, data, options.

warning(format, data \\ [], options \\ [])
warning(term, :io.format, [any], log_options) :: logger_instance

Equivalent to Logi.log :warning, format, data, options.