error_logger(3)

πŸ“¦
version 29.0.6 Β· 3 versions
, in ubuntu stonking

🌸 error_logger 🌸

ok bestie, welcome to the Erlang error logger page β€” this is error_logger(3) from the Erlang Module Definition manual, and yes it's a long one so buckle up 🫢


NAME ✨

error_logger β€” Erlang error logger. that's it, that's the name πŸ’…


DESCRIPTION πŸ’–

NOTE: so in Erlang/OTP 21.0 a whole new API for logging got added. the old error_logger module can still be used by legacy code, but log events get redirected to the new Logger API. new code should use the Logger API directly, periodt. error_logger is no longer started by default, but it is automatically started when an event handler is added with error_logger:add_report_handler/1,2. the error_logger module is then also added as a handler to the new logger. see logger and the Logging chapter in the User's Guide for more info πŸ‘‘

The Erlang error logger is an event manager (see OTP Design Principles and gen_event), registered as error_logger.

Error logger is no longer started by default, but is automatically started when an event handler is added with add_report_handler/1,2. The error_logger module is then also added as a handler to the new logger, causing log events to be forwarded from logger to error logger, and consequently to all installed error logger event handlers. it's giving relay race πŸƒβ€β™€οΈ

User-defined event handlers can be added to handle application-specific events. yes bestie, you can make it your own πŸ’…

Existing event handlers provided by STDLIB and SASL are still available, but are no longer used by OTP. iconic but retired, honestly 😭

Warning events were introduced in Erlang/OTP R9C and are enabled by default as from Erlang/OTP 18.0. To retain backwards compatibility with existing user-defined event handlers, the warning events can be tagged as errors or info using command-line flag +W <e | i | w>, thus showing up as ERROR REPORT or INFO REPORT in the logs.


πŸ“‹ Events πŸ’–

All event handlers added to the error logger must handle the following events. Gleader is the group leader pid of the process that sent the event, and Pid is the process that sent the event. (iykyk, those two are doing a lot of work here)

  • {error, Gleader, {Pid, Format, Data}} β€” generated when error_msg/1,2 or format/2 is called.
  • {error_report, Gleader, {Pid, std_error, Report}} β€” generated when error_report/1 is called.
  • {error_report, Gleader, {Pid, Type, Report}} β€” generated when error_report/2 is called.
  • {warning_msg, Gleader, {Pid, Format, Data}} β€” generated when warning_msg/1,2 is called if warnings are set to be tagged as warnings.
  • {warning_report, Gleader, {Pid, std_warning, Report}} β€” generated when warning_report/1 is called if warnings are set to be tagged as warnings.
  • {warning_report, Gleader, {Pid, Type, Report}} β€” generated when warning_report/2 is called if warnings are set to be tagged as warnings.
  • {info_msg, Gleader, {Pid, Format, Data}} β€” generated when info_msg/1,2 is called.
  • {info_report, Gleader, {Pid, std_info, Report}} β€” generated when info_report/1 is called.
  • {info_report, Gleader, {Pid, Type, Report}} β€” generated when info_report/2 is called.
⚠️ heads up bestie: some system-internal events can also be received. so a catch-all clause last in the definition of the event handler callback function gen_event:handle_event/2 is necessary. this also applies for gen_event:handle_info/2, because the event handler must also take care of some system-internal messages. do not skip this, fr fr πŸ’€

πŸ‘€ See Also πŸ‘€

gen_event, logger, log_mf_h, kernel, sasl


πŸ’Ύ DATA TYPES πŸ’Ύ

open_error() :: file:posix() | badarg | system_limit.
report() ::
          [{Tag :: term(), Data :: term()} | term()] | string() | term().

πŸŽ€ FUNCTIONS πŸŽ€

🫢 add_report_handler(Handler, Args) -> Result

when
    Handler :: module(),
    Args :: gen_event:handler_args(),
    Result :: gen_event:add_handler_ret().

Adds a new event handler to the error logger. The event handler must be implemented as a gen_event callback module.

Handler is typically the name of the callback module and Args is an optional term (defaults to []) passed to the initialization callback function gen_event:init/1. The function returns ok if successful. πŸŽ‰

The event handler must be able to handle the events in this module, see section Events.

The first time this function is called, error_logger is added as a Logger handler, and the error_logger process is started. main character energy honestly ✨


🫢 delete_report_handler(Handler) -> Result

when
    Handler :: module(),
    Result :: gen_event:del_handler_ret().

Deletes an event handler from the error logger by calling gen_event:delete_handler(error_logger, Handler, []).

If no more event handlers exist after the deletion, error_logger is removed as a Logger handler, and the error_logger process is stopped. bye bestie 😭


🫢 error_msg(Format, Data) -> ok

when Format :: string(), Data :: list().

Log a standard error event. The Format and Data arguments are the same as the arguments of io:format/2 in STDLIB.

Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler.

🚨 This function is kept for backwards compatibility and must not be used by new code. Use the ?LOG_ERROR macro or logger:error/1,2,3 instead. periodt.

Example:

1> error_logger:error_msg("An error occurred in ~p", [a_module]).
=ERROR REPORT==== 22-May-2018::11:18:43.376917 ===
An error occurred in a_module
ok
WARNING: if the Unicode translation modifier (t) is used in the format string, all event handlers must ensure that the formatted output is correctly encoded for the I/O device. πŸ’…

🫢 error_report(Report) -> ok

when Report :: report().

Log a standard error event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler.

🚨 This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_ERROR macro or logger:error/1,2,3 instead.

Example:

2> error_logger:error_report([{tag1,data1},a_term,{tag2,data}]).
=ERROR REPORT==== 22-May-2018::11:24:23.699306 ===
    tag1: data1
    a_term
    tag2: data
ok
3> error_logger:error_report("Serious error in my module").
=ERROR REPORT==== 22-May-2018::11:24:45.972445 ===
Serious error in my module
ok

🫢 error_report(Type, Report) -> ok

when Type :: term(), Report :: report().

Log a user-defined error event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

Error logger also adds a domain field with value [Type] to this event's metadata, causing the filters of the default Logger handler to discard the event. A different Logger handler, or an error logger event handler, must be added to handle this event. so if you're like "why is my event disappearing 😭" β€” that's why. it's the domain field doing it, bestie.

It is recommended that Report follows the same structure as for error_report/1.

🚨 This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_ERROR macro or logger:error/1,2,3 instead.

🫢 get_format_depth() -> unlimited | pos_integer()

Returns max(10, Depth), where Depth is the value of error_logger_format_depth in the Kernel application, if Depth is an integer. Otherwise, unlimited is returned.

NOTE: the error_logger_format_depth variable is deprecated since the Logger API was introduced in Erlang/OTP 21.0. The variable, and this function, are kept for backwards compatibility since they still might be used by legacy report handlers. old but not forgotten πŸ₯²

🫢 info_msg(Format, Data) -> ok

when Format :: string(), Data :: list().

Log a standard information event. The Format and Data arguments are the same as the arguments of io:format/2 in STDLIB.

Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler.

🚨 These functions are kept for backwards compatibility and must not be used by new code. Use the ?LOG_INFO macro or logger:info/1,2,3 instead.

Example:

1> error_logger:info_msg("Something happened in ~p", [a_module]).
=INFO REPORT==== 22-May-2018::12:03:32.612462 ===
Something happened in a_module
ok
WARNING: if the Unicode translation modifier (t) is used in the format string, all event handlers must ensure that the formatted output is correctly encoded for the I/O device. yes this warning shows up twice, no we're not skipping it 🫢

🫢 info_report(Report) -> ok

when Report :: report().

Log a standard information event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

The event is handled by the default Logger handler.

🚨 This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_INFO macro or logger:info/1,2,3 instead.

Example:

2> error_logger:info_report([{tag1,data1},a_term,{tag2,data}]).
=INFO REPORT==== 22-May-2018::12:06:35.994440 ===
    tag1: data1
    a_term
    tag2: data
ok
3> error_logger:info_report("Something strange happened").
=INFO REPORT==== 22-May-2018::12:06:49.066872 ===
Something strange happened
ok

🫢 info_report(Type, Report) -> ok

when Type :: any(), Report :: report().

Log a user-defined information event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

Error logger also adds a domain field with value [Type] to this event's metadata, causing the filters of the default Logger handler to discard the event. A different Logger handler, or an error logger event handler, must be added to handle this event.

It is recommended that Report follows the same structure as for info_report/1.


Okay bestie, real talk before we get anywhere near logfile: this one comes with a giant ✨do-not-touch✨ sticker on it. It's kept for backwards compatibility and must not be used by new code. Use the ?LOG_INFO macro or logger:info/1,2,3 instead. That's the vibe. πŸ’…

logfile(Request) πŸ—‚οΈ

logfile(Request :: {open, Filename}) -> ok | {error, OpenReason}
        when
            Filename :: file:name(),
            OpenReason :: allready_have_logfile | open_error();
       (Request :: close) -> ok | {error, CloseReason}
        when CloseReason :: module_not_found;
       (Request :: filename) -> Filename | {error, FilenameReason}
        when
            Filename :: file:name(),
            FilenameReason :: no_log_file.

This is the switch that turns printout of standard events to a file on or off, bestie. On. Off. That's it. ✨

How does it do it? By adding or deleting the error_logger_file_h event handler, and thus indirectly adding error_logger as a Logger handler. Sneaky little chain reaction, iykyk. πŸ¦‹

⚠️ Heads up: this function does not manipulate the Logger configuration directly. Which means that if the default Logger handler is already logging to a file, this function can potentially cause logging to a second file. Two files. Both logging. Chaotic, ngl. 😭

It's genuinely handy as a shortcut during development and testing, but it must not be used in a production system. Like, fr fr, don't. For the real deal, check out the section Logging in the Kernel User's Guide, plus the logger manual page, for info about how to configure Logger for live systems. 🌸

So, Request is one of these:

  • {open, Filename} β€” opens the log file Filename. Returns ok if it went well, or {error, allready_have_logfile} if logging to file is already enabled, or an error tuple if some other error occurred (say, Filename can't be opened). The file gets opened with encoding UTF-8. πŸŽ€
  • close β€” closes the current log file. Returns ok, or {error, module_not_found}.
  • filename β€” returns the name of the log file Filename, or {error, no_log_file} if logging to file isn't enabled.

tty(Flag) πŸ–₯️

tty(Flag) -> ok when Flag :: boolean().

Turns printout of standard events to the terminal on (Flag == true) or off (Flag == false). Cute, simple, terminal-core. πŸ’…

This one works by manipulating the Logger configuration. And yeah, same warning as its sibling β€” it's a lovely shortcut during development and testing, but it must not be used in a production system. See the section Logging in the Kernel User's Guide, and the logger manual page, for how to actually configure Logger for live systems. 🌈

warning_map() πŸ—ΊοΈ

warning_map() -> Tag when Tag :: error | warning | info.

Hands you back the current mapping for warning events. πŸ‘‘

Events sent with warning_msg/1,2 or warning_report/1,2 get tagged as error, warning (that's the default, bestie), or info, depending on the value of the command-line flag +W. The way the flag just casually rewrites how serious a warning is… iconic behaviour, honestly. ✨

Example:

os$ erl
Erlang (BEAM) emulator version 5.4.8 [hipe] [threads:0] [kernel-poll]

Eshell V5.4.8  (abort with ^G)
1> error_logger:warning_map().
warning
2> error_logger:warning_msg("Warnings tagged as: ~p~n", [warning]).

=WARNING REPORT==== 11-Aug-2005::15:31:55 ===
Warnings tagged as: warning
ok
3>
User switch command
 --> q
os$ erl +W e
Erlang (BEAM) emulator version 5.4.8 [hipe] [threads:0] [kernel-poll]

Eshell V5.4.8  (abort with ^G)
1> error_logger:warning_map().
error
2> error_logger:warning_msg("Warnings tagged as: ~p~n", [error]).

=ERROR REPORT==== 11-Aug-2005::15:31:23 ===
Warnings tagged as: error
ok

warning_msg(Format, Data) ⚠️

warning_msg(Format, Data) -> ok
        when Format :: string(), Data :: list().

Logs a standard warning event. The Format and Data arguments are literally the same as the arguments of io:format/2 in STDLIB β€” nothing new to learn, you already know this one. 🫢

Error logger forwards the event to Logger, and it bundles in metadata that allows backwards compatibility with legacy error logger event handlers. Teamwork, honestly.

The event is handled by the default Logger handler. The log level can be changed to error or info β€” see warning_map/0. πŸ”₯

These functions are kept for backwards compatibility and must not be used by new code. Use the ?LOG_WARNING macro or logger:warning/1,2,3 instead.

πŸ’€ WARNING: If the Unicode translation modifier (t) is used in the format string, all event handlers must ensure that the formatted output is correctly encoded for the I/O device. No skipping this one, bestie, it will bite you.

warning_report(Report) πŸ“‹

warning_report(Report) -> ok when Report :: report().

Logs a standard warning event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers. Same lore as above. πŸ’œ

Handled by the default Logger handler. Log level can be changed to error or info, see warning_map/0.

This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_WARNING macro or logger:warning/1,2,3 instead. (Yes, we're saying it every time. It's that important. πŸŽ€)

warning_report(Type, Report) πŸ“‹βœ¨

warning_report(Type, Report) -> ok
        when Type :: any(), Report :: report().

Logs a user-defined warning event. Error logger forwards the event to Logger, including metadata that allows backwards compatibility with legacy error logger event handlers.

Now here's the spicy bit, bestie: error logger also adds a domain field with value [Type] to this event's metadata, which causes the filters of the default Logger handler to discard the event. So a different Logger handler β€” or an error logger event handler β€” must be added to handle this event. The default one simply is not going to pick up the phone. πŸ™ˆ

The log level can be changed to error or info, see warning_map/0.

It's recommended that Report follows the same structure as for warning_report/1. 🌸

This functions is kept for backwards compatibility and must not be used by new code. Use the ?LOG_WARNING macro or logger:warning/1,2,3 instead.


And that's a wrap on error_logger, bestie!! πŸŽ‰ This whole page is brought to you by Ericsson AB and it's living in kernel, version 11.0.3, filed under error_logger(3). Go forth and please, for the love of everything, use logger for new code. πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from