Help us shape the future of Go! Take the 2026 Go Developer Survey

logging

package
v0.57.0 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: AGPL-3.0 Imports: 23 Imported by: 0

Documentation

Overview

Package logging sets up ogcode's process-wide slog logger: a size-rotated, owner-only log file that receives everything at the configured level, and a terminal that sees only what the user must act on (errors, by default).

Configuration is by environment, like the rest of ogcode's runtime knobs:

OGCODE_LOG_LEVEL        debug | info (default) | warn | error — the file's threshold
OGCODE_LOG_FORMAT       text (default) | json — the file's format
OGCODE_LOG_CONSOLE      off | error (default) | warn | info | debug — the terminal's threshold
OGCODE_LOG_DIR          root for log files (default ~/.ogcode/logs; each project gets a folder inside)
OGCODE_LOG_MAX_SIZE_MB  rotate the file past this size (default 10)
OGCODE_LOG_MAX_FILES    rotated files kept (default 5)
OGCODE_LOG_MAX_AGE_DAYS rotated files older than this are deleted (default 14, 0 = keep)
OGCODE_LOG_COMPRESS     gzip rotated files (default on)

Records can also be shipped to PostHog Logs, off by default:

OGCODE_POSTHOG_LOGS       on | off (default) — ship records to PostHog Logs
OGCODE_POSTHOG_LOGS_LEVEL severity floor for shipped records (default warn)

Shipping is opt-in and honours DO_NOT_TRACK; records are redacted before they leave the process.

Index

Constants

View Source
const (
	DefaultMaxSizeMB  = 10
	DefaultMaxFiles   = 5
	DefaultMaxAgeDays = 14
)

Defaults for a log file's size and retention. The worst case on disk is MaxSizeMB × (MaxFiles + 1), before compression.

View Source
const DefaultRemoteLevel = slog.LevelWarn

DefaultRemoteLevel is the floor below which records are never shipped to PostHog: a debug log file is for the machine it runs on, and shipping debug lines would be both noisy and a surprise. The file's level raises or lowers nothing here — OGCODE_POSTHOG_LOGS_LEVEL is the only remote knob.

View Source
const LevelOff = slog.Level(math.MaxInt32)

LevelOff is a threshold no record reaches: the sink is silent.

View Source
const Redacted = "[REDACTED]"

Redacted replaces a secret in a log line.

Variables

This section is empty.

Functions

func ProjectDir

func ProjectDir(root, dir string) string

ProjectDir is the log directory for the project at dir: one folder per project under root, so projects running side by side never share a file. The folder is named after the project, for a person looking for it, with a short hash of its path appended, so two checkouts that are both called "app" stay apart. The path is canonicalized the way portmap keys a project (absolute, symlinks resolved, cleaned), so one project has one log folder however its path was spelled.

func Root

func Root(home string) string

Root is the directory every ogcode log lives under: $OGCODE_LOG_DIR when set, otherwise ~/.ogcode/logs, beside the global config database. Logs never live inside a project, where they could be committed, indexed, or read back by the agent as if they were project content.

func Scrub

func Scrub(s string) string

Scrub removes secrets from free text.

Types

type Logger

type Logger struct {
	*slog.Logger

	// ConsoleFallback reports that the log file could not be opened and the
	// terminal is carrying its records. Set once by New.
	ConsoleFallback bool
	// contains filtered or unexported fields
}

Logger is a configured process logger and the file behind it.

func New

func New(o Options) *Logger

New builds a logger from o. It never fails: if the file cannot be opened (read-only disk, no permission) the terminal takes over at the file's level, and says why, so nothing is lost silently.

func Setup

func Setup(o Options) *Logger

Setup builds a logger from o and installs it as the process default, which also routes the standard library's log package (net/http's server errors, for one) through it.

func (*Logger) Close

func (l *Logger) Close() error

Close stops the PostHog sink (flushing any buffered records), closes the file and waits for pending rotation housekeeping.

func (*Logger) Path

func (l *Logger) Path() string

Path is the active log file, or "" when there is none.

func (*Logger) Started

func (l *Logger) Started(ctx context.Context, command, dir, version string, o Options)

Started logs the line that opens a process's section of the log: which process, in which directory, which version, under which settings. It makes a file shared by restarts (and, rarely, by concurrent processes) readable, and names the project a per-project log folder belongs to.

type Options

type Options struct {
	// Dir and Name place the log file. Empty Name means no file: the terminal
	// is the only sink (used by commands like `version` that do no work worth
	// keeping and must not create .ogcode/ wherever they are run).
	Dir  string
	Name string

	Level  slog.Level // file threshold
	Format string     // "text" or "json"; the file's format

	Console slog.Level // terminal threshold; LevelOff silences it

	Rotate RotateOptions

	// Stderr is the terminal sink. Nil means os.Stderr.
	Stderr io.Writer
}

Options configure the process logger.

func FromEnv

func FromEnv(dir, name string) Options

FromEnv reads the OGCODE_LOG_* variables over the defaults. dir and name are where the calling command keeps its log (see Root and ProjectDir, which apply OGCODE_LOG_DIR).

type RotateOptions

type RotateOptions struct {
	// MaxSize is the size in bytes at which the active file is rotated.
	MaxSize int64
	// MaxBackups is how many rotated files are kept; 0 keeps them all.
	MaxBackups int
	// MaxAge removes rotated files older than this; 0 keeps them regardless.
	MaxAge time.Duration
	// Compress gzips rotated files.
	Compress bool
}

RotateOptions bound how much disk a log file may take.

type RotatingFile

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

RotatingFile is an io.Writer that appends to a log file and, when the file would grow past MaxSize, renames it to <stem>-<UTC stamp><ext> and starts a fresh one. Pruning and compressing the rotated files happens off the write path, in one background goroutine.

Files are created 0600 and a directory it creates 0700: log lines carry paths, prompts and provider errors, which are the user's alone to read.

Several processes may append to the same file (two servers or two `ogcode run` in one project). Appends are O_APPEND, so records never interleave mid-line; each writer re-checks the path every followInterval, so after one process rotates, the others follow it to the new file within a second rather than writing on into the backup — and the size each one rotates on includes the others' writes.

func OpenRotating

func OpenRotating(path string, opts RotateOptions) (*RotatingFile, error)

OpenRotating opens (creating if needed) the log file at path.

func (*RotatingFile) Close

func (r *RotatingFile) Close() error

Close closes the file and waits for any pruning or compression in flight.

func (*RotatingFile) Path

func (r *RotatingFile) Path() string

Path is the active log file.

func (*RotatingFile) Write

func (r *RotatingFile) Write(p []byte) (int, error)

Write appends p, rotating first when p would take the file past MaxSize. A single record larger than MaxSize is still written whole, to a fresh file.

Jump to

Keyboard shortcuts

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