diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 544d8286ee5..2846ac152b5 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -26,7 +26,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { combinedAppender, NullTelemetryService, ITelemetryAppender, NullAppender } from 'vs/platform/telemetry/common/telemetryUtils'; import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; import { TelemetryAppenderChannel } from 'vs/platform/telemetry/node/telemetryIpc'; -import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService'; +import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender'; import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { ILogService, LogLevel, ILoggerService } from 'vs/platform/log/common/log'; @@ -48,7 +48,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; import { Schemas } from 'vs/base/common/network'; import { IProductService } from 'vs/platform/product/common/productService'; -import { IUserDataSyncService, IUserDataSyncStoreService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncResourceEnablementService, IUserDataSyncBackupStoreService, IUserDataSyncStoreManagementService, IUserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserDataSyncService, IUserDataSyncStoreService, registerConfiguration as registerUserDataSyncConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncResourceEnablementService, IUserDataSyncBackupStoreService, IUserDataSyncStoreManagementService, IUserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync'; import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService'; import { UserDataSyncStoreService, UserDataSyncStoreManagementService } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; import { UserDataSyncChannel, UserDataSyncUtilServiceClient, UserDataAutoSyncChannel, UserDataSyncMachinesServiceChannel, UserDataSyncAccountServiceChannel, UserDataSyncStoreManagementServiceChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc'; @@ -72,8 +72,9 @@ import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogA import { UserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataAutoSyncService'; import { IgnoredExtensionsManagementService, IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions'; import { ExtensionsStorageSyncService, IExtensionsStorageSyncService } from 'vs/platform/userDataSync/common/extensionsStorageSync'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -export interface ISharedProcessConfiguration { +interface ISharedProcessConfiguration { readonly machineId: string; readonly windowId: number; } @@ -86,8 +87,6 @@ interface ISharedProcessInitData { backupWorkspacesPath: string; } -const eventPrefix = 'monacoworkbench'; - class MainProcessService implements IMainProcessService { declare readonly _serviceBrand: undefined; @@ -108,164 +107,219 @@ class MainProcessService implements IMainProcessService { class SharedProcessMain extends Disposable { - async init(server: NodeIPCServer, initData: ISharedProcessInitData, configuration: ISharedProcessConfiguration): Promise { - const services = new ServiceCollection(); + constructor(private server: NodeIPCServer, private initData: ISharedProcessInitData, private configuration: ISharedProcessConfiguration) { + super(); + this._register(this.server); + + this.registerListeners(); + } + + private registerListeners(): void { + + // Dispose on exit const onExit = () => this.dispose(); process.once('exit', onExit); ipcRenderer.once('vscode:electron-main->shared-process=exit', onExit); + } - this._register(server); + async open(): Promise { - const environmentService = new NativeEnvironmentService(initData.args); + // Services + const instantiationService = await this.initServices(); + // Config + registerUserDataSyncConfiguration(); + + instantiationService.invokeFunction(accessor => { + + // Log info + accessor.get(ILogService).info('sharedProcess main', JSON.stringify(this.configuration)); + + // Channels + this.initChannels(accessor); + + // Clean-up deprecated extensions + const extensionManagementService = this._register((accessor.get(IExtensionManagementService) as ExtensionManagementService)); + extensionManagementService.removeDeprecatedExtensions(); + + // Update localizations cache + (accessor.get(ILocalizationsService) as LocalizationsService).update(); + }); + + // Instantiate Clean-up helpers + this._register(combinedDisposable( + new NodeCachedDataCleaner(this.initData.nodeCachedDataDir), + instantiationService.createInstance(LanguagePackCachedDataCleaner), + instantiationService.createInstance(StorageDataCleaner, this.initData.backupWorkspacesPath), + instantiationService.createInstance(LogsDataCleaner) + )); + } + + private async initServices(): Promise { + const services = new ServiceCollection(); + + // Environment + const environmentService = new NativeEnvironmentService(this.initData.args); + services.set(IEnvironmentService, environmentService); + services.set(INativeEnvironmentService, environmentService); + + // Log const mainRouter = new StaticRouter(ctx => ctx === 'main'); - const loggerClient = new LoggerChannelClient(server.getChannel('logger', mainRouter)); - const logService = this._register(new FollowerLogService(loggerClient, new SpdLogService('sharedprocess', environmentService.logsPath, initData.logLevel))); - logService.info('main', JSON.stringify(configuration)); + const loggerClient = new LoggerChannelClient(this.server.getChannel('logger', mainRouter)); + const logService = this._register(new FollowerLogService(loggerClient, new SpdLogService('sharedprocess', environmentService.logsPath, this.initData.logLevel))); + services.set(ILogService, logService); - const mainProcessService = new MainProcessService(server, mainRouter); + // Main Process + const mainProcessService = new MainProcessService(this.server, mainRouter); services.set(IMainProcessService, mainProcessService); // Files const fileService = this._register(new FileService(logService)); services.set(IFileService, fileService); + const diskFileSystemProvider = this._register(new DiskFileSystemProvider(logService)); fileService.registerProvider(Schemas.file, diskFileSystemProvider); // Configuration const configurationService = this._register(new ConfigurationService(environmentService.settingsResource, fileService)); + services.set(IConfigurationService, configurationService); + await configurationService.initialize(); // Storage const storageService = new NativeStorageService(new GlobalStorageDatabaseChannelClient(mainProcessService.getChannel('storage')), logService, environmentService); - await storageService.initialize(); services.set(IStorageService, storageService); + + await storageService.initialize(); this._register(toDisposable(() => storageService.flush())); - services.set(IEnvironmentService, environmentService); - services.set(INativeEnvironmentService, environmentService); - + // Product services.set(IProductService, { _serviceBrand: undefined, ...product }); - services.set(ILogService, logService); - services.set(IConfigurationService, configurationService); - services.set(IRequestService, new SyncDescriptor(RequestService)); - services.set(ILoggerService, new SyncDescriptor(LoggerService)); - const nativeHostService = createChannelSender(mainProcessService.getChannel('nativeHost'), { context: configuration.windowId }); + // Request + services.set(IRequestService, new SyncDescriptor(RequestService)); + + // Native Host + const nativeHostService = createChannelSender(mainProcessService.getChannel('nativeHost'), { context: this.configuration.windowId }); services.set(INativeHostService, nativeHostService); + + // Download + services.set(IDownloadService, new SyncDescriptor(DownloadService)); + + // Extension recommendations const activeWindowManager = new ActiveWindowManager(nativeHostService); const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id)); + services.set(IExtensionRecommendationNotificationService, new ExtensionRecommendationNotificationServiceChannelClient(this.server.getChannel('IExtensionRecommendationNotificationService', activeWindowRouter))); - services.set(IDownloadService, new SyncDescriptor(DownloadService)); - services.set(IExtensionRecommendationNotificationService, new ExtensionRecommendationNotificationServiceChannelClient(server.getChannel('IExtensionRecommendationNotificationService', activeWindowRouter))); + // Logger + const loggerService = new LoggerService(logService, fileService); + services.set(ILoggerService, loggerService); - const instantiationService = new InstantiationService(services); + // Telemetry + const { appRoot, extensionsPath, extensionDevelopmentLocationURI, isBuilt, installSourcePath } = environmentService; let telemetryService: ITelemetryService; - instantiationService.invokeFunction(accessor => { - const services = new ServiceCollection(); - const { appRoot, extensionsPath, extensionDevelopmentLocationURI, isBuilt, installSourcePath } = environmentService; + let telemetryAppender: ITelemetryAppender; + if (!extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) { + telemetryAppender = new TelemetryLogAppender(loggerService, environmentService); - let telemetryAppender: ITelemetryAppender = NullAppender; - if (!extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) { - telemetryAppender = new TelemetryLogAppender(accessor.get(ILoggerService), environmentService); - if (product.aiConfig && product.aiConfig.asimovKey && isBuilt) { - const appInsightsAppender = new AppInsightsAppender(eventPrefix, null, product.aiConfig.asimovKey); - this._register(toDisposable(() => appInsightsAppender!.flush())); // Ensure the AI appender is disposed so that it flushes remaining data - telemetryAppender = combinedAppender(appInsightsAppender, telemetryAppender); - } - const config: ITelemetryServiceConfig = { - appender: telemetryAppender, - commonProperties: resolveCommonProperties(product.commit, product.version, configuration.machineId, product.msftInternalDomains, installSourcePath), - sendErrorTelemetry: true, - piiPaths: [appRoot, extensionsPath] - }; - - telemetryService = new TelemetryService(config, configurationService); - services.set(ITelemetryService, telemetryService); - } else { - telemetryService = NullTelemetryService; - services.set(ITelemetryService, NullTelemetryService); + // Application Insights + if (product.aiConfig && product.aiConfig.asimovKey && isBuilt) { + const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, product.aiConfig.asimovKey); + this._register(toDisposable(() => appInsightsAppender.flush())); // Ensure the AI appender is disposed so that it flushes remaining data + telemetryAppender = combinedAppender(appInsightsAppender, telemetryAppender); } - server.registerChannel('telemetryAppender', new TelemetryAppenderChannel(telemetryAppender)); - services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); - services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); - services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService)); - services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService)); - services.set(IExtensionTipsService, new SyncDescriptor(ExtensionTipsService)); + telemetryService = new TelemetryService({ + appender: telemetryAppender, + commonProperties: resolveCommonProperties(product.commit, product.version, this.configuration.machineId, product.msftInternalDomains, installSourcePath), + sendErrorTelemetry: true, + piiPaths: [appRoot, extensionsPath] + }, configurationService); + } else { + telemetryService = NullTelemetryService; + telemetryAppender = NullAppender; + } - services.set(IUserDataSyncAccountService, new SyncDescriptor(UserDataSyncAccountService)); - services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService)); - services.set(IUserDataSyncUtilService, new UserDataSyncUtilServiceClient(server.getChannel('userDataSyncUtil', client => client.ctx !== 'main'))); - services.set(IGlobalExtensionEnablementService, new SyncDescriptor(GlobalExtensionEnablementService)); - services.set(IIgnoredExtensionsManagementService, new SyncDescriptor(IgnoredExtensionsManagementService)); - services.set(IExtensionsStorageSyncService, new SyncDescriptor(ExtensionsStorageSyncService)); - services.set(IUserDataSyncStoreManagementService, new SyncDescriptor(UserDataSyncStoreManagementService)); - services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService)); - services.set(IUserDataSyncMachinesService, new SyncDescriptor(UserDataSyncMachinesService)); - services.set(IUserDataSyncBackupStoreService, new SyncDescriptor(UserDataSyncBackupStoreService)); - services.set(IUserDataAutoSyncEnablementService, new SyncDescriptor(UserDataAutoSyncEnablementService)); - services.set(IUserDataSyncResourceEnablementService, new SyncDescriptor(UserDataSyncResourceEnablementService)); - services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService)); - registerConfiguration(); + this.server.registerChannel('telemetryAppender', new TelemetryAppenderChannel(telemetryAppender)); + services.set(ITelemetryService, telemetryService); - const instantiationService2 = instantiationService.createChild(services); + // Extension Management + services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); - instantiationService2.invokeFunction(accessor => { + // Extension Gallery + services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); - const extensionManagementService = accessor.get(IExtensionManagementService); - const channel = new ExtensionManagementChannel(extensionManagementService, () => null); - server.registerChannel('extensions', channel); + // Extension Tips + services.set(IExtensionTipsService, new SyncDescriptor(ExtensionTipsService)); - const localizationsService = accessor.get(ILocalizationsService); - const localizationsChannel = createChannelReceiver(localizationsService); - server.registerChannel('localizations', localizationsChannel); + // Localizations + services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService)); - const diagnosticsService = accessor.get(IDiagnosticsService); - const diagnosticsChannel = createChannelReceiver(diagnosticsService); - server.registerChannel('diagnostics', diagnosticsChannel); + // Diagnostics + services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService)); - const extensionTipsService = accessor.get(IExtensionTipsService); - const extensionTipsChannel = new ExtensionTipsChannel(extensionTipsService); - server.registerChannel('extensionTipsService', extensionTipsChannel); + // Settings Sync + services.set(IUserDataSyncAccountService, new SyncDescriptor(UserDataSyncAccountService)); + services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService)); + services.set(IUserDataSyncUtilService, new UserDataSyncUtilServiceClient(this.server.getChannel('userDataSyncUtil', client => client.ctx !== 'main'))); + services.set(IGlobalExtensionEnablementService, new SyncDescriptor(GlobalExtensionEnablementService)); + services.set(IIgnoredExtensionsManagementService, new SyncDescriptor(IgnoredExtensionsManagementService)); + services.set(IExtensionsStorageSyncService, new SyncDescriptor(ExtensionsStorageSyncService)); + services.set(IUserDataSyncStoreManagementService, new SyncDescriptor(UserDataSyncStoreManagementService)); + services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService)); + services.set(IUserDataSyncMachinesService, new SyncDescriptor(UserDataSyncMachinesService)); + services.set(IUserDataSyncBackupStoreService, new SyncDescriptor(UserDataSyncBackupStoreService)); + services.set(IUserDataAutoSyncEnablementService, new SyncDescriptor(UserDataAutoSyncEnablementService)); + services.set(IUserDataSyncResourceEnablementService, new SyncDescriptor(UserDataSyncResourceEnablementService)); + services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService)); - const userDataSyncMachinesService = accessor.get(IUserDataSyncMachinesService); - const userDataSyncMachineChannel = new UserDataSyncMachinesServiceChannel(userDataSyncMachinesService); - server.registerChannel('userDataSyncMachines', userDataSyncMachineChannel); + return new InstantiationService(services); + } - const authTokenService = accessor.get(IUserDataSyncAccountService); - const authTokenChannel = new UserDataSyncAccountServiceChannel(authTokenService); - server.registerChannel('userDataSyncAccount', authTokenChannel); + private initChannels(accessor: ServicesAccessor): void { - const userDataSyncStoreManagementService = accessor.get(IUserDataSyncStoreManagementService); - const userDataSyncStoreManagementChannel = new UserDataSyncStoreManagementServiceChannel(userDataSyncStoreManagementService); - server.registerChannel('userDataSyncStoreManagement', userDataSyncStoreManagementChannel); + // Extensions Management + const extensionManagementService = accessor.get(IExtensionManagementService); + const channel = new ExtensionManagementChannel(extensionManagementService, () => null); + this.server.registerChannel('extensions', channel); - const userDataSyncService = accessor.get(IUserDataSyncService); - const userDataSyncChannel = new UserDataSyncChannel(server, userDataSyncService, logService); - server.registerChannel('userDataSync', userDataSyncChannel); + // Localizations + const localizationsService = accessor.get(ILocalizationsService); + const localizationsChannel = createChannelReceiver(localizationsService); + this.server.registerChannel('localizations', localizationsChannel); - const userDataAutoSync = instantiationService2.createInstance(UserDataAutoSyncService); - const userDataAutoSyncChannel = new UserDataAutoSyncChannel(userDataAutoSync); - server.registerChannel('userDataAutoSync', userDataAutoSyncChannel); + // Diagnostics + const diagnosticsService = accessor.get(IDiagnosticsService); + const diagnosticsChannel = createChannelReceiver(diagnosticsService); + this.server.registerChannel('diagnostics', diagnosticsChannel); - // clean up deprecated extensions - (extensionManagementService as ExtensionManagementService).removeDeprecatedExtensions(); - // update localizations cache - (localizationsService as LocalizationsService).update(); - // cache clean ups - this._register(combinedDisposable( - new NodeCachedDataCleaner(initData.nodeCachedDataDir), - instantiationService2.createInstance(LanguagePackCachedDataCleaner), - instantiationService2.createInstance(StorageDataCleaner, initData.backupWorkspacesPath), - instantiationService2.createInstance(LogsDataCleaner), - userDataAutoSync - )); - this._register(extensionManagementService as ExtensionManagementService); - }); - }); + // Extension Tips + const extensionTipsService = accessor.get(IExtensionTipsService); + const extensionTipsChannel = new ExtensionTipsChannel(extensionTipsService); + this.server.registerChannel('extensionTipsService', extensionTipsChannel); + + // Settings Sync + const userDataSyncMachinesService = accessor.get(IUserDataSyncMachinesService); + const userDataSyncMachineChannel = new UserDataSyncMachinesServiceChannel(userDataSyncMachinesService); + this.server.registerChannel('userDataSyncMachines', userDataSyncMachineChannel); + + const authTokenService = accessor.get(IUserDataSyncAccountService); + const authTokenChannel = new UserDataSyncAccountServiceChannel(authTokenService); + this.server.registerChannel('userDataSyncAccount', authTokenChannel); + + const userDataSyncStoreManagementService = accessor.get(IUserDataSyncStoreManagementService); + const userDataSyncStoreManagementChannel = new UserDataSyncStoreManagementServiceChannel(userDataSyncStoreManagementService); + this.server.registerChannel('userDataSyncStoreManagement', userDataSyncStoreManagementChannel); + + const userDataSyncService = accessor.get(IUserDataSyncService); + const userDataSyncChannel = new UserDataSyncChannel(this.server, userDataSyncService, accessor.get(ILogService)); + this.server.registerChannel('userDataSync', userDataSyncChannel); + + const userDataAutoSync = this._register(accessor.get(IInstantiationService).createInstance(UserDataAutoSyncService)); + const userDataAutoSyncChannel = new UserDataAutoSyncChannel(userDataAutoSync); + this.server.registerChannel('userDataAutoSync', userDataAutoSyncChannel); } } @@ -318,7 +372,7 @@ export async function main(configuration: ISharedProcessConfiguration): Promise< ipcRenderer.send('vscode:shared-process->electron-main=ipc-ready'); // await initialization and signal this back to electron-main - const sharedProcess = new SharedProcessMain(); - await sharedProcess.init(server, initData, configuration); + const sharedProcess = new SharedProcessMain(server, initData, configuration); + await sharedProcess.open(); ipcRenderer.send('vscode:shared-process->electron-main=init-done'); } diff --git a/src/vs/platform/log/node/loggerService.ts b/src/vs/platform/log/node/loggerService.ts index 7120d99d213..49fe8ad4579 100644 --- a/src/vs/platform/log/node/loggerService.ts +++ b/src/vs/platform/log/node/loggerService.ts @@ -9,8 +9,8 @@ import { URI } from 'vs/base/common/uri'; import { basename, extname, dirname } from 'vs/base/common/resources'; import { Schemas } from 'vs/base/common/network'; import { FileLogService } from 'vs/platform/log/common/fileLogService'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { SpdLogService } from 'vs/platform/log/node/spdlogService'; +import { IFileService } from 'vs/platform/files/common/files'; export class LoggerService extends Disposable implements ILoggerService { @@ -20,7 +20,7 @@ export class LoggerService extends Disposable implements ILoggerService { constructor( @ILogService private logService: ILogService, - @IInstantiationService private instantiationService: IInstantiationService, + @IFileService private fileService: IFileService ) { super(); this._register(logService.onDidChangeLogLevel(level => this.loggers.forEach(logger => logger.setLevel(level)))); @@ -34,7 +34,7 @@ export class LoggerService extends Disposable implements ILoggerService { const ext = extname(resource); logger = new SpdLogService(baseName.substring(0, baseName.length - ext.length), dirname(resource).fsPath, this.logService.getLevel()); } else { - logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel()); + logger = new FileLogService(basename(resource), resource, this.logService.getLevel(), this.fileService); } this.loggers.set(resource.toString(), logger); }