Skip to content

Logging

Eshan Roy edited this page Jun 16, 2026 · 2 revisions

Logging

M31A uses Go's structured logging (log/slog) with JSON output, file rotation, and configurable log levels.

Source: internal/log/log.go

Logger Setup

func NewLogger(version string) (*slog.Logger, func(), error)

The logger is initialized in main.go before any other component:

  1. Resolve log directory: ~/.m31a/
  2. Rotate old log files
  3. Open log file in append mode
  4. Create handler (JSON or text format)
  5. Return logger and cleanup function

Log File

Property Value
Path ~/.m31a/m31a.log
Format JSON (default) or text
Append mode Yes
Permission 0644

Log Rotation

Daily rotation based on file modification time:

  1. On startup, check if m31a.log was last modified before today
  2. Rename to m31a.log.YYYY-MM-DD
  3. Remove rotated files older than 7 days

Rotation failure is non-fatal -- the logger continues in append-only mode.

Log Level

Configured via M31A_LOG_LEVEL environment variable:

Level Value
debug Verbose debugging output
info Standard operational messages (default)
warn Warnings and recoverable errors
error Errors only

Log Format

Configured via M31A_LOG_FORMAT environment variable:

Format Description
json JSON lines (default) -- machine-parseable
text Human-readable key=value format

Usage

The logger is set as the default slog logger:

slog.SetDefault(logger)

Components use slog.Info(), slog.Warn(), slog.Error(), and slog.Debug() throughout:

slog.Info("M31A starting", "version", Version, "go_version", runtime.Version())
slog.Warn("keychain initialization failed", "error", kcErr)
slog.Error("failed to load config", "error", err)
slog.Debug("tool executed", "tool", call.Name, "duration_ms", elapsed)

Viewing Logs

# Show recent log entries
/log              # default 20 lines
/log 50           # show 50 lines

# Direct file access
cat ~/.m31a/m31a.log
tail -f ~/.m31a/m31a.log

Clone this wiki locally