chore: optimized logging
This commit is contained in:
+75
-4
@@ -1,6 +1,29 @@
|
|||||||
import { fs } from 'zx';
|
import { fs } from 'zx';
|
||||||
import { path } from 'zx';
|
import { path } from 'zx';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strips ANSI escape codes from a string
|
||||||
|
* @param {string} str - String with ANSI codes
|
||||||
|
* @returns {string} Clean string without ANSI codes
|
||||||
|
*/
|
||||||
|
function stripAnsi(str) {
|
||||||
|
if (typeof str !== 'string') {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove ANSI escape sequences
|
||||||
|
// This regex matches all common ANSI codes including:
|
||||||
|
// - Colors (e.g., \x1b[32m)
|
||||||
|
// - Cursor movement (e.g., \x1b[1;1H)
|
||||||
|
// - Screen clearing (e.g., \x1b[0J)
|
||||||
|
// - 256-color codes (e.g., \x1b[38;2;244;197;66m)
|
||||||
|
return str.replace(
|
||||||
|
// eslint-disable-next-line no-control-regex
|
||||||
|
/\x1b\[[0-9;]*[a-zA-Z]|\x1b\][0-9];.*?\x07|\x1b\[[\d;]*m/g,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up logging to capture all stdout and stderr to a file
|
* Sets up logging to capture all stdout and stderr to a file
|
||||||
* @param {string} logFilePath - Path to the log file
|
* @param {string} logFilePath - Path to the log file
|
||||||
@@ -18,23 +41,63 @@ export async function setupLogging(logFilePath) {
|
|||||||
// Create write stream for the log file
|
// Create write stream for the log file
|
||||||
const logStream = fs.createWriteStream(absoluteLogPath, { flags: 'a' });
|
const logStream = fs.createWriteStream(absoluteLogPath, { flags: 'a' });
|
||||||
|
|
||||||
|
// Buffer for lines that might be overwritten (carriage return without newline)
|
||||||
|
let stdoutBuffer = '';
|
||||||
|
let stderrBuffer = '';
|
||||||
|
|
||||||
// Store original stdout/stderr write functions
|
// Store original stdout/stderr write functions
|
||||||
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
||||||
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
||||||
|
|
||||||
// Override stdout
|
// Override stdout
|
||||||
process.stdout.write = function(chunk, encoding, callback) {
|
process.stdout.write = function(chunk, encoding, callback) {
|
||||||
// Write to both original stdout and log file
|
// Write colorized output to terminal
|
||||||
originalStdoutWrite(chunk, encoding, callback);
|
originalStdoutWrite(chunk, encoding, callback);
|
||||||
logStream.write(chunk, encoding);
|
|
||||||
|
// Write plain text (without ANSI codes) to log file
|
||||||
|
const cleanChunk = stripAnsi(chunk.toString());
|
||||||
|
|
||||||
|
// Handle carriage returns - only log when we get a newline
|
||||||
|
if (cleanChunk.includes('\r') && !cleanChunk.includes('\n')) {
|
||||||
|
// Buffer this line - it will be overwritten in terminal
|
||||||
|
stdoutBuffer = cleanChunk.replace(/\r/g, '');
|
||||||
|
} else if (cleanChunk.includes('\n')) {
|
||||||
|
// Flush buffer if exists, then write the new line
|
||||||
|
if (stdoutBuffer) {
|
||||||
|
stdoutBuffer = ''; // Clear buffer without writing (it was overwritten)
|
||||||
|
}
|
||||||
|
logStream.write(cleanChunk);
|
||||||
|
} else {
|
||||||
|
// Normal write
|
||||||
|
logStream.write(cleanChunk);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Override stderr
|
// Override stderr
|
||||||
process.stderr.write = function(chunk, encoding, callback) {
|
process.stderr.write = function(chunk, encoding, callback) {
|
||||||
// Write to both original stderr and log file
|
// Write colorized output to terminal
|
||||||
originalStderrWrite(chunk, encoding, callback);
|
originalStderrWrite(chunk, encoding, callback);
|
||||||
logStream.write(chunk, encoding);
|
|
||||||
|
// Write plain text (without ANSI codes) to log file
|
||||||
|
const cleanChunk = stripAnsi(chunk.toString());
|
||||||
|
|
||||||
|
// Handle carriage returns - only log when we get a newline
|
||||||
|
if (cleanChunk.includes('\r') && !cleanChunk.includes('\n')) {
|
||||||
|
// Buffer this line - it will be overwritten in terminal
|
||||||
|
stderrBuffer = cleanChunk.replace(/\r/g, '');
|
||||||
|
} else if (cleanChunk.includes('\n')) {
|
||||||
|
// Flush buffer if exists, then write the new line
|
||||||
|
if (stderrBuffer) {
|
||||||
|
stderrBuffer = ''; // Clear buffer without writing (it was overwritten)
|
||||||
|
}
|
||||||
|
logStream.write(cleanChunk);
|
||||||
|
} else {
|
||||||
|
// Normal write
|
||||||
|
logStream.write(cleanChunk);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,6 +107,14 @@ export async function setupLogging(logFilePath) {
|
|||||||
process.stdout.write = originalStdoutWrite;
|
process.stdout.write = originalStdoutWrite;
|
||||||
process.stderr.write = originalStderrWrite;
|
process.stderr.write = originalStderrWrite;
|
||||||
|
|
||||||
|
// Flush any remaining buffers
|
||||||
|
if (stdoutBuffer) {
|
||||||
|
logStream.write(stdoutBuffer + '\n');
|
||||||
|
}
|
||||||
|
if (stderrBuffer) {
|
||||||
|
logStream.write(stderrBuffer + '\n');
|
||||||
|
}
|
||||||
|
|
||||||
// Close the log stream
|
// Close the log stream
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
logStream.end((err) => {
|
logStream.end((err) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user