Allow filtering of system logs with push and logs commands

Change-type: minor
Signed-off-by: Cameron Diver <cameron@balena.io>
This commit is contained in:
Cameron Diver 2019-04-24 17:30:18 +01:00
parent b22ddb50f1
commit a6d2950260
5 changed files with 94 additions and 19 deletions

View File

@ -865,7 +865,8 @@ If an IP address is passed to this command, logs are displayed from
a local mode device with that address. Note that --tail is implied a local mode device with that address. Note that --tail is implied
when this command is provided an IP address. when this command is provided an IP address.
Logs from a single service can be displayed with the --service flag. Logs from a single service can be displayed with the --service flag. Just system logs
can be shown with the --system flag. Note that these flags can be used together.
Examples: Examples:
@ -875,6 +876,8 @@ Examples:
$ balena logs 192.168.0.31 $ balena logs 192.168.0.31
$ balena logs 192.168.0.31 --service my-service $ balena logs 192.168.0.31 --service my-service
$ balena logs 192.168.0.31 --system
$ balena logs 192.168.0.31 --system --service my-service
### Options ### Options
@ -884,7 +887,11 @@ continuously stream output
#### --service, -s &#60;service&#62; #### --service, -s &#60;service&#62;
Only show logs for a single service Only show logs for a single service. This can be used in combination with --system
#### --system, -S
Only show system logs. This can be used in combination with --service.
# Sync # Sync
@ -1417,7 +1424,9 @@ Logs will be streamed back from the device as part of the same invocation.
The web dashboard can be used to switch a device to local mode: The web dashboard can be used to switch a device to local mode:
https://www.balena.io/docs/learn/develop/local-mode/ https://www.balena.io/docs/learn/develop/local-mode/
Note that local mode requires a supervisor version of at least v7.21.0. Note that local mode requires a supervisor version of at least v7.21.0.
The logs from only a single service can be shown with the --service flag. The logs from only a single service can be shown with the --service flag, and
showing only the system logs can be achieved with --system. Note that these
flags can be used together.
It is also possible to run a push to a local mode device in live mode. It is also possible to run a push to a local mode device in live mode.
This will watch for changes in the source directory and perform an This will watch for changes in the source directory and perform an
@ -1447,6 +1456,8 @@ Examples:
$ balena push 10.0.0.1 --source <source directory> $ balena push 10.0.0.1 --source <source directory>
$ balena push 10.0.0.1 -s <source directory> $ balena push 10.0.0.1 -s <source directory>
$ balena push 10.0.0.1 --service my-service $ balena push 10.0.0.1 --service my-service
$ balena push 10.0.0.1 --system
$ balena push 10.0.0.1 --system --service my-service
### Options ### Options
@ -1487,7 +1498,12 @@ Don't tail application logs when pushing to a local mode device
#### --service &#60;service&#62; #### --service &#60;service&#62;
Only show logs from a single service. Only show logs from a single service. This can be used in combination with --system.
Only valid when pushing to a local mode device.
#### --system
Only show system logs. This can be used in combination with --service.
Only valid when pushing to a local mode device. Only valid when pushing to a local mode device.
# Settings # Settings

View File

@ -36,7 +36,11 @@ export const logs: CommandDefinition<
{ {
uuidOrDevice: string; uuidOrDevice: string;
}, },
{ tail: boolean; service: string } {
tail: boolean;
service: string;
system: boolean;
}
> = { > = {
signature: 'logs <uuidOrDevice>', signature: 'logs <uuidOrDevice>',
description: 'show device logs', description: 'show device logs',
@ -51,7 +55,8 @@ export const logs: CommandDefinition<
a local mode device with that address. Note that --tail is implied a local mode device with that address. Note that --tail is implied
when this command is provided an IP address. when this command is provided an IP address.
Logs from a single service can be displayed with the --service flag. Logs from a single service can be displayed with the --service flag. Just system logs
can be shown with the --system flag. Note that these flags can be used together.
Examples: Examples:
@ -60,7 +65,9 @@ export const logs: CommandDefinition<
$ balena logs 23c73a1 --service my-service $ balena logs 23c73a1 --service my-service
$ balena logs 192.168.0.31 $ balena logs 192.168.0.31
$ balena logs 192.168.0.31 --service my-service`, $ balena logs 192.168.0.31 --service my-service
$ balena logs 192.168.0.31 --system
$ balena logs 192.168.0.31 --system --service my-service`,
options: [ options: [
{ {
signature: 'tail', signature: 'tail',
@ -70,10 +77,18 @@ export const logs: CommandDefinition<
}, },
{ {
signature: 'service', signature: 'service',
description: 'Only show logs for a single service', description:
'Only show logs for a single service. This can be used in combination with --system',
parameter: 'service', parameter: 'service',
alias: 's', alias: 's',
}, },
{
signature: 'system',
alias: 'S',
boolean: true,
description:
'Only show system logs. This can be used in combination with --service.',
},
], ],
permission: 'user', permission: 'user',
primary: true, primary: true,
@ -96,9 +111,19 @@ export const logs: CommandDefinition<
if (serviceName == null) { if (serviceName == null) {
serviceName = 'Unknown service'; serviceName = 'Unknown service';
} }
displayLogObject({ serviceName, ...line }, logger, options.service); displayLogObject(
{ serviceName, ...line },
logger,
options.system || false,
options.service,
);
} else { } else {
displayLogObject(line, logger, options.service); displayLogObject(
line,
logger,
options.system || false,
options.service,
);
} }
}; };
@ -117,7 +142,12 @@ export const logs: CommandDefinition<
} }
const logStream = await deviceApi.getLogStream(); const logStream = await deviceApi.getLogStream();
displayDeviceLogs(logStream, logger, options.service); displayDeviceLogs(
logStream,
logger,
options.system || false,
options.service,
);
} else { } else {
if (options.tail) { if (options.tail) {
return balena.logs return balena.logs

View File

@ -109,6 +109,7 @@ export const push: CommandDefinition<
live: boolean; live: boolean;
detached: boolean; detached: boolean;
service: string; service: string;
system: boolean;
} }
> = { > = {
signature: 'push <applicationOrDevice>', signature: 'push <applicationOrDevice>',
@ -129,7 +130,9 @@ export const push: CommandDefinition<
The web dashboard can be used to switch a device to local mode: The web dashboard can be used to switch a device to local mode:
https://www.balena.io/docs/learn/develop/local-mode/ https://www.balena.io/docs/learn/develop/local-mode/
Note that local mode requires a supervisor version of at least v7.21.0. Note that local mode requires a supervisor version of at least v7.21.0.
The logs from only a single service can be shown with the --service flag. The logs from only a single service can be shown with the --service flag, and
showing only the system logs can be achieved with --system. Note that these
flags can be used together.
It is also possible to run a push to a local mode device in live mode. It is also possible to run a push to a local mode device in live mode.
This will watch for changes in the source directory and perform an This will watch for changes in the source directory and perform an
@ -147,6 +150,8 @@ export const push: CommandDefinition<
$ balena push 10.0.0.1 --source <source directory> $ balena push 10.0.0.1 --source <source directory>
$ balena push 10.0.0.1 -s <source directory> $ balena push 10.0.0.1 -s <source directory>
$ balena push 10.0.0.1 --service my-service $ balena push 10.0.0.1 --service my-service
$ balena push 10.0.0.1 --system
$ balena push 10.0.0.1 --system --service my-service
`, `,
options: [ options: [
{ {
@ -204,10 +209,17 @@ export const push: CommandDefinition<
{ {
signature: 'service', signature: 'service',
description: stripIndent` description: stripIndent`
Only show logs from a single service. Only show logs from a single service. This can be used in combination with --system.
Only valid when pushing to a local mode device.`, Only valid when pushing to a local mode device.`,
parameter: 'service', parameter: 'service',
}, },
{
signature: 'system',
description: stripIndent`
Only show system logs. This can be used in combination with --service.
Only valid when pushing to a local mode device.`,
boolean: true,
},
], ],
async action(params, options, done) { async action(params, options, done) {
const sdk = (await import('balena-sdk')).fromSharedOptions(); const sdk = (await import('balena-sdk')).fromSharedOptions();
@ -260,6 +272,11 @@ export const push: CommandDefinition<
'The --service flag is only valid when pushing to a local mode device.', 'The --service flag is only valid when pushing to a local mode device.',
); );
} }
if (options.system) {
exitWithExpectedError(
'The --system flag is only valid when pushing to a local mode device.',
);
}
const app = appOrDevice; const app = appOrDevice;
await exitIfNotLoggedIn(); await exitIfNotLoggedIn();
@ -301,6 +318,7 @@ export const push: CommandDefinition<
live: options.live || false, live: options.live || false,
detached: options.detached || false, detached: options.detached || false,
service: options.service, service: options.service,
system: options.system || false,
}), }),
) )
.catch(BuildError, e => { .catch(BuildError, e => {

View File

@ -49,6 +49,7 @@ export interface DeviceDeployOptions {
live: boolean; live: boolean;
detached: boolean; detached: boolean;
service?: string; service?: string;
system: boolean;
} }
async function checkSource(source: string): Promise<boolean> { async function checkSource(source: string): Promise<boolean> {
@ -176,10 +177,10 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
globalLogger.logLivepush('Watching for file changes...'); globalLogger.logLivepush('Watching for file changes...');
await Promise.all([ await Promise.all([
livepush.init(), livepush.init(),
displayDeviceLogs(logStream, globalLogger, opts.service), displayDeviceLogs(logStream, globalLogger, opts.system, opts.service),
]); ]);
} else { } else {
await displayDeviceLogs(logStream, globalLogger, opts.service); await displayDeviceLogs(logStream, globalLogger, opts.system, opts.service);
} }
} }

View File

@ -28,17 +28,20 @@ interface BuildLog {
* objects * objects
* @param logger A Logger instance which the logs will be * @param logger A Logger instance which the logs will be
* displayed through * displayed through
* @param system Only show system (and potentially the
* filterService) logs
* @param filterService Filter the logs so that only logs * @param filterService Filter the logs so that only logs
* from a single service will be displayed * from a single service will be displayed
*/ */
export function displayDeviceLogs( export function displayDeviceLogs(
logs: Readable, logs: Readable,
logger: Logger, logger: Logger,
system: boolean,
filterService?: string, filterService?: string,
): Bluebird<void> { ): Bluebird<void> {
return new Bluebird((resolve, reject) => { return new Bluebird((resolve, reject) => {
logs.on('data', log => { logs.on('data', log => {
displayLogLine(log, logger, filterService); displayLogLine(log, logger, system, filterService);
}); });
logs.on('error', reject); logs.on('error', reject);
@ -57,11 +60,12 @@ export function displayBuildLog(log: BuildLog, logger: Logger): void {
function displayLogLine( function displayLogLine(
log: string | Buffer, log: string | Buffer,
logger: Logger, logger: Logger,
system: boolean,
filterService?: string, filterService?: string,
): void { ): void {
try { try {
const obj: Log = JSON.parse(log.toString()); const obj: Log = JSON.parse(log.toString());
displayLogObject(obj, logger, filterService); displayLogObject(obj, logger, system, filterService);
} catch (e) { } catch (e) {
logger.logDebug(`Dropping device log due to failed parsing: ${e}`); logger.logDebug(`Dropping device log due to failed parsing: ${e}`);
} }
@ -70,6 +74,7 @@ function displayLogLine(
export function displayLogObject<T extends Log>( export function displayLogObject<T extends Log>(
obj: T, obj: T,
logger: Logger, logger: Logger,
system: boolean,
filterService?: string, filterService?: string,
): void { ): void {
let toPrint: string; let toPrint: string;
@ -80,13 +85,18 @@ export function displayLogObject<T extends Log>(
} }
if (obj.serviceName != null) { if (obj.serviceName != null) {
if (filterService && obj.serviceName !== filterService) { if (filterService) {
if (obj.serviceName !== filterService) {
return;
}
} else if (system) {
return; return;
} }
const colourFn = getServiceColourFn(obj.serviceName); const colourFn = getServiceColourFn(obj.serviceName);
toPrint += ` ${colourFn(`[${obj.serviceName}]`)}`; toPrint += ` ${colourFn(`[${obj.serviceName}]`)}`;
} else if (filterService != null) { } else if (filterService != null && !system) {
// We have a system log here but we are filtering based // We have a system log here but we are filtering based
// on a service, so drop this too // on a service, so drop this too
return; return;