logging

package
v0.11.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 23, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package logging provides structured logging for the Entire CLI using slog.

A Logger owns one log file. The entry point builds one, puts it in the context with WithLogger, and closes it from there; nothing here is process-global.

Index

Constants

View Source
const (
	LogFileName = "entire.log"
	LogName     = LogsName + "/" + LogFileName
)

LogFileName is the log file's basename, and LogName addresses it from the .entire root — the pair readers (doctor logs, trace) use so they open the same file this package writes without re-joining LogsDir themselves.

View Source
const LogLevelEnvVar = "ENTIRE_LOG_LEVEL"

LogLevelEnvVar is the environment variable that controls log level.

View Source
const LogsDir = ".entire/logs"

LogsDir is the directory where log files are stored (relative to repo root). It is the spelling for messages, git paths, and doctor output; the writer below addresses the same directory as LogsName inside the .entire root.

View Source
const LogsName = "logs"

LogsName is LogsDir relative to the .entire root, which is the coordinate Config.Root resolves names in.

Variables

This section is empty.

Functions

func Debug

func Debug(ctx context.Context, msg string, attrs ...any)

Debug logs at DEBUG level with context values automatically extracted.

func Error

func Error(ctx context.Context, msg string, attrs ...any)

Error logs at ERROR level with context values automatically extracted.

func Info

func Info(ctx context.Context, msg string, attrs ...any)

Info logs at INFO level with context values automatically extracted.

func ParseLevel added in v0.10.3

func ParseLevel(s string) (level slog.Level, ok bool)

ParseLevel maps a log level name to a slog.Level. ok is false for an unrecognized non-empty name, so the caller can warn about a typo. An empty name is INFO and reports ok.

func SessionLoggerFromContext added in v0.10.3

func SessionLoggerFromContext(ctx context.Context) *slog.Logger

SessionLoggerFromContext returns the context's logger stamped with its session ID, for packages that hold an injected *slog.Logger and call it without a context (redact) — those calls never reach log(), so they cannot pick the attribute up themselves.

Only the session is stamped. redact tags its own lines with component=redaction, and slog does not dedupe attrs, so adding component here would emit the key twice.

func Warn

func Warn(ctx context.Context, msg string, attrs ...any)

Warn logs at WARN level with context values automatically extracted.

func WithAgent

func WithAgent(ctx context.Context, agentName types.AgentName) context.Context

WithAgent adds an agent name to the context. Agent names identify the AI agent generating activity (e.g., "claude-code", "cursor", "aider").

func WithComponent

func WithComponent(ctx context.Context, component string) context.Context

WithComponent adds a component name to the context. Component names help identify the subsystem generating logs (e.g., "hooks", "strategy", "session").

func WithLogger added in v0.10.3

func WithLogger(ctx context.Context, l *Logger) context.Context

WithLogger attaches a Logger to the context. The exit point closes it by reading it back out — the logger has no other owner — so don't stash it anywhere that outlives the command.

func WithSessionID added in v0.10.3

func WithSessionID(ctx context.Context, sessionID string) context.Context

WithSessionID adds a session ID to the context, so lines logged under it are filterable by session. Re-stamping a derived context shadows the outer session for that scope only.

It deliberately does not validate: this is an slog attribute, not a path, so guarding traversal belongs where the ID is resolved from the filesystem.

Types

type Config added in v0.10.3

type Config struct {
	// Root resolves the directory tree Dir lives in, and is called on the first
	// line actually written — never by New. A function rather than an *os.Root
	// because the caller's root is .entire, which must not be created just
	// because a command started: a command that logs nothing must leave an
	// untouched repo untouched. Required rather than defaulted: only the caller
	// knows whether writing there is allowed.
	Root func() (*os.Root, error)

	// Dir is the log directory's name within Root, created if absent.
	Dir string

	// Level is the minimum level to emit; the zero value is slog.LevelInfo.
	Level slog.Level
}

type Logger added in v0.10.3

type Logger struct {
	// contains filtered or unexported fields
}

Logger is safe for concurrent use: slog handlers may be called from several goroutines and bufio.Writer is not goroutine-safe, so mu serializes every write and Close. Writes after Close are dropped — losing a log line must never surface as an error in the caller.

The file is created on first write, not by New, so a command that logs nothing (shell completion, version, help) neither pays for opening it nor leaves an empty entire.log behind.

func LoggerFromContext added in v0.10.3

func LoggerFromContext(ctx context.Context) *Logger

LoggerFromContext returns the Logger attached by WithLogger, or nil when logging is not file-backed. Its methods are nil-safe, so a nil result can be closed or asked for its Slog without a guard.

func New added in v0.10.3

func New(cfg Config) (*Logger, error)

New returns a Logger that writes JSON to cfg.Dir/entire.log, creating both on the first line actually written. It never falls back to stderr: an injected logger that wrote to the terminal would splash operational lines over the user's output.

A directory that cannot be created or opened is not reported here — by then lines have already been dropped, which is the same outcome as any other write failure and must never surface as an error in the caller. Two things can still surface it: Close returns it, and EnsureOpen asks for it up front, which is how `entire doctor` reports a log sink that is silently swallowing every diagnostic.

func (*Logger) Close added in v0.10.3

func (l *Logger) Close() error

Close flushes the buffer and closes the log file, and reports a failure to open it if one happened. Idempotent, and safe to call concurrently with logging: later writes are dropped rather than reopening the file.

func (*Logger) EnsureOpen added in v0.10.3

func (l *Logger) EnsureOpen() error

EnsureOpen opens the log file now instead of on the first line written, and reports a directory it cannot use.

It exists so the failure has one caller that looks: the deferred open drops the line and returns nil, so an unwritable .entire/logs makes every diagnostic vanish with no exit code, no message, and an empty log to grep — indistinguishable from "Entire never ran". `entire doctor` calls this to name it. Idempotent, and nil-safe so a caller need not know whether the entry point installed a logger.

It creates the directory and file, which is what the next logged line would have done anyway. That does cost the empty-file-free property New buys for commands that log nothing, so call it from commands that are diagnosing, not from hot paths.

func (*Logger) Slog added in v0.10.3

func (l *Logger) Slog() *slog.Logger

Slog returns the underlying *slog.Logger, for packages that take one by injection and should not depend on this type. Nil-safe.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL