Minga.LoggerHandler (Minga v0.1.0)

Copy Markdown View Source

Custom :logger handler that routes log messages to the *Messages* buffer.

When the TUI is active, the default console handler writes to stderr which corrupts the terminal display. This module:

  1. Replaces the default :logger_std_h handler with a file-based one (writes to ~/.local/share/minga/minga.log)
  2. Adds a custom handler that forwards messages to the *Messages* buffer via Minga.Events broadcasts
  3. Redirects the :standard_error IO device to the same log file so that raw BEAM warnings (e.g. IO.warn/2) don't corrupt the TUI either

Crash recovery

When the Editor GenServer is down (e.g., mid-restart after a crash), log messages are buffered in an ETS table owned by the Application supervisor. The Editor calls flush_buffer/0 during init/1 to replay them into *Messages*. The buffer is capped at @max_buffered entries to prevent unbounded growth during crash loops.

Installation

Called from the Editor's init/1 after the *Messages* buffer is ready:

Minga.LoggerHandler.install()

The handler stays installed across Editor restarts so that crash reports are captured in the ETS buffer. uninstall/0 is called only during clean application shutdown (Application.stop/1).

install/0 is idempotent: safe to call on every Editor init even when the handlers are already in place from a previous Editor lifetime.

Summary

Functions

Creates the ETS buffer table if it doesn't already exist.

Flush buffered log messages into the Editor.

Install the file handler and stderr redirect for TUI mode.

Install just the custom :log_message-broadcast handler.

Restore the default console handler and original stderr device.

Functions

ensure_buffer_table()

@spec ensure_buffer_table() :: :ok

Creates the ETS buffer table if it doesn't already exist.

Called from Minga.Application.start/2 so the table is owned by the supervisor process and survives Editor crashes.

flush_buffer()

@spec flush_buffer() :: [{String.t(), atom()}]

Flush buffered log messages into the Editor.

Called from the Editor's init/1 after *Messages* is ready. Replays all buffered messages in order, then clears the buffer. Messages that arrived while the Editor was down (e.g., supervisor crash reports) will appear in *Messages* as if they'd been logged normally.

install()

@spec install() :: String.t()

Install the file handler and stderr redirect for TUI mode.

Idempotent: skips any handler or redirect that is already in place. Safe to call on every Editor init, including restarts after a crash where the handlers survived because terminate/2 no longer tears them down.

Also ensures the :log_message broadcast handler is installed (no-op if the application boot already added it).

Returns the log file path for display in *Messages*.

install_messages_handler()

@spec install_messages_handler() :: :ok

Install just the custom :log_message-broadcast handler.

Called from Minga.Application.start/2 and Minga.Runtime.start/1 so the broadcast path is live before any editor (or the gateway, or the singleton *Messages* buffer owner) is up. Idempotent.

Unlike install/0, this does not replace the default :logger handler and does not redirect stderr — those are TUI-only concerns and stay in the editor's init path so headless and mix invocations keep stdout/stderr output.

uninstall()

@spec uninstall() :: :ok

Restore the default console handler and original stderr device.