Module logi

Logger Interface.

Copyright © 2014-2016 Takeru Ohta <phjgt308@gmail.com>

Description

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.

EXAMPLE

Basic Usage:
  > error_logger:tty(false). % Suppresses annoying warnings for the sake of brevity
  > {ok, _} = logi_channel:install_sink(logi_builtin_sink_io_device:new(foo), info). % Installs a sink to the default channel
  > logi:info("hello world").
  2015-11-09 08:18:34.954 [info] nonode@nohost <0.91.0> erl_eval:do_apply:673 [] hello world
  

Data Types

context()

context() = logger_instance()

This is provided only for maintaining compatibility with v0.0.12

context_ref()

context_ref() = logger()

This is provided only for maintaining compatibility with v0.0.12

frequency_policy()

frequency_policy() = always | once | {once_in_times, Times::pos_integer()} | {interval, MilliSeconds::non_neg_integer()}

headers()

headers() = #{}

The headers of a log message.

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

log_option()

log_option() = {logger, logger()} | {location, logi_location:location()} | {headers, headers()} | {metadata, metadata()} | {timestamp, erlang:timestamp()} | {frequency, frequency_policy()}

log_options()

log_options() = [log_option()]

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, LoggerId}]).

logger_instance()

abstract datatype: 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_option()

new_option() = {channel, logi_channel:id()} | {headers, headers()} | {metadata, metadata()} | {filter, logi_filter:filter()} | {next, logger_instance()}

[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)

new_options()

new_options() = [new_option()]

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](https://tools.ietf.org/html/rfc5424#section-6.2.1).

Function Index

alert/1Equivalent to alert(Format, []).
alert/2Equivalent to alert(Format, Data, []).
alert/3Equivalent to log(alert, Format, Data, Options).
critical/1Equivalent to critical(Format, []).
critical/2Equivalent to critical(Format, Data, []).
critical/3Equivalent to log(critical, Format, Data, Options).
debug/1Equivalent to debug(Format, []).
debug/2Equivalent to debug(Format, Data, []).
debug/3Equivalent to log(debug, Format, Data, Options).
debug_opt/3Equivalent to debug(Format, Data, Options).
default_logger/0Returns the default logger.
delete_headers/1Equivalent to delete_headers(Keys, []).
delete_headers/2Deletes headers which associated with Keys
delete_metadata/1Equivalent to delete_metadata(Keys, []).
delete_metadata/2Deletes metadata entries which associated with Keys
emergency/1Equivalent to emergency(Format, []).
emergency/2Equivalent to emergency(Format, Data, []).
emergency/3Equivalent to log(emergency, Format, Data, Options).
ensure_to_be_instance/1Returns the logger instance associated to Logger
erase/0Returns the saved loggers and deletes them from the process dictionary.
erase/1Returns the logger associated with LoggerId and deletes it from the process dictionary.
error/1Equivalent to error(Format, []).
error/2Equivalent to error(Format, Data, []).
error/3Equivalent to log(error, Format, Data, Options).
from_list/1Aggregates Loggers into a logger instance.
from_map/1Creates a new logger instance from Map
info/1Equivalent to info(Format, []).
info/2Equivalent to info(Format, Data, []).
info/3Equivalent to log(info, Format, Data, Options).
info_opt/3Equivalent to info(Format, Data, Options).
is_logger/1Returns true if X is a logger, otherwise false
is_severity/1Returns true if X is a severity, otherwise false
load/1Loads a logger which associated with the ID LoggerId from the process dictionary.
load_context/0Equivalent to ensure_to_be_instance(default_logger()).
load_default/0Equivalent to load(default_logger()).
log/4Issues a log message to the destination channel.
make_context/0Equivalent to new().
make_context/1Equivalent to new([{channel, ChannelId}]).
new/0Equivalent to new([]).
new/1Creates a new logger instance.
notice/1Equivalent to notice(Format, []).
notice/2Equivalent to notice(Format, Data, []).
notice/3Equivalent to log(notice, Format, Data, Options).
notice_opt/3Equivalent to notice(Format, Data, Options).
save/2Saves Logger with the ID LoggerId to the process dictionary.
save_as_default/1Equivalent to save(default_logger(), Logger).
save_context/1Equivalent to save_as_default(Logger).
set_headers/1Equivalent to set_headers(Headers, []).
set_headers/2Sets headers of the logger.
set_metadata/1Equivalent to set_metadata(Metadata, []).
set_metadata/2Sets metadata of the logger.
severities/0Returns the available severity list.
severity_level/1Returns the level of Severity
to_list/1Flattens the nested logger.
to_map/1Converts Logger into a map form.
verbose/1Equivalent to verbose(Format, []).
verbose/2Equivalent to verbose(Format, Data, []).
verbose/3Equivalent to log(debug, Format, Data, Options).
verbose_opt/3Equivalent to debug(Format, Data, Options).
warning/1Equivalent to warning(Format, []).
warning/2Equivalent to warning(Format, Data, []).
warning/3Equivalent to log(warning, Format, Data, Options).
warning_opt/3Equivalent to warning(Format, Data, Options).
which_loggers/0Returns the ID list of the saved loggers.

Function Details

alert/1

alert(Format::io:format()) -> logger_instance()

Equivalent to alert(Format, []).

alert/2

alert(Format::io:format(), Data::[term()]) -> logger_instance()

Equivalent to alert(Format, Data, []).

alert/3

alert(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to log(alert, Format, Data, Options).

critical/1

critical(Format::io:format()) -> logger_instance()

Equivalent to critical(Format, []).

critical/2

critical(Format::io:format(), Data::[term()]) -> logger_instance()

Equivalent to critical(Format, Data, []).

critical/3

critical(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to log(critical, Format, Data, Options).

debug/1

debug(Format::io:format()) -> logger_instance()

Equivalent to debug(Format, []).

debug/2

debug(Format::io:format(), Data::[term()]) -> logger_instance()

Equivalent to debug(Format, Data, []).

debug/3

debug(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to log(debug, Format, Data, Options).

debug_opt/3

debug_opt(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to debug(Format, Data, Options).

default_logger/0

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 application was started.

delete_headers/1

delete_headers(Keys::[term()]) -> logger_instance()

Equivalent to delete_headers(Keys, []).

delete_headers/2

delete_headers(Keys::[term()], Options) -> logger_instance()

Deletes headers which associated with Keys

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

OPTION

[logger] - The logger to which the operation applies. - Default: logi:default_logger().

  > Logger = logi:new([{headers, #{a => 1, b => 2}}]).
  > logi:to_map(logi:delete_headers([a], [{logger, Logger}])).
  #{channel => logi_default_log,headers => #{b => 2},metadata => #{}}
  

delete_metadata/1

delete_metadata(Keys::[term()]) -> logger_instance()

Equivalent to delete_metadata(Keys, []).

delete_metadata/2

delete_metadata(Keys::[term()], Options) -> logger_instance()

Deletes metadata entries which associated with Keys

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

OPTION

[logger] - The logger to which the operation applies. - Default: logi:default_logger().

  > Logger = logi:new([{metadata, #{a => 1, b => 2}}]).
  > logi:to_map(logi:delete_metadata([a], [{logger, Logger}])).
  #{channel => logi_default_log,headers => #{},metadata => #{b => 2}}
  

emergency/1

emergency(Format::io:format()) -> logger_instance()

Equivalent to emergency(Format, []).

emergency/2

emergency(Format::io:format(), Data::[term()]) -> logger_instance()

Equivalent to emergency(Format, Data, []).

emergency/3

emergency(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to log(emergency, Format, Data, Options).

ensure_to_be_instance/1

ensure_to_be_instance(Logger::logger()) -> logger_instance()

Returns the logger instance associated to Logger

  > logi:ensure_to_be_instance(unsaved).
  {logi_logger,unsaved,#{},#{},undefined,undefined}
 
  > logi:save(saved, logi:new([{channel, hoge}])).
  > logi:ensure_to_be_instance(hoge).
  {logi_logger,hoge,#{},#{},undefined,undefined}
 
  > logi:ensure_to_be_instance(logi:new([{channel, instance}])).
  {logi_logger,instance,#{},#{},undefined,undefined}
  

erase/0

erase() -> [{logger_id(), logger_instance()}]

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

  > logi:save(hoge, logi:new()).
  > logi:erase().
  [{hoge,{logi_logger,logi_default_log,#{},#{},undefined,undefined}}]
 
  > logi:erase().
  []
  

erase/1

erase(LoggerId::logger_id()) -> logger_instance() | undefined

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

Returns undefined if no logger is associated with LoggerId.

  > logi:save(hoge, logi:new()).
  > logi:erase(hoge).
  {logi_logger,logi_default_log,#{},#{},undefined,undefined}
 
  > logi:erase(hoge).
  undefined
  

error/1

error(Format::io:format()) -> logger_instance()

Equivalent to error(Format, []).

error/2

error(Format::io:format(), Data::[term()]) -> logger_instance()

Equivalent to error(Format, Data, []).

error/3

error(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to log(error, Format, Data, Options).

from_list/1

from_list(Loggers::[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()}])}]).

  > GetChannel = fun (Logger) -> maps:get(channel, logi:to_map(Logger)) end.
 
  > Logger0 = logi:new([{channel, aaa}]).
  > Logger1 = logi:new([{channel, bbb}]).
  > Logger2 = logi:new([{channel, ccc}, {next, logi:new([{channel, ccc_sub}])}]).
 
  > [aaa, bbb] = lists:map(GetChannel, logi:to_list(logi:from_list([Logger0, Logger1]))).
  > [ccc, ccc_sub, aaa, bbb] = lists:map(GetChannel, logi:to_list(logi:from_list([Logger2, Logger0, Logger1]))).
  

from_map/1

from_map(Map::logger_map_form()) -> logger_instance()

Creates a new logger instance from Map

Default Value: - channel: logi_channel:default_channel() - headers: #{} - metadata: #{} - filter: none (optional) - next: none (optional)

  > logi:to_map(logi:from_map(#{})).
  #{channel => logi_default_log,headers => #{},metadata => #{}}
  

info/1

info(Format::io:format()) -> logger_instance()

Equivalent to info(Format, []).

info/2

info(Format::io:format(), Data::[term()]) -> logger_instance()

Equivalent to info(Format, Data, []).

info/3

info(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to log(info, Format, Data, Options).

info_opt/3

info_opt(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to info(Format, Data, Options).

is_logger/1

is_logger(X::logger() | term()) -> boolean()

Returns true if X is a logger, otherwise false

is_severity/1

is_severity(X::severity() | term()) -> boolean()

Returns true if X is a severity, otherwise false

load/1

load(LoggerId::logger_id()) -> {ok, logger_instance()} | error

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

  > error = logi:load(hoge_log).
 
  > logi:save(hoge_log, logi:new()).
  > {ok, _} = logi:load(hoge_log).
  

load_context/0

load_context() -> logger_instance()

Equivalent to ensure_to_be_instance(default_logger()).

load_default/0

load_default() -> {ok, logger_instance()} | error

Equivalent to load(default_logger()).

log/4

log(Severity::severity(), Format::io:format(), Data::[term()], Options::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 (i.e. logi_sink:condition/0) are ignored.

  > {ok, _} = logi_channel:install_sink(logi_builtin_sink_io_device:new(sample), info). % Installs a sink to the default channel
  > logi:log(debug, "hello world", [], []). % There are no applicable sinks (the severity is too low)
  > logi:log(info, "hello world", [], []). % The log message is consumed by the above sink
  2015-10-22 13:16:37.003 [info] nonode@nohost <0.91.0> erl_eval:do_apply:673 [] hello world
  

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

  > {ok, _} = logi_channel:install_sink(logi_builtin_sink_io_device:new(sample), info). % Installs a sink to the default channel
  > Logger = logi:from_list([logi:new([{headers, #{id => hoge}}]), logi:new([{headers, #{id => fuga}}])]).
  > logi:log(info, "hello world", [], [{logger, Logger}]).
  2015-10-22 13:28:10.332 [info] nonode@nohost <0.91.0> erl_eval:do_apply:673 [id=hoge] hello world
  2015-10-22 13:28:10.332 [info] nonode@nohost <0.91.0> erl_eval:do_apply:673 [id=fuga] hello world
  

NOTE

Typically, it is preferred to log messages through the wrapper functions (i.e. logi:Severity/{1,2,3}) rather than calling the function directly.

If the {parse_transform, logi_transform} compiler option is specified, the invocation of the wrapper functions will be transformed to a more efficient code at compile time.

For example logi:info("hello world) will be transformed to a code such as following:
  %% Current location (Application, Module, Function and Line) is detected at compile time
  Location = logi_location:unsafe_new(self(), Application, Module, Function, Line),
  case logi:'_ready'(info, Location, Options) of
    {Logger, []}                    -> Logger;
    {Logger, ListOfContextAndSinks} -> logi:_write(ListOfContextAndSinks, Format, Data)
  end.
  

From the efficiency point of view, the following two points are important: - 1. An implicit call of logi_location:guess_location/0 to guess the currrent location is replaced by the more efficient and accurate code - 2. If it is unnecessary (e.g. there are no applicable sinks), Format and Data will not be evaluated

The logi_location:guess_location/0 is a heavy function, so if it is called at runtime, a warning will be emitted via the error_logger module.

See also: logi_location:guess_location/0.

make_context/0

make_context() -> logger_instance()

Equivalent to new().

make_context/1

make_context(ChannelId::logi_channel:id()) -> logger_instance()

Equivalent to new([{channel, ChannelId}]).

new/0

new() -> logger_instance()

Equivalent to new([]).

new/1

new(Options::new_options()) -> logger_instance()

Creates a new logger instance

notice/1

notice(Format::io:format()) -> logger_instance()

Equivalent to notice(Format, []).

notice/2

notice(Format::io:format(), Data::[term()]) -> logger_instance()

Equivalent to notice(Format, Data, []).

notice/3

notice(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to log(notice, Format, Data, Options).

notice_opt/3

notice_opt(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to notice(Format, Data, Options).

save/2

save(LoggerId::logger_id(), Logger::logger()) -> logger_instance() | undefined

Saves Logger with the ID LoggerId to the process dictionary

If LoggerId 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.
  > Logger = logi:new().
  > logi:save(sample_log, Logger).
 
  % The following two expression is equivalent.
  > logi:info("hello world", [{logger, Logger}]).  % referred by instance
  > logi:info("hello world", [{logger, sample_log}]). % referred by ID
  

save_as_default/1

save_as_default(Logger::logger()) -> logger_instance() | undefined

Equivalent to save(default_logger(), Logger).

save_context/1

save_context(Logger::logger()) -> logger_instance() | undefined

Equivalent to save_as_default(Logger).

set_headers/1

set_headers(Headers::headers() | list()) -> logger_instance()

Equivalent to set_headers(Headers, []).

set_headers/2

set_headers(Headers::headers() | V0_0_12_Compatible, Options) -> logger_instance()

Sets headers of the logger

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

OPTION

[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

  > Logger = logi:new([{headers, #{a => 10, b => 20}}]).
  > Set = fun (Headers, IfExists) ->
              L = logi:set_headers(Headers, [{logger, Logger}, {if_exists, IfExists}]),
              maps:get(headers, logi:to_map(L))
          end.
 
  > true = #{a => 0,           c => 30} =:= Set(#{a => 0, c => 30}, supersede).
  > true = #{a => 0,  b => 20, c => 30} =:= Set(#{a => 0, c => 30}, overwrite).
  > true = #{a => 10, b => 20, c => 30} =:= Set(#{a => 0, c => 30}, ignore).
  

set_metadata/1

set_metadata(Metadata::metadata()) -> logger_instance()

Equivalent to set_metadata(Metadata, []).

set_metadata/2

set_metadata(Metadata::metadata(), Options) -> logger_instance()

Sets metadata of the logger

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

OPTION

[logger] - The logger to which the operation applies. - Default: logi:default_logger().

[if_exists] - If the value is supersede, the existing metadata is deleted and replaced by Metadata. - If the value is overwrite, the existing metadata and Metadata are merged and the rear has priority when a key collision occurs. - If the value is ignore, the existing metadata and Metadata are merged and the former has priority when a key collision occurs. - Default: overwrite

  > Logger = logi:new([{metadata, #{a => 10, b => 20}}]).
  > Set = fun (Metadata, IfExists) ->
              L = logi:set_metadata(Metadata, [{logger, Logger}, {if_exists, IfExists}]),
              maps:get(metadata, logi:to_map(L))
          end.
 
  > true = #{a => 0,           c => 30} =:= Set(#{a => 0, c => 30}, supersede).
  > true = #{a => 0,  b => 20, c => 30} =:= Set(#{a => 0, c => 30}, overwrite).
  > true = #{a => 10, b => 20, c => 30} =:= Set(#{a => 0, c => 30}, ignore).
  

severities/0

severities() -> [severity()]

Returns the available severity list

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

severity_level/1

severity_level(Severity::severity()) -> 1..8

Returns the level of Severity

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

to_list/1

to_list(Logger::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.

  > Logger0 = logi:new().
  > Logger1 = logi:new([{next, Logger0}]).
  > Logger2 = logi:new([{next, Logger1}]).
  > [Logger0] = logi:to_list(Logger0).
  > [Logger0, Logger0] = logi:to_list(Logger1).
  > [Logger0, Logger0, Logger0] = logi:to_list(Logger2).
  

to_map/1

to_map(Logger::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.

  > logi:to_map(logi:new()).
  #{channel => logi_default_log,headers => #{},metadata => #{}}
 
  > logi:to_map(logi:new([{next, logi:new()}])).
  #{channel => logi_default_log,
    headers => #{},
    metadata => #{},
    next => {logi_logger,logi_default_log,#{},#{},undefined,undefined}}
  

verbose/1

verbose(Format::io:format()) -> logger_instance()

Equivalent to verbose(Format, []).

verbose/2

verbose(Format::io:format(), Data::[term()]) -> logger_instance()

Equivalent to verbose(Format, Data, []).

verbose/3

verbose(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to log(debug, Format, Data, Options).

verbose_opt/3

verbose_opt(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to debug(Format, Data, Options).

warning/1

warning(Format::io:format()) -> logger_instance()

Equivalent to warning(Format, []).

warning/2

warning(Format::io:format(), Data::[term()]) -> logger_instance()

Equivalent to warning(Format, Data, []).

warning/3

warning(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to log(warning, Format, Data, Options).

warning_opt/3

warning_opt(Format::io:format(), Data::[term()], Options::log_options()) -> logger_instance()

Equivalent to warning(Format, Data, Options).

which_loggers/0

which_loggers() -> [logger_id()]

Returns the ID list of the saved loggers

  > logi:save(hoge, logi:new()).
  > logi:which_loggers().
  [hoge]
  


Generated by EDoc