Skip to content

Commit

Permalink
feat(logs): support "json" and "json-stream" formats (for apps only)
Browse files Browse the repository at this point in the history
  • Loading branch information
miton18 authored and hsablonniere committed Feb 16, 2024
1 parent 7ecf87f commit a909959
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 8 deletions.
3 changes: 2 additions & 1 deletion bin/clever.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ function run () {
sourceableEnvVarsList: cliparse.flag('add-export', { description: 'Display sourceable env variables setting' }),
accesslogsFormat: getOutputFormatOption(['simple', 'extended', 'clf']),
addonEnvFormat: getOutputFormatOption(['shell']),
logsFormat: getOutputFormatOption(['json-stream']),
accesslogsFollow: cliparse.flag('follow', {
aliases: ['f'],
description: 'Display access logs continuously (ignores before/until, after/since)',
Expand Down Expand Up @@ -763,7 +764,7 @@ function run () {
const logs = lazyRequirePromiseModule('../src/commands/logs.js');
const logsCommand = cliparse.command('logs', {
description: 'Fetch application logs, continuously',
options: [opts.alias, opts.before, opts.after, opts.search, opts.deploymentId, opts.addonId],
options: [opts.alias, opts.before, opts.after, opts.search, opts.deploymentId, opts.addonId, opts.logsFormat],
}, logs('appLogs'));

// MAKE DEFAULT COMMAND
Expand Down
17 changes: 13 additions & 4 deletions src/commands/logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,32 @@ const { Deferred } = require('../models/utils.js');
const colors = require('colors/safe');

async function appLogs (params) {
const { alias, addon: addonId, after: since, before: until, search, 'deployment-id': deploymentId } = params.options;
const { alias, addon: addonId, after: since, before: until, search, 'deployment-id': deploymentId, format } = params.options;

// ignore --search ""
const filter = (search !== '') ? search : null;

const { appId, ownerId } = await AppConfig.getAppDetails({ alias });

const isForHuman = (format === 'human');

// TODO: drop when addons are migrated to the v4 API
if (addonId) {
Logger.println(colors.blue('Waiting for addon logs…'));
if (isForHuman) {
Logger.println(colors.blue('Waiting for addon logs…'));
}
else {
throw new Error(`"${format}" format is not yet available for add-on logs`);
}
return LogV2.displayLogs({ appAddonId: addonId, since, until, filter, deploymentId });
}

Logger.println(colors.blue('Waiting for application logs…'));
if (isForHuman) {
Logger.println(colors.blue('Waiting for application logs…'));
}

const deferred = new Deferred();
await Log.displayLogs({ ownerId, appId, since, until, filter, deploymentId, deferred });
await Log.displayLogs({ ownerId, appId, since, until, filter, deploymentId, format, deferred });
return deferred.promise;
}

Expand Down
56 changes: 53 additions & 3 deletions src/models/log-v4.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ async function displayLogs (params) {

const deferred = params.deferred || new Deferred();
const { apiHost, tokens } = await getHostAndTokens();
const { ownerId, appId, filter, since, until, deploymentId } = params;
const { ownerId, appId, filter, since, until, deploymentId, format } = params;

if (format === 'json' && until == null) {
throw new Error('"json" format is only applicable with a limiting parameter such as `--until`');
}

const logStream = new ApplicationLogStream({
apiHost,
Expand All @@ -37,21 +41,40 @@ async function displayLogs (params) {

// Properly close the stream
process.once('SIGINT', (signal) => logStream.close(signal));
const jsonArray = new JsonArray();

logStream
.on('open', (event) => {
Logger.debug(colors.blue(`Logs stream (open) ${JSON.stringify({ appId, filter, deploymentId })}`));
if (format === 'json') {
jsonArray.open();
}
})
.on('error', (event) => {
Logger.debug(colors.red(`Logs stream (error) ${event.error.message}`));
})
.onLog((log) => {
Logger.println(formatLogLine(log));
switch (format) {
case 'json':
jsonArray.push(log);
return;
case 'json-stream':
Logger.printJson(log);
return;
case 'human':
default:
Logger.println(formatLogLine(log));
}
});

// start() is blocking until end of stream
logStream.start()
.then((reason) => deferred.resolve())
.then((reason) => {
if (format === 'json') {
jsonArray.close();
}
return deferred.resolve();
})
.catch(processError)
.catch((error) => deferred.reject(error));

Expand Down Expand Up @@ -142,3 +165,30 @@ function isBuildSucessMessage (log) {
};

module.exports = { displayLogs, watchDeploymentAndDisplayLogs };

/**
* Helper to print a real JSON array with starting `[` and ending `]`
*/
class JsonArray {
constructor () {
this._isFirst = true;
}

open () {
process.stdout.write('[\n');
}

push (log) {
if (this._isFirst) {
this._isFirst = false;
}
else {
process.stdout.write(',\n');
}
process.stdout.write(` ${JSON.stringify(log)}`);
}

close () {
process.stdout.write('\n]');
}
}

0 comments on commit a909959

Please sign in to comment.