fix(cli): prevent unbounded log file growth with size-based rotation (#8136)

* fix(cli): prevent unbounded log file growth with size-based rotation

Fix two issues causing log files to grow to 50+ GB:

1. Server middleware leaked a "started" log line for skipped endpoints
   because log.time() was called unconditionally — only timer.stop()
   was gated by the skipLogging flag. Restructure to early-return for
   skipped paths so no logging occurs at all.

2. Log files had no size limit within a session. A long-running
   kilo serve process (e.g. VS Code extension) would write a single
   file indefinitely. Add rotating-file-stream (50 MB, maxFiles: 1)
   to cap log file size automatically.

* fix(cli): address review feedback on log rotation

- Revert server.ts changes (handled separately in #8141)
- Add error/warning event handlers on rotating-file-stream
- Increase maxFiles from 1 to 3 for better debug headroom
- Set explicit history file path to avoid .txt side-effect

* fix(cli): revert maxFiles back to 1

maxFiles: 1 is sufficient — we only need to cap disk usage, not retain
old rotated fragments. The existing cleanup() handles session-level
file retention separately.

* fix(cli): set maxFiles to 10 for log rotation
This commit is contained in:
Marius
2026-04-02 11:54:49 +02:00
committed by GitHub
parent e09040fe45
commit 3a86e15189
3 changed files with 23 additions and 9 deletions
+3
View File
@@ -401,6 +401,7 @@
"opentui-spinner": "0.0.6",
"partial-json": "0.1.7",
"remeda": "catalog:",
"rotating-file-stream": "3.2.9",
"simple-git": "3.31.1",
"solid-js": "catalog:",
"strip-ansi": "7.1.2",
@@ -3797,6 +3798,8 @@
"rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="],
"rotating-file-stream": ["rotating-file-stream@3.2.9", "", {}, "sha512-i9i0KkHh12ryl4xtELg+0gyoFre2PJ9RcQQLzquWsiqygyYsrZLckrqqYrthhnJZGZb4g+KUHtcoWYVq34gaug=="],
"roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
+1
View File
@@ -126,6 +126,7 @@
"opentui-spinner": "0.0.6",
"partial-json": "0.1.7",
"remeda": "catalog:",
"rotating-file-stream": "3.2.9",
"simple-git": "3.31.1",
"solid-js": "catalog:",
"strip-ansi": "7.1.2",
+19 -9
View File
@@ -1,9 +1,9 @@
import path from "path"
import fs from "fs/promises"
import { createWriteStream } from "fs"
import { Global } from "../global"
import z from "zod"
import { Glob } from "./glob"
import { createStream } from "rotating-file-stream" // kilocode_change
export namespace Log {
export const Level = z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).meta({ ref: "LogLevel", description: "Log level" })
@@ -66,15 +66,25 @@ export namespace Log {
options.dev ? "dev.log" : new Date().toISOString().split(".")[0].replace(/:/g, "") + ".log",
)
await fs.truncate(logpath).catch(() => {})
const stream = createWriteStream(logpath, { flags: "a" })
write = async (msg: any) => {
return new Promise((resolve, reject) => {
stream.write(msg, (err) => {
if (err) reject(err)
else resolve(msg.length)
})
})
// kilocode_change start - use rotating-file-stream to cap log files at 50 MB
const dir = path.dirname(logpath)
const stream = createStream(path.basename(logpath), {
size: "50M",
maxFiles: 10,
history: path.join(dir, ".log-history"),
path: dir,
})
stream.on("error", (err: Error) => {
process.stderr.write("log stream error: " + err.message + "\n")
})
stream.on("warning", (err: Error) => {
process.stderr.write("log stream warning: " + err.message + "\n")
})
write = (msg: any) => {
stream.write(msg)
return msg.length
}
// kilocode_change end
}
async function cleanup(dir: string) {