Skip to content

Commit

Permalink
cli: more improvements (#176663)
Browse files Browse the repository at this point in the history
- more logging
- reduce extensions scanning
  • Loading branch information
sandy081 committed Mar 9, 2023
1 parent 2cf863b commit 34652da
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 120 deletions.
8 changes: 4 additions & 4 deletions src/vs/code/node/cliProcessMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,23 +268,23 @@ class CliMain extends Disposable {

// List Extensions
if (this.argv['list-extensions']) {
return instantiationService.createInstance(ExtensionManagementCLI).listExtensions(!!this.argv['show-versions'], this.argv['category'], profileLocation);
return instantiationService.createInstance(ExtensionManagementCLI, new ConsoleLogger(LogLevel.Info, false)).listExtensions(!!this.argv['show-versions'], this.argv['category'], profileLocation);
}

// Install Extension
else if (this.argv['install-extension'] || this.argv['install-builtin-extension']) {
const installOptions: InstallOptions = { isMachineScoped: !!this.argv['do-not-sync'], installPreReleaseVersion: !!this.argv['pre-release'], profileLocation };
return instantiationService.createInstance(ExtensionManagementCLI).installExtensions(this.asExtensionIdOrVSIX(this.argv['install-extension'] || []), this.asExtensionIdOrVSIX(this.argv['install-builtin-extension'] || []), installOptions, !!this.argv['force']);
return instantiationService.createInstance(ExtensionManagementCLI, new ConsoleLogger(LogLevel.Info, false)).installExtensions(this.asExtensionIdOrVSIX(this.argv['install-extension'] || []), this.asExtensionIdOrVSIX(this.argv['install-builtin-extension'] || []), installOptions, !!this.argv['force']);
}

// Uninstall Extension
else if (this.argv['uninstall-extension']) {
return instantiationService.createInstance(ExtensionManagementCLI).uninstallExtensions(this.asExtensionIdOrVSIX(this.argv['uninstall-extension']), !!this.argv['force'], profileLocation);
return instantiationService.createInstance(ExtensionManagementCLI, new ConsoleLogger(LogLevel.Info, false)).uninstallExtensions(this.asExtensionIdOrVSIX(this.argv['uninstall-extension']), !!this.argv['force'], profileLocation);
}

// Locate Extension
else if (this.argv['locate-extension']) {
return instantiationService.createInstance(ExtensionManagementCLI).locateExtension(this.argv['locate-extension']);
return instantiationService.createInstance(ExtensionManagementCLI, new ConsoleLogger(LogLevel.Info, false)).locateExtension(this.argv['locate-extension']);
}

// Telemetry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,8 +516,3 @@ export interface IExtensionTipsService {
export const ExtensionsLabel = localize('extensions', "Extensions");
export const ExtensionsLocalizedLabel = { value: ExtensionsLabel, original: 'Extensions' };
export const PreferencesLocalizedLabel = { value: localize('preferences', "Preferences"), original: 'Preferences' };

export interface CLIOutput {
log(s: string): void;
error(s: string): void;
}
153 changes: 75 additions & 78 deletions src/vs/platform/extensionManagement/common/extensionManagementCLI.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,11 @@ export class ExtensionsScanner extends Disposable {

private async removeUninstalledExtensions(): Promise<void> {
const uninstalled = await this.getUninstalledExtensions();
if (Object.keys(uninstalled).length === 0) {
this.logService.debug(`No uninstalled extensions found.`);
return;
}

this.logService.debug(`Removing uninstalled extensions:`, Object.keys(uninstalled));

const extensions = await this.extensionsScannerService.scanUserExtensions({ includeAllVersions: true, includeUninstalled: true, includeInvalid: true }); // All user extensions
Expand Down
32 changes: 26 additions & 6 deletions src/vs/platform/log/common/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,38 +390,58 @@ export class ConsoleMainLogger extends AbstractLogger implements ILogger {

export class ConsoleLogger extends AbstractLogger implements ILogger {

constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL, private readonly useColors: boolean = true) {
super();
this.setLevel(logLevel);
}

trace(message: string, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Trace)) {
console.log('%cTRACE', 'color: #888', message, ...args);
if (this.useColors) {
console.log('%cTRACE', 'color: #888', message, ...args);
} else {
console.log(message, ...args);
}
}
}

debug(message: string, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Debug)) {
console.log('%cDEBUG', 'background: #eee; color: #888', message, ...args);
if (this.useColors) {
console.log('%cDEBUG', 'background: #eee; color: #888', message, ...args);
} else {
console.log(message, ...args);
}
}
}

info(message: string, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Info)) {
console.log('%c INFO', 'color: #33f', message, ...args);
if (this.useColors) {
console.log('%c INFO', 'color: #33f', message, ...args);
} else {
console.log(message, ...args);
}
}
}

warn(message: string | Error, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Warning)) {
console.log('%c WARN', 'color: #993', message, ...args);
if (this.useColors) {
console.log('%c WARN', 'color: #993', message, ...args);
} else {
console.log(message, ...args);
}
}
}

error(message: string, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Error)) {
console.log('%c ERR', 'color: #f33', message, ...args);
if (this.useColors) {
console.log('%c ERR', 'color: #f33', message, ...args);
} else {
console.error(message, ...args);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/vs/server/node/remoteExtensionHostAgentCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { getLogLevel, ILoggerService, ILogService } from 'vs/platform/log/common/log';
import { ConsoleLogger, getLogLevel, ILoggerService, ILogService } from 'vs/platform/log/common/log';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
Expand Down Expand Up @@ -68,7 +68,7 @@ class CliMain extends Disposable {
await instantiationService.invokeFunction(async accessor => {
const logService = accessor.get(ILogService);
try {
await this.doRun(instantiationService.createInstance(ExtensionManagementCLI));
await this.doRun(instantiationService.createInstance(ExtensionManagementCLI, new ConsoleLogger(logService.getLevel(), false)));
} catch (error) {
logService.error(error);
console.error(getErrorMessage(error));
Expand Down
16 changes: 10 additions & 6 deletions src/vs/server/node/remoteExtensionsScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,14 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS
) {
const builtinExtensionsToInstall = environmentService.args['install-builtin-extension'];
if (builtinExtensionsToInstall) {
_logService.trace('Installing builtin extensions passed via args...');
const installOptions: InstallOptions = { isMachineScoped: !!environmentService.args['do-not-sync'], installPreReleaseVersion: !!environmentService.args['pre-release'] };
performance.mark('code/server/willInstallBuiltinExtensions');
this._whenExtensionsReady = _extensionManagementCLI.installExtensions([], this._asExtensionIdOrVSIX(builtinExtensionsToInstall), installOptions, !!environmentService.args['force'])
.then(() => performance.mark('code/server/didInstallBuiltinExtensions'), error => {
.then(() => {
performance.mark('code/server/didInstallBuiltinExtensions');
_logService.trace('Finished installing builtin extensions');
}, error => {
_logService.error(error);
});
} else {
Expand All @@ -53,9 +57,12 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS

const extensionsToInstall = environmentService.args['install-extension'];
if (extensionsToInstall) {
_logService.trace('Installing extensions passed via args...');
this._whenExtensionsReady
.then(() => _extensionManagementCLI.installExtensions(this._asExtensionIdOrVSIX(extensionsToInstall), [], { isMachineScoped: !!environmentService.args['do-not-sync'], installPreReleaseVersion: !!environmentService.args['pre-release'] }, !!environmentService.args['force']))
.then(null, error => {
.then(() => {
_logService.trace('Finished installing extensions');
}, error => {
_logService.error(error);
});
}
Expand Down Expand Up @@ -174,10 +181,7 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS

this._logService.trace(`Language Pack ${languagePackId} for language ${language} is not installed. It will be installed now.`);
try {
await this._extensionManagementCLI.installExtensions([languagePackId], [], { isMachineScoped: true }, true, {
log: (s) => this._logService.info(s),
error: (s) => this._logService.error(s)
});
await this._extensionManagementCLI.installExtensions([languagePackId], [], { isMachineScoped: true }, true);
} catch (err) {
// We tried to install the language pack but failed. We can continue without it thus using the default language.
this._logService.error(err);
Expand Down
7 changes: 4 additions & 3 deletions src/vs/server/node/serverServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { InstantiationService } from 'vs/platform/instantiation/common/instantia
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
import { NativeLanguagePackService } from 'vs/platform/languagePacks/node/languagePacks';
import { AbstractLogger, DEFAULT_LOG_LEVEL, getLogLevel, ILoggerService, ILogService, LogLevel } from 'vs/platform/log/common/log';
import { AbstractLogger, DEFAULT_LOG_LEVEL, getLogLevel, ILoggerService, ILogService, log, LogLevel, LogLevelToString } from 'vs/platform/log/common/log';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment';
Expand Down Expand Up @@ -102,6 +102,7 @@ export async function setupServerServices(connectionToken: ServerConnectionToken
const logService = new LogService(logger, [new ServerLogger(getLogLevel(environmentService))]);
services.set(ILogService, logService);
setTimeout(() => cleanupOlderLogs(environmentService.logsHome.fsPath).then(null, err => logService.error(err)), 10000);
logService.onDidChangeLogLevel(logLevel => log(logService, logLevel, `Log level changed to ${LogLevelToString(logService.getLevel())}`));

logService.trace(`Remote configuration data at ${REMOTE_DATA_FOLDER}`);
logService.trace('process arguments:', environmentService.args);
Expand Down Expand Up @@ -217,7 +218,7 @@ export async function setupServerServices(connectionToken: ServerConnectionToken

socketServer.registerChannel(REMOTE_TERMINAL_CHANNEL_NAME, new RemoteTerminalChannel(environmentService, logService, ptyService, productService, extensionManagementService, configurationService));

const remoteExtensionsScanner = new RemoteExtensionsScannerService(instantiationService.createInstance(ExtensionManagementCLI), environmentService, userDataProfilesService, extensionsScannerService, logService, extensionGalleryService, languagePackService);
const remoteExtensionsScanner = new RemoteExtensionsScannerService(instantiationService.createInstance(ExtensionManagementCLI, logService), environmentService, userDataProfilesService, extensionsScannerService, logService, extensionGalleryService, languagePackService);
socketServer.registerChannel(RemoteExtensionsScannerChannelName, new RemoteExtensionsScannerChannel(remoteExtensionsScanner, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)));

const remoteFileSystemChannel = new RemoteAgentFileSystemProviderChannel(logService, environmentService);
Expand All @@ -235,7 +236,7 @@ export async function setupServerServices(connectionToken: ServerConnectionToken
socketServer.registerChannel('credentials', credentialsChannel);

// clean up extensions folder
extensionManagementService.cleanUp();
remoteExtensionsScanner.whenExtensionsReady().then(() => extensionManagementService.cleanUp());

disposables.add(new ErrorTelemetry(accessor.get(ITelemetryService)));

Expand Down
29 changes: 15 additions & 14 deletions src/vs/workbench/api/browser/mainThreadCLICommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@ import { isString } from 'vs/base/common/types';
import { URI, UriComponents } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CLIOutput, IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementCLI } from 'vs/platform/extensionManagement/common/extensionManagementCLI';
import { getExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ILabelService } from 'vs/platform/label/common/label';
import { AbstractMessageLogger, ILogger, LogLevel } from 'vs/platform/log/common/log';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IProductService } from 'vs/platform/product/common/productService';
import { IOpenWindowOptions, IWindowOpenable } from 'vs/platform/window/common/window';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
Expand Down Expand Up @@ -61,25 +60,28 @@ CommandsRegistry.registerCommand('_remoteCLI.manageExtensions', async function (
return;
}

const cliService = instantiationService.createChild(new ServiceCollection([IExtensionManagementService, remoteExtensionManagementService])).createInstance(RemoteExtensionManagementCLI);

const lines: string[] = [];
const output = { log: lines.push.bind(lines), error: lines.push.bind(lines) };
const logger = new class extends AbstractMessageLogger {
protected override log(level: LogLevel, message: string): void {
lines.push(message);
}
}();
const cliService = instantiationService.createChild(new ServiceCollection([IExtensionManagementService, remoteExtensionManagementService])).createInstance(RemoteExtensionManagementCLI, logger);

if (args.list) {
await cliService.listExtensions(!!args.list.showVersions, args.list.category, undefined, output);
await cliService.listExtensions(!!args.list.showVersions, args.list.category, undefined);
} else {
const revive = (inputs: (string | UriComponents)[]) => inputs.map(input => isString(input) ? input : URI.revive(input));
if (Array.isArray(args.install) && args.install.length) {
try {
await cliService.installExtensions(revive(args.install), [], { isMachineScoped: true }, !!args.force, output);
await cliService.installExtensions(revive(args.install), [], { isMachineScoped: true }, !!args.force);
} catch (e) {
lines.push(e.message);
}
}
if (Array.isArray(args.uninstall) && args.uninstall.length) {
try {
await cliService.uninstallExtensions(revive(args.uninstall), !!args.force, undefined, output);
await cliService.uninstallExtensions(revive(args.uninstall), !!args.force, undefined);
} catch (e) {
lines.push(e.message);
}
Expand All @@ -93,15 +95,14 @@ class RemoteExtensionManagementCLI extends ExtensionManagementCLI {
private _location: string | undefined;

constructor(
logger: ILogger,
@IExtensionManagementService extensionManagementService: IExtensionManagementService,
@IProductService productService: IProductService,
@IConfigurationService configurationService: IConfigurationService,
@IExtensionGalleryService extensionGalleryService: IExtensionGalleryService,
@ILabelService labelService: ILabelService,
@IWorkbenchEnvironmentService envService: IWorkbenchEnvironmentService,
@IExtensionManifestPropertiesService private readonly _extensionManifestPropertiesService: IExtensionManifestPropertiesService,
) {
super(extensionManagementService, extensionGalleryService);
super(logger, extensionManagementService, extensionGalleryService);

const remoteAuthority = envService.remoteAuthority;
this._location = remoteAuthority ? labelService.getHostLabel(Schemas.vscodeRemote, remoteAuthority) : undefined;
Expand All @@ -111,11 +112,11 @@ class RemoteExtensionManagementCLI extends ExtensionManagementCLI {
return this._location;
}

protected override validateExtensionKind(manifest: IExtensionManifest, output: CLIOutput): boolean {
protected override validateExtensionKind(manifest: IExtensionManifest): boolean {
if (!this._extensionManifestPropertiesService.canExecuteOnWorkspace(manifest)
// Web extensions installed on remote can be run in web worker extension host
&& !(isWeb && this._extensionManifestPropertiesService.canExecuteOnWeb(manifest))) {
output.log(localize('cannot be installed', "Cannot install the '{0}' extension because it is declared to not run in this setup.", getExtensionId(manifest.publisher, manifest.name)));
this.logger.info(localize('cannot be installed', "Cannot install the '{0}' extension because it is declared to not run in this setup.", getExtensionId(manifest.publisher, manifest.name)));
return false;
}
return true;
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/browser/web.main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { mark } from 'vs/base/common/performance';
import { domContentLoaded, detectFullscreen, getCookieValue } from 'vs/base/browser/dom';
import { assertIsDefined } from 'vs/base/common/types';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ILogService, ConsoleLogger, getLogLevel, ILoggerService } from 'vs/platform/log/common/log';
import { ILogService, ConsoleLogger, getLogLevel, ILoggerService, ILogger } from 'vs/platform/log/common/log';
import { ConsoleLogInAutomationLogger } from 'vs/platform/log/browser/log';
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { BrowserWorkbenchEnvironmentService, IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
Expand Down Expand Up @@ -244,7 +244,7 @@ export class BrowserMain extends Disposable {
// Log
const logLevel = getLogLevel(environmentService);
const bufferLogger = new BufferLogger(logLevel);
const otherLoggers = [new ConsoleLogger(logLevel)];
const otherLoggers: ILogger[] = [new ConsoleLogger(logLevel)];
if (environmentService.isExtensionDevelopment && !!environmentService.extensionTestsLocationURI) {
otherLoggers.push(new ConsoleLogInAutomationLogger(logLevel));
}
Expand Down

0 comments on commit 34652da

Please sign in to comment.