Skip to content

fix(doltserver): rotate dolt-server.log at startup to cap size#3161

Merged
maphew merged 1 commit into
gastownhall:mainfrom
quad341:fix/dolt-server-log-rotation
Apr 11, 2026
Merged

fix(doltserver): rotate dolt-server.log at startup to cap size#3161
maphew merged 1 commit into
gastownhall:mainfrom
quad341:fix/dolt-server-log-rotation

Conversation

@quad341

@quad341 quad341 commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Problem

`dolt-server.log` grows unbounded with no rotation. Field report: 379 MB at one site (with verbose connection logging — even after that's reduced, the log still needs a hard cap).

Fix

Startup-only rotation. At each `Start()`, if `dolt-server.log` exceeds the threshold, rotate it to `dolt-server.log.1` (overwriting any previous rotated file) and open a fresh log.

  • Default cap: 50 MB
  • Override via `BEADS_DOLT_LOG_MAX_BYTES` env var (bytes)
  • Set to 0 or negative to disable rotation entirely
  • Single-generation retention (only `.log.1` is kept)
  • Rotation failures are logged but non-fatal — the server always proceeds to open the log, preferring a running server with an oversized log over a startup abort

Why startup-only: true runtime rotation would require either a streaming goroutine owning the dolt server stdout/stderr pipe (significant restructuring) or copy-truncate (which races with the child's append writes). Startup rotation is sufficient for the field report's needs and documented at the top of `logrotate.go`.

Tests

  • `TestRotateLogIfOversized_RotatesWhenOverThreshold`
  • `TestRotateLogIfOversized_LeavesSmallFileAlone`
  • `TestRotateLogIfOversized_LeavesExactThresholdAlone` (boundary)
  • `TestRotateLogIfOversized_OverwritesExistingRotated`
  • `TestRotateLogIfOversized_MissingPrimaryIsNoop`
  • `TestRotateLogIfOversized_DisabledWhenMaxBytesZero`
  • `TestMaybeRotateLog_EndToEnd`
  • `TestMaxLogBytes_EnvOverride` (default / valid / invalid / zero)

All passing. `go vet` clean. `gofmt` clean.

The dolt sql-server's stdout/stderr is captured directly to
.beads/dolt-server.log with no rotation, leading to field reports of
the file reaching 379 MB. Since dolt owns the file descriptor, we
cannot interpose a size-limiting writer at runtime without a streaming
goroutine, so implement the simplest fix that works: a startup-time
size check that renames the log to .log.1 (overwriting any previous
rotation) when it exceeds a configurable ceiling, defaulting to 50 MB
and overridable via BEADS_DOLT_LOG_MAX_BYTES.

Rotation is best-effort and never blocks startup: failures are logged
via debug.Logf and the server proceeds to open the existing log. This
is startup-only; a long-running server whose log grows past the cap
mid-run will not be rotated until the next restart.

Tests cover the rotate/leave-alone/overwrite/missing/disabled paths,
the env-var override parsing, and the higher-level maybeRotateLog
wrapper against the production logPath helper.

@maphew maphew left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @quad341 — nice defensive implementation. Best-effort rotation that never blocks startup, single-generation retention is pragmatic, env var escape hatch for the threshold. 8 test cases cover the edges well.

The Windows os.Rename / MoveFileEx comment is a nice touch.

Approved.

🤖 Reviewed with Claude Code

@maphew maphew merged commit 9fa62ee into gastownhall:main Apr 11, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants