logwriter

package
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package logwriter provides atomic NDJSON event writing with optional size-based rotation for workspace logs and no rotation for per-slot logs.

Atomicity: each Append opens the file with O_APPEND|O_CREATE|O_WRONLY and writes a single newline-terminated line. POSIX guarantees that writes no larger than PIPE_BUF (512 bytes minimum; 4096+ on Linux and macOS) are atomic on append-only file descriptors, so concurrent slot processes cannot interleave lines for the small payloads we emit (~150–300 bytes).

Rotation (workspace log only): on every Append, the file is stat-ed; if its size exceeds maxSize the numbered series is shifted (.log.1→.log.2, etc.), the current .log is renamed to .log.1, and a fresh .log is opened. The oldest numbered file is removed when the count exceeds maxFiles.

Single-writer assumed for v1 (one process appending per file at a time). Concurrent-process safety relies on O_APPEND atomicity but NOT on rotation being race-free — do not call Append concurrently on the same Writer.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendOnce

func AppendOnce(path string, e Event) error

AppendOnce writes one event line to path without rotation. Use this for per-slot logs and other call sites that don't carry rotation state across calls — it skips the Writer allocation entirely. The parent directory is created if absent.

Atomicity: opens with O_APPEND|O_CREATE|O_WRONLY and writes a single newline-terminated line. POSIX guarantees writes ≤PIPE_BUF are atomic.

func SlotLogPath

func SlotLogPath(slotDir, slot string) string

SlotLogPath returns the per-slot log path under <slotDir>/log. Per-slot logs are bounded by slot lifetime and never rotate, so callers should use AppendOnce(SlotLogPath(slotDir, slot), event) — no Writer needed.

Types

type Event

type Event struct {
	Timestamp time.Time              `json:"-"`
	Slot      string                 `json:"-"` // optional; omitted when empty
	Event     EventType              `json:"-"`
	Fields    map[string]interface{} `json:"-"`
}

Event is one NDJSON row. MarshalJSON merges Fields into the top-level object so the on-disk row is flat: {"ts":"...","event":"...","slot":"...",...fields}. json:"-" tags keep the zero-value encoding path from double-emitting keys.

func (Event) MarshalJSON

func (e Event) MarshalJSON() ([]byte, error)

MarshalJSON emits a single flat JSON object. Required keys are always present; "slot" is omitted when empty; entries from Fields are merged at the top level. If a Fields key collides with a reserved key ("ts", "event", "slot") it is silently dropped — callers must not reuse reserved names.

type EventType

type EventType string

EventType is one entry in the closed catalog of slot/workspace event kinds. Each constant matches the string written to the on-disk NDJSON "event" field so operator tooling can grep without understanding Go constants.

const (
	// EventJoin is emitted when a slot successfully acquires a session.
	EventJoin EventType = "join"

	// EventCommit is emitted when a slot's commit completes without error.
	EventCommit EventType = "commit"

	// EventCommitError is emitted when a slot's commit fails.
	EventCommitError EventType = "commit_error"

	// EventRenew is emitted when a slot renews its lease.
	EventRenew EventType = "renew"

	// EventClose is emitted when a slot closes and releases its session.
	EventClose EventType = "close"

	// EventDispatched is emitted when the workspace dispatches a new plan.
	EventDispatched EventType = "dispatched"

	// EventError is emitted for any unexpected error worth recording.
	EventError EventType = "error"
)

type Writer

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

Writer writes NDJSON event lines to a single file, optionally rotating on size. Zero value is not valid; use Open or OpenSlot.

func Open

func Open(path string) *Writer

Open returns a Writer for the workspace log at path. Defaults: 10 MiB maxSize, 5 backup files. Overridable via BONES_LOG_MAX_SIZE (bytes) and BONES_LOG_MAX_FILES.

func OpenSlot

func OpenSlot(slotDir, slot string) *Writer

OpenSlot returns a Writer for a per-slot log at <slotDir>/log. Rotation is disabled (maxSize=0) because per-slot logs are bounded by slot lifetime and must not rotate under the slot process's feet.

func (*Writer) Append

func (w *Writer) Append(e Event) error

Append writes one event line atomically to the log file. If maxSize > 0 and the file has grown beyond it, rotation is performed first. The parent directory is created if absent.

Jump to

Keyboard shortcuts

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