diff --git a/CHANGES b/CHANGES index d327cf96f..c4c7a4c4a 100644 --- a/CHANGES +++ b/CHANGES @@ -1509,6 +1509,7 @@ * Add UI to switch dashboard domain * Fix remote support button to not remove misparsed ssh keys * cloudflare: preseve domain proxying status -* Fix issue where oom killer might kill the box code +* Fix issue where oom killer might kill the box code or the updater * Add contabo and netcup as supported providers +* Allow full logs to be downloaded diff --git a/src/addons.js b/src/addons.js index 371659e02..b58b01d5d 100644 --- a/src/addons.js +++ b/src/addons.js @@ -369,24 +369,25 @@ function getServiceLogs(serviceName, options, callback) { assert(options && typeof options === 'object'); assert.strictEqual(typeof callback, 'function'); + assert.strictEqual(typeof options.lines, 'number'); + assert.strictEqual(typeof options.format, 'string'); + assert.strictEqual(typeof options.follow, 'boolean'); + if (!KNOWN_SERVICES[serviceName]) return callback(new AddonsError(AddonsError.NOT_FOUND)); debug(`Getting logs for ${serviceName}`); - var lines = options.lines || 100, + var lines = options.lines, format = options.format || 'json', - follow = !!options.follow; + follow = options.follow; - assert.strictEqual(typeof lines, 'number'); - assert.strictEqual(typeof format, 'string'); - - var cmd; - var args = [ '--lines=' + lines ]; + let cmd, args = []; // docker and unbound use journald if (serviceName === 'docker' || serviceName === 'unbound') { cmd = 'journalctl'; + args.push('--lines=' + (lines === -1 ? 'all' : lines)); args.push(`--unit=${serviceName}`); args.push('--no-pager'); args.push('--output=short-iso'); @@ -395,6 +396,7 @@ function getServiceLogs(serviceName, options, callback) { } else { cmd = '/usr/bin/tail'; + args.push('--lines=' + (lines === -1 ? '+1' : lines)); if (follow) args.push('--follow', '--retry', '--quiet'); // same as -F. to make it work if file doesn't exist, --quiet to not output file headers, which are no logs args.push(path.join(paths.LOG_DIR, serviceName, 'app.log')); } diff --git a/src/apps.js b/src/apps.js index 2d76dfccc..c9fc2dcc4 100644 --- a/src/apps.js +++ b/src/apps.js @@ -869,16 +869,19 @@ function getLogs(appId, options, callback) { assert(options && typeof options === 'object'); assert.strictEqual(typeof callback, 'function'); + assert.strictEqual(typeof options.lines, 'number'); + assert.strictEqual(typeof options.format, 'string'); + assert.strictEqual(typeof options.follow, 'boolean'); + debug('Getting logs for %s', appId); get(appId, function (error, app) { if (error) return callback(error); - var lines = options.lines || 100, + var lines = options.lines === -1 ? '+1' : options.lines, format = options.format || 'json', - follow = !!options.follow; + follow = options.follow; - assert.strictEqual(typeof lines, 'number'); assert.strictEqual(typeof format, 'string'); var args = [ '--lines=' + lines ]; diff --git a/src/cloudron.js b/src/cloudron.js index 025b2fe0f..e4bb00ce6 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -228,15 +228,13 @@ function getLogs(unit, options, callback) { assert(options && typeof options === 'object'); assert.strictEqual(typeof callback, 'function'); - var lines = options.lines || 100, + assert.strictEqual(typeof options.lines, 'number'); + assert.strictEqual(typeof options.format, 'string'); + assert.strictEqual(typeof options.follow, 'boolean'); + + var lines = options.lines === -1 ? '+1' : options.lines, format = options.format || 'json', - follow = !!options.follow; - - assert.strictEqual(typeof lines, 'number'); - assert.strictEqual(typeof format, 'string'); - - assert.strictEqual(typeof lines, 'number'); - assert.strictEqual(typeof format, 'string'); + follow = options.follow; debug('Getting logs for %s as %s', unit, format); diff --git a/src/routes/apps.js b/src/routes/apps.js index e0134b833..955e2b101 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -367,7 +367,7 @@ function getLogStream(req, res, next) { debug('Getting logstream of app id:%s', req.params.id); - var lines = req.query.lines ? parseInt(req.query.lines, 10) : -10; // we ignore last-event-id + var lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; // we ignore last-event-id if (isNaN(lines)) return next(new HttpError(400, 'lines must be a valid number')); function sse(id, data) { return 'id: ' + id + '\ndata: ' + data + '\n\n'; } @@ -376,7 +376,8 @@ function getLogStream(req, res, next) { var options = { lines: lines, - follow: true + follow: true, + format: 'json' }; apps.getLogs(req.params.id, options, function (error, logStream) { @@ -405,7 +406,7 @@ function getLogStream(req, res, next) { function getLogs(req, res, next) { assert.strictEqual(typeof req.params.id, 'string'); - var lines = req.query.lines ? parseInt(req.query.lines, 10) : 100; + var lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; if (isNaN(lines)) return next(new HttpError(400, 'lines must be a number')); debug('Getting logs of app id:%s', req.params.id); @@ -413,7 +414,7 @@ function getLogs(req, res, next) { var options = { lines: lines, follow: false, - format: req.query.format + format: req.query.format || 'json' }; apps.getLogs(req.params.id, options, function (error, logStream) { diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index d0dcf4694..85c10e595 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -90,13 +90,13 @@ function checkForUpdates(req, res, next) { function getLogs(req, res, next) { assert.strictEqual(typeof req.params.unit, 'string'); - var lines = req.query.lines ? parseInt(req.query.lines, 10) : 100; + var lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; // we ignore last-event-id if (isNaN(lines)) return next(new HttpError(400, 'lines must be a number')); var options = { lines: lines, follow: false, - format: req.query.format + format: req.query.format || 'json' }; cloudron.getLogs(req.params.unit, options, function (error, logStream) { @@ -116,7 +116,7 @@ function getLogs(req, res, next) { function getLogStream(req, res, next) { assert.strictEqual(typeof req.params.unit, 'string'); - var lines = req.query.lines ? parseInt(req.query.lines, 10) : -10; // we ignore last-event-id + var lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; // we ignore last-event-id if (isNaN(lines)) return next(new HttpError(400, 'lines must be a valid number')); function sse(id, data) { return 'id: ' + id + '\ndata: ' + data + '\n\n'; } @@ -126,7 +126,7 @@ function getLogStream(req, res, next) { var options = { lines: lines, follow: true, - format: req.query.format + format: req.query.format || 'json' }; cloudron.getLogs(req.params.unit, options, function (error, logStream) { diff --git a/src/routes/services.js b/src/routes/services.js index 0943bd33d..d320bbb93 100644 --- a/src/routes/services.js +++ b/src/routes/services.js @@ -56,7 +56,7 @@ function configure(req, res, next) { function getLogs(req, res, next) { assert.strictEqual(typeof req.params.service, 'string'); - var lines = req.query.lines ? parseInt(req.query.lines, 10) : 100; + var lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; // we ignore last-event-id if (isNaN(lines)) return next(new HttpError(400, 'lines must be a number')); debug(`Getting logs of service ${req.params.service}`); @@ -64,7 +64,7 @@ function getLogs(req, res, next) { var options = { lines: lines, follow: false, - format: req.query.format + format: req.query.format || 'json' }; addons.getServiceLogs(req.params.service, options, function (error, logStream) { @@ -87,7 +87,7 @@ function getLogStream(req, res, next) { debug(`Getting logstream of service ${req.params.service}`); - var lines = req.query.lines ? parseInt(req.query.lines, 10) : -10; // we ignore last-event-id + var lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; // we ignore last-event-id if (isNaN(lines)) return next(new HttpError(400, 'lines must be a valid number')); function sse(id, data) { return 'id: ' + id + '\ndata: ' + data + '\n\n'; } @@ -96,7 +96,8 @@ function getLogStream(req, res, next) { var options = { lines: lines, - follow: true + follow: true, + format: 'json' }; addons.getServiceLogs(req.params.service, options, function (error, logStream) { diff --git a/src/routes/tasks.js b/src/routes/tasks.js index 051e86e79..2a0f0d004 100644 --- a/src/routes/tasks.js +++ b/src/routes/tasks.js @@ -59,13 +59,13 @@ function list(req, res, next) { function getLogs(req, res, next) { assert.strictEqual(typeof req.params.taskId, 'string'); - var lines = req.query.lines ? parseInt(req.query.lines, 10) : 100; + var lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; // we ignore last-event-id if (isNaN(lines)) return next(new HttpError(400, 'lines must be a number')); var options = { lines: lines, follow: false, - format: req.query.format + format: req.query.format || 'json' }; tasks.getLogs(req.params.taskId, options, function (error, logStream) { @@ -86,7 +86,7 @@ function getLogs(req, res, next) { function getLogStream(req, res, next) { assert.strictEqual(typeof req.params.taskId, 'string'); - var lines = req.query.lines ? parseInt(req.query.lines, 10) : -10; // we ignore last-event-id + var lines = 'lines' in req.query ? parseInt(req.query.lines, 10) : 10; // we ignore last-event-id if (isNaN(lines)) return next(new HttpError(400, 'lines must be a valid number')); function sse(id, data) { return 'id: ' + id + '\ndata: ' + data + '\n\n'; } @@ -95,7 +95,8 @@ function getLogStream(req, res, next) { var options = { lines: lines, - follow: true + follow: true, + format: 'json' }; tasks.getLogs(req.params.taskId, options, function (error, logStream) { diff --git a/src/tasks.js b/src/tasks.js index e2262b4e7..2c3067d80 100644 --- a/src/tasks.js +++ b/src/tasks.js @@ -175,11 +175,15 @@ function getLogs(taskId, options, callback) { assert(options && typeof options === 'object'); assert.strictEqual(typeof callback, 'function'); + assert.strictEqual(typeof options.lines, 'number'); + assert.strictEqual(typeof options.format, 'string'); + assert.strictEqual(typeof options.follow, 'boolean'); + debug(`Getting logs for ${taskId}`); - var lines = options.lines || 100, + var lines = options.lines === -1 ? '+1' : options.lines, format = options.format || 'json', - follow = !!options.follow; + follow = options.follow; assert.strictEqual(typeof lines, 'number'); assert.strictEqual(typeof format, 'string');