chore: prune runtime slo reports
This commit is contained in:
@@ -367,6 +367,7 @@ async function writeMetadata() {
|
||||
' bash scripts/install-runtime-metrics-agent.sh',
|
||||
' node scripts/runtime-slo-report.mjs',
|
||||
' node scripts/runtime-slo-report.mjs --write-report',
|
||||
' node scripts/runtime-slo-report.mjs --write-report --prune --retention-days 30',
|
||||
' bash scripts/install-runtime-slo-report-agent.sh',
|
||||
' node scripts/runtime-worker-drain.mjs drain goosed-3',
|
||||
' node scripts/runtime-worker-drain.mjs undrain goosed-3',
|
||||
|
||||
@@ -11,6 +11,7 @@ GUI="gui/$(id -u)"
|
||||
HOUR="${MEMIND_RUNTIME_SLO_HOUR:-23}"
|
||||
MINUTE="${MEMIND_RUNTIME_SLO_MINUTE:-55}"
|
||||
REPORT_DIR="${MEMIND_RUNTIME_REPORT_DIR:-$ROOT/reports/runtime-slo}"
|
||||
RETENTION_DAYS="${MEMIND_RUNTIME_SLO_RETENTION_DAYS:-30}"
|
||||
|
||||
mkdir -p "$HOME/Library/LaunchAgents" "$HOME/Library/Logs" "$REPORT_DIR"
|
||||
|
||||
@@ -34,6 +35,9 @@ cat > "$PLIST" <<EOF
|
||||
<string>$NODE_BIN</string>
|
||||
<string>$SCRIPT</string>
|
||||
<string>--write-report</string>
|
||||
<string>--prune</string>
|
||||
<string>--retention-days</string>
|
||||
<string>$RETENTION_DAYS</string>
|
||||
<string>--report-dir</string>
|
||||
<string>$REPORT_DIR</string>
|
||||
</array>
|
||||
@@ -69,4 +73,5 @@ echo "installed $PLIST"
|
||||
echo "script: $SCRIPT"
|
||||
echo "schedule: daily ${HOUR}:${MINUTE}"
|
||||
echo "report_dir: $REPORT_DIR"
|
||||
echo "retention_days: $RETENTION_DAYS"
|
||||
echo "log: $LOG"
|
||||
|
||||
@@ -90,27 +90,85 @@ function uniquePaths(paths) {
|
||||
function parseArgs(argv) {
|
||||
const args = {
|
||||
writeReport: false,
|
||||
prune: false,
|
||||
retentionDays: Number(process.env.MEMIND_RUNTIME_SLO_RETENTION_DAYS || 30),
|
||||
reportDir: process.env.MEMIND_RUNTIME_REPORT_DIR || '',
|
||||
};
|
||||
for (let i = 0; i < argv.length; i += 1) {
|
||||
const item = argv[i];
|
||||
if (item === '--write-report') args.writeReport = true;
|
||||
else if (item === '--prune') args.prune = true;
|
||||
else if (item === '--retention-days') args.retentionDays = Number(argv[++i] ?? args.retentionDays);
|
||||
else if (item === '--report-dir') args.reportDir = String(argv[++i] ?? args.reportDir);
|
||||
else if (item === '--help' || item === '-h') args.help = true;
|
||||
}
|
||||
if (!Number.isFinite(args.retentionDays) || args.retentionDays < 1) {
|
||||
throw new Error(`Invalid --retention-days: ${args.retentionDays}`);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
console.log([
|
||||
'Usage:',
|
||||
' node scripts/runtime-slo-report.mjs [--write-report] [--report-dir <dir>]',
|
||||
' node scripts/runtime-slo-report.mjs [--write-report] [--prune] [--retention-days <days>] [--report-dir <dir>]',
|
||||
'',
|
||||
'Default behavior is read-only and writes nothing.',
|
||||
'--write-report writes JSON and Markdown snapshots to an operations report directory.',
|
||||
'--prune deletes old .json/.md snapshots in the report directory only.',
|
||||
].join('\n'));
|
||||
}
|
||||
|
||||
function pruneReportDir(reportDir, retentionDays) {
|
||||
const resolvedDir = path.resolve(reportDir);
|
||||
const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000;
|
||||
const result = {
|
||||
enabled: true,
|
||||
reportDir: resolvedDir,
|
||||
retentionDays,
|
||||
deleted: [],
|
||||
kept: 0,
|
||||
skipped: 0,
|
||||
errors: [],
|
||||
};
|
||||
let entries = [];
|
||||
try {
|
||||
entries = fs.readdirSync(resolvedDir, { withFileTypes: true });
|
||||
} catch (err) {
|
||||
result.errors.push(err instanceof Error ? err.message : String(err));
|
||||
return result;
|
||||
}
|
||||
for (const entry of entries) {
|
||||
if (!entry.isFile()) {
|
||||
result.skipped += 1;
|
||||
continue;
|
||||
}
|
||||
if (!entry.name.endsWith('.json') && !entry.name.endsWith('.md')) {
|
||||
result.skipped += 1;
|
||||
continue;
|
||||
}
|
||||
const full = path.join(resolvedDir, entry.name);
|
||||
let stat = null;
|
||||
try {
|
||||
stat = fs.statSync(full);
|
||||
} catch (err) {
|
||||
result.errors.push(`${entry.name}: ${err instanceof Error ? err.message : String(err)}`);
|
||||
continue;
|
||||
}
|
||||
if (stat.mtimeMs >= cutoffMs) {
|
||||
result.kept += 1;
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
fs.unlinkSync(full);
|
||||
result.deleted.push(entry.name);
|
||||
} catch (err) {
|
||||
result.errors.push(`${entry.name}: ${err instanceof Error ? err.message : String(err)}`);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function tableCountQueries() {
|
||||
return [
|
||||
['h5_users', 'users'],
|
||||
@@ -257,6 +315,17 @@ if (runtimeSummary?.toolQueue?.inFlight > runtimeSummary?.toolQueue?.maxConcurre
|
||||
failures.push('tool_queue_concurrency_exceeded');
|
||||
}
|
||||
|
||||
const reportDir = path.resolve(args.reportDir || path.join(appRoot, 'reports', 'runtime-slo'));
|
||||
if (args.writeReport || args.prune) {
|
||||
fs.mkdirSync(reportDir, { recursive: true });
|
||||
}
|
||||
const reportPrune = args.prune
|
||||
? pruneReportDir(reportDir, args.retentionDays)
|
||||
: { enabled: false, reportDir, retentionDays: args.retentionDays };
|
||||
for (const error of reportPrune.errors ?? []) {
|
||||
failures.push(`report_prune_error:${error}`);
|
||||
}
|
||||
|
||||
const report = {
|
||||
ok: failures.length === 0,
|
||||
checkedAt: new Date().toISOString(),
|
||||
@@ -274,7 +343,9 @@ const report = {
|
||||
mindSpace: false,
|
||||
redis: false,
|
||||
report: Boolean(args.writeReport),
|
||||
reportPrune: Boolean(args.prune),
|
||||
},
|
||||
reportPrune,
|
||||
};
|
||||
|
||||
function markdownReport(payload) {
|
||||
@@ -319,13 +390,17 @@ function markdownReport(payload) {
|
||||
JSON.stringify(payload.writes, null, 2),
|
||||
'```',
|
||||
'',
|
||||
'## Report Prune',
|
||||
'',
|
||||
'```json',
|
||||
JSON.stringify(payload.reportPrune ?? null, null, 2),
|
||||
'```',
|
||||
'',
|
||||
);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
if (args.writeReport) {
|
||||
const reportDir = path.resolve(args.reportDir || path.join(appRoot, 'reports', 'runtime-slo'));
|
||||
fs.mkdirSync(reportDir, { recursive: true });
|
||||
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
report.reportFiles = {
|
||||
json: path.join(reportDir, `${stamp}.json`),
|
||||
|
||||
Reference in New Issue
Block a user