diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 6cf2921a795..08e7fda1ad1 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -28,7 +28,7 @@ import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender'; import { ActiveWindowManager } from 'vs/platform/windows/node/windows'; import { ipcRenderer } from 'electron'; -import { ILogService, LogLevel } from 'vs/platform/log/common/log'; +import { ILogService, LogLevel, ILoggerService } from 'vs/platform/log/common/log'; import { LoggerChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; import { LocalizationsService } from 'vs/platform/localizations/node/localizations'; import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; @@ -50,13 +50,15 @@ import { IFileService } from 'vs/platform/files/common/files'; import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider'; import { Schemas } from 'vs/base/common/network'; import { IProductService } from 'vs/platform/product/common/productService'; -import { IUserDataSyncService, IUserDataSyncStoreService, ISettingsMergeService, registerConfiguration } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserDataSyncService, IUserDataSyncStoreService, ISettingsMergeService, registerConfiguration, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; import { UserDataSyncService, UserDataAutoSync } from 'vs/platform/userDataSync/common/userDataSyncService'; import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc'; import { SettingsMergeChannelClient } from 'vs/platform/userDataSync/common/settingsSyncIpc'; import { createChannelSender } from 'vs/platform/ipc/node/ipcChannelCreator'; import { IElectronService } from 'vs/platform/electron/node/electron'; +import { LoggerService } from 'vs/platform/log/node/loggerService'; +import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog'; export interface ISharedProcessConfiguration { readonly machineId: string; @@ -117,10 +119,17 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat services.set(ILogService, logService); services.set(IConfigurationService, configurationService); services.set(IRequestService, new SyncDescriptor(RequestService)); + services.set(ILoggerService, new SyncDescriptor(LoggerService)); const mainProcessService = new MainProcessService(server, mainRouter); services.set(IMainProcessService, mainProcessService); + const electronService = createChannelSender(mainProcessService.getChannel('electron'), { context: configuration.windowId }); + services.set(IElectronService, electronService); + + const activeWindowManager = new ActiveWindowManager(electronService); + const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id)); + // Files const fileService = new FileService(logService); services.set(IFileService, fileService); @@ -168,12 +177,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService)); services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService)); - const electronService = createChannelSender(mainProcessService.getChannel('electron'), { context: configuration.windowId }); - services.set(IElectronService, electronService); - - // User Data Sync Contributions - const activeWindowManager = new ActiveWindowManager(electronService); - const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id)); + services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService)); const settingsMergeChannel = server.getChannel('settingsMerge', activeWindowRouter); services.set(ISettingsMergeService, new SettingsMergeChannelClient(settingsMergeChannel)); services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService)); diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index fdd4e9997a0..789bb4c805f 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -114,11 +114,14 @@ export interface IEnvironmentService { // user roaming data userRoamingDataHome: URI; settingsResource: URI; - settingsSyncPreviewResource: URI; keybindingsResource: URI; keyboardLayoutResource: URI; localeResource: URI; + // sync resources + userDataSyncLogResource: URI; + settingsSyncPreviewResource: URI; + machineSettingsHome: URI; machineSettingsResource: URI; diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index 0df72e178ad..f7d207009de 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -119,6 +119,9 @@ export class EnvironmentService implements IEnvironmentService { @memoize get settingsSyncPreviewResource(): URI { return resources.joinPath(this.userRoamingDataHome, '.settings.json'); } + @memoize + get userDataSyncLogResource(): URI { return URI.file(path.join(this.logsPath, 'userDataSync.log')); } + @memoize get machineSettingsHome(): URI { return URI.file(path.join(this.userDataPath, 'Machine')); } diff --git a/src/vs/platform/log/common/fileLogService.ts b/src/vs/platform/log/common/fileLogService.ts index f9b600063bf..5d013e7defb 100644 --- a/src/vs/platform/log/common/fileLogService.ts +++ b/src/vs/platform/log/common/fileLogService.ts @@ -3,12 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ILogService, LogLevel, AbstractLogService } from 'vs/platform/log/common/log'; +import { ILogService, LogLevel, AbstractLogService, ILoggerService, ILogger } from 'vs/platform/log/common/log'; import { URI } from 'vs/base/common/uri'; import { IFileService } from 'vs/platform/files/common/files'; import { Queue } from 'vs/base/common/async'; import { VSBuffer } from 'vs/base/common/buffer'; import { dirname, joinPath, basename } from 'vs/base/common/resources'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; const MAX_FILE_SIZE = 1024 * 1024 * 5; @@ -16,6 +18,7 @@ export class FileLogService extends AbstractLogService implements ILogService { _serviceBrand: undefined; + private readonly initializePromise: Promise; private readonly queue: Queue; private backupIndex: number = 1; @@ -28,6 +31,7 @@ export class FileLogService extends AbstractLogService implements ILogService { super(); this.setLevel(level); this.queue = this._register(new Queue()); + this.initializePromise = this.initialize(); } trace(): void { @@ -82,8 +86,13 @@ export class FileLogService extends AbstractLogService implements ILogService { this._log(level, this.format(args)); } + private async initialize(): Promise { + await this.fileService.createFile(this.resource); + } + private _log(level: LogLevel, message: string): void { this.queue.queue(async () => { + await this.initializePromise; let content = await this.loadContent(); if (content.length > MAX_FILE_SIZE) { await this.fileService.writeFile(this.getBackupResource(), VSBuffer.fromString(content)); @@ -145,3 +154,33 @@ export class FileLogService extends AbstractLogService implements ILogService { return result; } } + +export class FileLoggerService extends Disposable implements ILoggerService { + + _serviceBrand: undefined; + + private readonly loggers = new Map(); + + constructor( + @ILogService private logService: ILogService, + @IInstantiationService private instantiationService: IInstantiationService, + ) { + super(); + this._register(logService.onDidChangeLogLevel(level => this.loggers.forEach(logger => logger.setLevel(level)))); + } + + getLogger(resource: URI): ILogger { + let logger = this.loggers.get(resource.toString()); + if (!logger) { + logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel()); + this.loggers.set(resource.toString(), logger); + } + return logger; + } + + dispose(): void { + this.loggers.forEach(logger => logger.dispose()); + this.loggers.clear(); + super.dispose(); + } +} diff --git a/src/vs/platform/log/common/log.ts b/src/vs/platform/log/common/log.ts index 0009b304e53..3c7feb1e9b1 100644 --- a/src/vs/platform/log/common/log.ts +++ b/src/vs/platform/log/common/log.ts @@ -9,8 +9,10 @@ import { isWindows } from 'vs/base/common/platform'; import { Event, Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { LoggerChannelClient } from 'vs/platform/log/common/logIpc'; +import { URI } from 'vs/base/common/uri'; export const ILogService = createServiceDecorator('logService'); +export const ILoggerService = createServiceDecorator('loggerService'); function now(): string { return new Date().toISOString(); @@ -28,12 +30,11 @@ export enum LogLevel { export const DEFAULT_LOG_LEVEL: LogLevel = LogLevel.Info; -export interface ILogService extends IDisposable { - _serviceBrand: undefined; +export interface ILogger extends IDisposable { onDidChangeLogLevel: Event; - getLevel(): LogLevel; setLevel(level: LogLevel): void; + trace(message: string, ...args: any[]): void; debug(message: string, ...args: any[]): void; info(message: string, ...args: any[]): void; @@ -42,6 +43,16 @@ export interface ILogService extends IDisposable { critical(message: string | Error, ...args: any[]): void; } +export interface ILogService extends ILogger { + _serviceBrand: undefined; +} + +export interface ILoggerService { + _serviceBrand: undefined; + + getLogger(file: URI): ILogger; +} + export abstract class AbstractLogService extends Disposable { private level: LogLevel = DEFAULT_LOG_LEVEL; diff --git a/src/vs/platform/log/node/loggerService.ts b/src/vs/platform/log/node/loggerService.ts new file mode 100644 index 00000000000..f2ab74d4ba8 --- /dev/null +++ b/src/vs/platform/log/node/loggerService.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ILogService, ILoggerService, ILogger } from 'vs/platform/log/common/log'; +import { Disposable } from 'vs/base/common/lifecycle'; +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'; + +export class LoggerService extends Disposable implements ILoggerService { + + _serviceBrand: undefined; + + private readonly loggers = new Map(); + + constructor( + @ILogService private logService: ILogService, + @IInstantiationService private instantiationService: IInstantiationService, + ) { + super(); + this._register(logService.onDidChangeLogLevel(level => this.loggers.forEach(logger => logger.setLevel(level)))); + } + + getLogger(resource: URI): ILogger { + let logger = this.loggers.get(resource.toString()); + if (!logger) { + if (resource.scheme === Schemas.file) { + const baseName = basename(resource); + const ext = extname(resource); + logger = new SpdLogService(baseName.substring(0, baseName.length - ext.length), dirname(resource).path, this.logService.getLevel()); + } else { + logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel()); + } + this.loggers.set(resource.toString(), logger); + } + return logger; + } + + dispose(): void { + this.loggers.forEach(logger => logger.dispose()); + this.loggers.clear(); + super.dispose(); + } +} + diff --git a/src/vs/platform/userDataSync/common/extensionsSync.ts b/src/vs/platform/userDataSync/common/extensionsSync.ts index b3ef2e6cd81..7da549b2dd6 100644 --- a/src/vs/platform/userDataSync/common/extensionsSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsSync.ts @@ -4,10 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable } from 'vs/base/common/lifecycle'; -import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, IUserDataSyncStoreService, ISyncExtension } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; import { VSBuffer } from 'vs/base/common/buffer'; import { Emitter, Event } from 'vs/base/common/event'; -import { ILogService } from 'vs/platform/log/common/log'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { URI } from 'vs/base/common/uri'; import { joinPath } from 'vs/base/common/resources'; @@ -47,7 +46,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser @IFileService private readonly fileService: IFileService, @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService, @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, - @ILogService private readonly logService: ILogService, + @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService, @IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService, @IConfigurationService private readonly configurationService: IConfigurationService, ) { diff --git a/src/vs/platform/userDataSync/common/settingsSync.ts b/src/vs/platform/userDataSync/common/settingsSync.ts index efb78c6d2ab..db63e678203 100644 --- a/src/vs/platform/userDataSync/common/settingsSync.ts +++ b/src/vs/platform/userDataSync/common/settingsSync.ts @@ -5,12 +5,11 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IFileService, FileSystemProviderErrorCode, FileSystemProviderError, IFileContent } from 'vs/platform/files/common/files'; -import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, ISettingsMergeService, IUserDataSyncStoreService, DEFAULT_IGNORED_SETTINGS } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, ISettingsMergeService, IUserDataSyncStoreService, DEFAULT_IGNORED_SETTINGS, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; import { VSBuffer } from 'vs/base/common/buffer'; import { parse, ParseError } from 'vs/base/common/json'; import { localize } from 'vs/nls'; import { Emitter, Event } from 'vs/base/common/event'; -import { ILogService } from 'vs/platform/log/common/log'; import { CancelablePromise, createCancelablePromise, ThrottledDelayer } from 'vs/base/common/async'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { URI } from 'vs/base/common/uri'; @@ -49,7 +48,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { @IEnvironmentService private readonly environmentService: IEnvironmentService, @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService, @ISettingsMergeService private readonly settingsMergeService: ISettingsMergeService, - @ILogService private readonly logService: ILogService, + @IUserDataSyncLogService private readonly logService: IUserDataSyncLogService, @IConfigurationService private readonly configurationService: IConfigurationService, ) { super(); @@ -93,11 +92,13 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { return false; } + this.logService.trace('Synchronising Settings...'); this.setStatus(SyncStatus.Syncing); try { const result = await this.getPreview(); if (result.hasConflicts) { + this.logService.info('Detected conflicts while synchronising Settings. Suspended until conflicts are resolved.'); this.setStatus(SyncStatus.HasConflicts); return false; } @@ -126,6 +127,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { this.syncPreviewResultPromise = null; } this.fileService.del(this.environmentService.settingsSyncPreviewResource); + this.logService.trace('Stopped Synchronising Settings.'); this.setStatus(SyncStatus.Idle); } @@ -166,6 +168,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser { await this.fileService.del(this.environmentService.settingsSyncPreviewResource); } + this.logService.trace('Finised Synchronising Settings.'); this.syncPreviewResultPromise = null; this.setStatus(SyncStatus.Idle); } diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index d62bb770fcc..8a647c47807 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -13,6 +13,7 @@ import { localize } from 'vs/nls'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; +import { ILogService } from 'vs/platform/log/common/log'; export const DEFAULT_IGNORED_SETTINGS = [ 'configurationSync.enable', @@ -162,4 +163,10 @@ export interface ISettingsMergeService { } +export const IUserDataSyncLogService = createDecorator('IUserDataSyncLogService'); + +export interface IUserDataSyncLogService extends ILogService { + +} + export const CONTEXT_SYNC_STATE = new RawContextKey('syncStatus', SyncStatus.Uninitialized); diff --git a/src/vs/platform/userDataSync/common/userDataSyncLog.ts b/src/vs/platform/userDataSync/common/userDataSyncLog.ts new file mode 100644 index 00000000000..b8abaee8089 --- /dev/null +++ b/src/vs/platform/userDataSync/common/userDataSyncLog.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; +import { AbstractLogService, ILoggerService, ILogger } from 'vs/platform/log/common/log'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; + +export class UserDataSyncLogService extends AbstractLogService implements IUserDataSyncLogService { + + _serviceBrand: undefined; + private readonly logger: ILogger; + + constructor( + @ILoggerService loggerService: ILoggerService, + @IEnvironmentService environmentService: IEnvironmentService + ) { + super(); + this.logger = this._register(loggerService.getLogger(environmentService.userDataSyncLogResource)); + } + + trace(message: string, ...args: any[]): void { + this.logger.trace(message, ...args); + } + + debug(message: string, ...args: any[]): void { + this.logger.debug(message, ...args); + } + + info(message: string, ...args: any[]): void { + this.logger.info(message, ...args); + } + + warn(message: string, ...args: any[]): void { + this.logger.warn(message, ...args); + } + + error(message: string | Error, ...args: any[]): void { + this.logger.error(message, ...args); + } + + critical(message: string | Error, ...args: any[]): void { + this.logger.critical(message, ...args); + } + +} diff --git a/src/vs/workbench/contrib/logs/common/logConstants.ts b/src/vs/workbench/contrib/logs/common/logConstants.ts index e0d6d16c883..ca22b9947bc 100644 --- a/src/vs/workbench/contrib/logs/common/logConstants.ts +++ b/src/vs/workbench/contrib/logs/common/logConstants.ts @@ -7,4 +7,5 @@ export const mainLogChannelId = 'mainLog'; export const sharedLogChannelId = 'sharedLog'; export const rendererLogChannelId = 'rendererLog'; export const extHostLogChannelId = 'extHostLog'; -export const telemetryLogChannelId = 'telemetryLog'; \ No newline at end of file +export const telemetryLogChannelId = 'telemetryLog'; +export const userDataSyncLogChannelId = 'userDataSyncLog'; diff --git a/src/vs/workbench/contrib/logs/common/logs.contribution.ts b/src/vs/workbench/contrib/logs/common/logs.contribution.ts index ab29875c3c3..5fcf011d725 100644 --- a/src/vs/workbench/contrib/logs/common/logs.contribution.ts +++ b/src/vs/workbench/contrib/logs/common/logs.contribution.ts @@ -22,6 +22,7 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { isWeb } from 'vs/base/common/platform'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { LogsDataCleaner } from 'vs/workbench/contrib/logs/common/logsDataCleaner'; +import { IProductService } from 'vs/platform/product/common/productService'; const workbenchActionsRegistry = Registry.as(WorkbenchActionExtensions.WorkbenchActions); const devCategory = nls.localize('developer', "Developer"); @@ -33,9 +34,11 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution { @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @ILogService private readonly logService: ILogService, @IFileService private readonly fileService: IFileService, - @IInstantiationService private readonly instantiationService: IInstantiationService + @IInstantiationService private readonly instantiationService: IInstantiationService, + @IProductService private readonly productService: IProductService ) { super(); + this.registerCommonContributions(); if (isWeb) { this.registerWebContributions(); } else { @@ -43,8 +46,14 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution { } } + private registerCommonContributions(): void { + if (this.productService.settingsSyncStoreUrl) { + this.registerLogChannel(Constants.userDataSyncLogChannelId, nls.localize('userDataSyncLog', "Configuration Sync"), this.environmentService.userDataSyncLogResource); + } + this.registerLogChannel(Constants.rendererLogChannelId, nls.localize('rendererLog', "Window"), this.environmentService.logFile); + } + private registerWebContributions(): void { - Registry.as(OutputExt.OutputChannels).registerChannel({ id: Constants.rendererLogChannelId, label: nls.localize('rendererLog', "Window"), file: this.environmentService.logFile, log: true }); this.instantiationService.createInstance(LogsDataCleaner); const workbenchActionsRegistry = Registry.as(WorkbenchActionExtensions.WorkbenchActions); @@ -55,7 +64,6 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution { private registerNativeContributions(): void { this.registerLogChannel(Constants.mainLogChannelId, nls.localize('mainLog', "Main"), URI.file(join(this.environmentService.logsPath, `main.log`))); this.registerLogChannel(Constants.sharedLogChannelId, nls.localize('sharedLog', "Shared"), URI.file(join(this.environmentService.logsPath, `sharedprocess.log`))); - this.registerLogChannel(Constants.rendererLogChannelId, nls.localize('rendererLog', "Window"), this.environmentService.logFile); const registerTelemetryChannel = (level: LogLevel) => { if (level === LogLevel.Trace && !Registry.as(OutputExt.OutputChannels).getChannel(Constants.telemetryLogChannelId)) { @@ -76,7 +84,7 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution { const watcher = this.fileService.watch(dirname(file)); const disposable = this.fileService.onFileChanges(e => { - if (e.contains(file, FileChangeType.ADDED)) { + if (e.contains(file, FileChangeType.ADDED) || e.contains(file, FileChangeType.UPDATED)) { watcher.dispose(); disposable.dispose(); outputChannelRegistry.registerChannel({ id, label, file, log: true }); diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 5bc8466e190..ee56e84cdc4 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -85,6 +85,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment this.userRoamingDataHome = URI.file('/User').with({ scheme: Schemas.userData }); this.settingsResource = joinPath(this.userRoamingDataHome, 'settings.json'); this.settingsSyncPreviewResource = joinPath(this.userRoamingDataHome, '.settings.json'); + this.userDataSyncLogResource = joinPath(options.logsPath, 'userDataSync.log'); this.keybindingsResource = joinPath(this.userRoamingDataHome, 'keybindings.json'); this.keyboardLayoutResource = joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); this.localeResource = joinPath(this.userRoamingDataHome, 'locale.json'); @@ -142,10 +143,11 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment appSettingsHome: URI; userRoamingDataHome: URI; settingsResource: URI; - settingsSyncPreviewResource: URI; keybindingsResource: URI; keyboardLayoutResource: URI; localeResource: URI; + settingsSyncPreviewResource: URI; + userDataSyncLogResource: URI; machineSettingsHome: URI; machineSettingsResource: URI; globalStorageHome: string; diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index 9545c435ea9..323c5f83a3e 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -62,7 +62,10 @@ import { IExtensionManagementService } from 'vs/platform/extensionManagement/com import { ExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagementService'; import { ITunnelService } from 'vs/platform/remote/common/tunnel'; import { NoOpTunnelService } from 'vs/platform/remote/common/tunnelService'; -import { IUserDataSyncStoreService, IUserDataSyncService } from 'vs/platform/userDataSync/common/userDataSync'; +import { ILoggerService } from 'vs/platform/log/common/log'; +import { FileLoggerService } from 'vs/platform/log/common/fileLogService'; +import { IUserDataSyncStoreService, IUserDataSyncService, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync'; +import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog'; import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; @@ -75,6 +78,8 @@ registerSingleton(IAccessibilityService, BrowserAccessibilityService, true); registerSingleton(ILifecycleService, BrowserLifecycleService); registerSingleton(IContextMenuService, ContextMenuService); registerSingleton(ITunnelService, NoOpTunnelService, true); +registerSingleton(ILoggerService, FileLoggerService); +registerSingleton(IUserDataSyncLogService, UserDataSyncLogService); registerSingleton(IUserDataSyncStoreService, UserDataSyncStoreService); registerSingleton(IUserDataSyncService, UserDataSyncService); registerSingleton(IWorkspaceEditingService, WorkspaceEditingService, true);