Files

94 lines
2.0 KiB
JavaScript

import fs from 'fs';
const DEFAULT_TAIL_LINES = 200;
const LOG_ROTATE_MAX_BYTES = 10 * 1024 * 1024;
const LOG_ROTATE_KEEP = 5;
function rotateLogFile(logPath) {
try {
const stats = fs.statSync(logPath);
if (stats.size < LOG_ROTATE_MAX_BYTES) {
return;
}
} catch {
return;
}
for (let i = LOG_ROTATE_KEEP - 1; i >= 1; i--) {
const src = `${logPath}.${i}`;
const dst = `${logPath}.${i + 1}`;
if (fs.existsSync(src)) {
try {
fs.renameSync(src, dst);
} catch {
}
}
}
try {
if (fs.existsSync(logPath)) {
fs.renameSync(logPath, `${logPath}.1`);
}
} catch {
}
}
function readTailLines(filePath, lineCount = DEFAULT_TAIL_LINES) {
if (!fs.existsSync(filePath)) {
return [];
}
const raw = fs.readFileSync(filePath, 'utf8');
const lines = raw.split(/\r?\n/);
if (lines.length && lines[lines.length - 1] === '') {
lines.pop();
}
return lines.slice(Math.max(0, lines.length - lineCount));
}
function followFile(filePath, onLine) {
let position = 0;
try {
position = fs.statSync(filePath).size;
} catch {
position = 0;
}
let remainder = '';
const interval = setInterval(() => {
try {
const stats = fs.statSync(filePath);
if (stats.size < position) {
position = 0;
}
if (stats.size === position) {
return;
}
const fd = fs.openSync(filePath, 'r');
try {
const length = stats.size - position;
const buffer = Buffer.alloc(length);
fs.readSync(fd, buffer, 0, length, position);
position = stats.size;
const chunk = remainder + buffer.toString('utf8');
const parts = chunk.split(/\r?\n/);
remainder = parts.pop() || '';
for (const line of parts) {
onLine(line);
}
} finally {
fs.closeSync(fd);
}
} catch {
}
}, 400);
return () => {
clearInterval(interval);
};
}
export { rotateLogFile, readTailLines, followFile };