logs: use stream.destroy() instead of custom hooks

This commit is contained in:
Girish Ramakrishnan
2024-02-24 17:18:38 +01:00
parent 0e83658aa3
commit 13e62bc738
10 changed files with 19 additions and 10 deletions

View File

@@ -2050,7 +2050,7 @@ async function getLogs(app, options) {
const cp = logs.tail(logPaths, { lines: options.lines, follow: options.follow });
const logStream = new logs.LogStream({ format: options.format || 'json', source: appId });
logStream.close = cp.terminate; // closing stream kills the child process
logStream.on('close', () => cp.terminate()); // the caller has to call destroy() on logStream. destroy() of Transform emits 'close'
cp.stdout.pipe(logStream);

View File

@@ -60,7 +60,7 @@ function tail(filePaths, options) {
const args = [ LOGTAIL_CMD, '--lines=' + lines ];
if (options.follow) args.push('--follow');
return shell.sudo('tail', args.concat(filePaths), { streamStdout: true }, function (e) { console.log(e); });
return shell.sudo('tail', args.concat(filePaths), { streamStdout: true }, () => {});
}
function journalctl(unit, options) {

View File

@@ -688,7 +688,7 @@ async function getLogStream(req, res, next) {
'Access-Control-Allow-Origin': '*'
});
res.write('retry: 3000\n');
res.on('close', logStream.close);
res.on('close', () => logStream.destroy());
logStream.on('data', function (data) {
const obj = JSON.parse(data);
const sse = `data: ${JSON.stringify(obj)}\n\n`;
@@ -719,6 +719,7 @@ async function getLogs(req, res, next) {
'Cache-Control': 'no-cache',
'X-Accel-Buffering': 'no' // disable nginx buffering
});
res.on('close', () => logStream.destroy());
logStream.pipe(res);
}

View File

@@ -83,6 +83,7 @@ async function getLogs(req, res, next) {
'Cache-Control': 'no-cache',
'X-Accel-Buffering': 'no' // disable nginx buffering
});
res.on('close', () => logStream.destroy());
logStream.pipe(res);
}
@@ -112,7 +113,7 @@ async function getLogStream(req, res, next) {
'Access-Control-Allow-Origin': '*'
});
res.write('retry: 3000\n');
res.on('close', logStream.close);
res.on('close', () => logStream.destroy());
logStream.on('data', function (data) {
const obj = JSON.parse(data);
const sse = `data: ${JSON.stringify(obj)}\n\n`;

View File

@@ -88,6 +88,7 @@ async function getLogs(req, res, next) {
'Cache-Control': 'no-cache',
'X-Accel-Buffering': 'no' // disable nginx buffering
});
res.on('close', () => logStream.destroy());
logStream.pipe(res);
}
@@ -118,7 +119,7 @@ async function getLogStream(req, res, next) {
'Access-Control-Allow-Origin': '*'
});
res.write('retry: 3000\n');
res.on('close', logStream.close);
res.on('close', () => logStream.destroy());
logStream.on('data', function (data) {
const obj = JSON.parse(data);
res.write(sse(obj.realtimeTimestamp, JSON.stringify(obj))); // send timestamp as id

View File

@@ -82,6 +82,7 @@ async function getLogs(req, res, next) {
'Cache-Control': 'no-cache',
'X-Accel-Buffering': 'no' // disable nginx buffering
});
res.on('close', () => logStream.destroy());
logStream.pipe(res);
}
@@ -113,7 +114,7 @@ async function getLogStream(req, res, next) {
'Access-Control-Allow-Origin': '*'
});
res.write('retry: 3000\n');
res.on('close', logStream.close);
res.on('close', () => logStream.destroy());
logStream.on('data', function (data) {
const obj = JSON.parse(data);
res.write(sse(obj.realtimeTimestamp, JSON.stringify(obj))); // send timestamp as id

View File

@@ -474,7 +474,7 @@ async function getServiceLogs(id, options) {
}
const logStream = new logs.LogStream({ format: options.format || 'json', source: name });
logStream.close = cp.terminate; // closing stream kills the child process
logStream.on('close', () => cp.terminate()); // the caller has to call destroy() on logStream. destroy() of Transform emits 'close'
cp.stdout.pipe(logStream);

View File

@@ -89,7 +89,11 @@ function sudo(tag, args, options, callback) {
e.code = code;
e.signal = signal;
debug(`${tag}: ${SUDO} ${spawnArgs.join(' ').replace(/\n/g, '\\n')} errored`, e);
if (cp.terminated) {
debug(`${tag}: ${SUDO} ${spawnArgs.join(' ').replace(/\n/g, '\\n')} terminated`); // was killed by us
} else {
debug(`${tag}: ${SUDO} ${spawnArgs.join(' ').replace(/\n/g, '\\n')} errored`, e);
}
callback(e);
});
@@ -107,6 +111,7 @@ function sudo(tag, args, options, callback) {
// the workaround is to invoke a kill from a different process group and this is done by starting detached
// another idea is: use "ps --pid cp.pid -o pid=" to get the pid of the command and then send it signal directly
cp.terminate = function () {
cp.terminated = true; // hint for better debug message in 'exit'
child_process.spawn('kill', ['-SIGTERM', cp.pid], { detached: true }, (error) => { if (error) debug(`${tag} could not terminate`, error); });
};

View File

@@ -321,7 +321,7 @@ async function getLogs(unit, options) {
const cp = logs.tail([logFile], { lines: options.lines, follow: options.follow });
const logStream = new logs.LogStream({ format: options.format || 'json', source: unit });
logStream.close = cp.terminate; // closing stream kills the child process
logStream.on('close', () => cp.terminate()); // the caller has to call destroy() on logStream. destroy() of Transform emits 'close'
cp.stdout.pipe(logStream);

View File

@@ -277,7 +277,7 @@ async function getLogs(task, options) {
const cp = logs.tail([`${paths.TASKS_LOG_DIR}/${task.id}.log`], { lines: options.lines, follow: options.follow });
const logStream = new logs.LogStream({ format: options.format || 'json', source: task.id });
logStream.close = cp.terminate; // closing stream kills the child process
logStream.on('close', () => cp.terminate()); // the caller has to call destroy() on logStream. destroy() of Transform emits 'close'
cp.stdout.pipe(logStream);