Module nh_logger

A logger handler that sends log events to NervesHub.

Description

A logger handler that sends log events to NervesHub.

Saves an application from calling nerves_hub_link:send_log/3 by hand, which is the difference between a logging extension that gets used and one that is forgotten.

  logger_manager:start_link(#{
      log_level => info,
      logger => [
          {handler, default, logger_std_h, #{}},
          nh_logger:handler(#{level => info})
      ]
  })

Handlers are given to logger_manager when it starts and there is no add_handler/3 on AtomVM, so this is arranged by the application at startup rather than by the agent when it connects. Nothing starts logger_manager on AtomVM either: an application that wants logging at all has to start it, and one that does not has no handlers for this to be added to.

What it does not catch

Only what goes through logger. io:format/2, console:print/1 and Elixir's IO.puts/1 write straight to the console and never reach a handler, and a good deal of AtomVM code — including most examples — logs that way.

Elixir has no Logger on AtomVM at all: exavmlib does not ship one, so an Elixir application calls :logger directly and is caught by the same handler. There is nothing that can be done for IO.puts.

Messages must be charlists or reports

logger:do_log/4 accepts a list or a map and raises badarg on anything else, so a **binary message crashes the process that logged it** before any handler runs. That is upstream of this module and nothing here can soften it.

It catches Elixir code in particular, where the obvious call is the one that fails:

:logger.info("started") %% badarg, a binary :logger.info(~c"started") %% fine, a charlist :logger.info(#{event => started}) %% fine, a report

Erlang code is less exposed, since a double-quoted string is already a list there.

Finding the agent

The handler is configured before the agent exists, so it looks the agent up by registered name each time. Start the agent with register => Name to give it one. Until it is registered, and after it stops, events are dropped rather than queued: a device that cannot talk to NervesHub should not spend its memory remembering why.

Function Index

handler/0Equivalent to handler(#{level => info}).
handler/1The entry to add to logger_manager's handler list.
log/2Called by logger for each event this handler's level allows.
message/1Render a logger message as text.

Function Details

handler/0

handler() -> tuple()

Equivalent to handler(#{level => info}).

handler/1

handler(Config::map()) -> tuple()

The entry to add to logger_manager's handler list.

log/2

log(Event::map(), Config::map()) -> ok

Called by logger for each event this handler's level allows.

message/1

message(Other::term()) -> binary()

Render a logger message as text.

logger hands over one of three shapes, and a handler has to render all of them or lose whichever it does not. Public so that nh_console_h renders a line the same way this does.


Generated by EDoc