Skip to content

Commit e77bded

Browse files
committed
Introduce output log channel for configuration sync
1 parent 156b5fd commit e77bded

14 files changed

Lines changed: 208 additions & 26 deletions

File tree

src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry
2828
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
2929
import { ActiveWindowManager } from 'vs/platform/windows/node/windows';
3030
import { ipcRenderer } from 'electron';
31-
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
31+
import { ILogService, LogLevel, ILoggerService } from 'vs/platform/log/common/log';
3232
import { LoggerChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
3333
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
3434
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
@@ -50,13 +50,15 @@ import { IFileService } from 'vs/platform/files/common/files';
5050
import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider';
5151
import { Schemas } from 'vs/base/common/network';
5252
import { IProductService } from 'vs/platform/product/common/productService';
53-
import { IUserDataSyncService, IUserDataSyncStoreService, ISettingsMergeService, registerConfiguration } from 'vs/platform/userDataSync/common/userDataSync';
53+
import { IUserDataSyncService, IUserDataSyncStoreService, ISettingsMergeService, registerConfiguration, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync';
5454
import { UserDataSyncService, UserDataAutoSync } from 'vs/platform/userDataSync/common/userDataSyncService';
5555
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
5656
import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
5757
import { SettingsMergeChannelClient } from 'vs/platform/userDataSync/common/settingsSyncIpc';
5858
import { createChannelSender } from 'vs/platform/ipc/node/ipcChannelCreator';
5959
import { IElectronService } from 'vs/platform/electron/node/electron';
60+
import { LoggerService } from 'vs/platform/log/node/loggerService';
61+
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
6062

6163
export interface ISharedProcessConfiguration {
6264
readonly machineId: string;
@@ -117,10 +119,17 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
117119
services.set(ILogService, logService);
118120
services.set(IConfigurationService, configurationService);
119121
services.set(IRequestService, new SyncDescriptor(RequestService));
122+
services.set(ILoggerService, new SyncDescriptor(LoggerService));
120123

121124
const mainProcessService = new MainProcessService(server, mainRouter);
122125
services.set(IMainProcessService, mainProcessService);
123126

127+
const electronService = createChannelSender<IElectronService>(mainProcessService.getChannel('electron'), { context: configuration.windowId });
128+
services.set(IElectronService, electronService);
129+
130+
const activeWindowManager = new ActiveWindowManager(electronService);
131+
const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id));
132+
124133
// Files
125134
const fileService = new FileService(logService);
126135
services.set(IFileService, fileService);
@@ -168,12 +177,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
168177
services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService));
169178
services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService));
170179

171-
const electronService = createChannelSender<IElectronService>(mainProcessService.getChannel('electron'), { context: configuration.windowId });
172-
services.set(IElectronService, electronService);
173-
174-
// User Data Sync Contributions
175-
const activeWindowManager = new ActiveWindowManager(electronService);
176-
const activeWindowRouter = new StaticRouter(ctx => activeWindowManager.getActiveClientId().then(id => ctx === id));
180+
services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService));
177181
const settingsMergeChannel = server.getChannel('settingsMerge', activeWindowRouter);
178182
services.set(ISettingsMergeService, new SettingsMergeChannelClient(settingsMergeChannel));
179183
services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService));

src/vs/platform/environment/common/environment.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,14 @@ export interface IEnvironmentService {
114114
// user roaming data
115115
userRoamingDataHome: URI;
116116
settingsResource: URI;
117-
settingsSyncPreviewResource: URI;
118117
keybindingsResource: URI;
119118
keyboardLayoutResource: URI;
120119
localeResource: URI;
121120

121+
// sync resources
122+
userDataSyncLogResource: URI;
123+
settingsSyncPreviewResource: URI;
124+
122125
machineSettingsHome: URI;
123126
machineSettingsResource: URI;
124127

src/vs/platform/environment/node/environmentService.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ export class EnvironmentService implements IEnvironmentService {
119119
@memoize
120120
get settingsSyncPreviewResource(): URI { return resources.joinPath(this.userRoamingDataHome, '.settings.json'); }
121121

122+
@memoize
123+
get userDataSyncLogResource(): URI { return URI.file(path.join(this.logsPath, 'userDataSync.log')); }
124+
122125
@memoize
123126
get machineSettingsHome(): URI { return URI.file(path.join(this.userDataPath, 'Machine')); }
124127

src/vs/platform/log/common/fileLogService.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { ILogService, LogLevel, AbstractLogService } from 'vs/platform/log/common/log';
6+
import { ILogService, LogLevel, AbstractLogService, ILoggerService, ILogger } from 'vs/platform/log/common/log';
77
import { URI } from 'vs/base/common/uri';
88
import { IFileService } from 'vs/platform/files/common/files';
99
import { Queue } from 'vs/base/common/async';
1010
import { VSBuffer } from 'vs/base/common/buffer';
1111
import { dirname, joinPath, basename } from 'vs/base/common/resources';
12+
import { Disposable } from 'vs/base/common/lifecycle';
13+
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1214

1315
const MAX_FILE_SIZE = 1024 * 1024 * 5;
1416

1517
export class FileLogService extends AbstractLogService implements ILogService {
1618

1719
_serviceBrand: undefined;
1820

21+
private readonly initializePromise: Promise<void>;
1922
private readonly queue: Queue<void>;
2023
private backupIndex: number = 1;
2124

@@ -28,6 +31,7 @@ export class FileLogService extends AbstractLogService implements ILogService {
2831
super();
2932
this.setLevel(level);
3033
this.queue = this._register(new Queue<void>());
34+
this.initializePromise = this.initialize();
3135
}
3236

3337
trace(): void {
@@ -82,8 +86,13 @@ export class FileLogService extends AbstractLogService implements ILogService {
8286
this._log(level, this.format(args));
8387
}
8488

89+
private async initialize(): Promise<void> {
90+
await this.fileService.createFile(this.resource);
91+
}
92+
8593
private _log(level: LogLevel, message: string): void {
8694
this.queue.queue(async () => {
95+
await this.initializePromise;
8796
let content = await this.loadContent();
8897
if (content.length > MAX_FILE_SIZE) {
8998
await this.fileService.writeFile(this.getBackupResource(), VSBuffer.fromString(content));
@@ -145,3 +154,33 @@ export class FileLogService extends AbstractLogService implements ILogService {
145154
return result;
146155
}
147156
}
157+
158+
export class FileLoggerService extends Disposable implements ILoggerService {
159+
160+
_serviceBrand: undefined;
161+
162+
private readonly loggers = new Map<string, ILogger>();
163+
164+
constructor(
165+
@ILogService private logService: ILogService,
166+
@IInstantiationService private instantiationService: IInstantiationService,
167+
) {
168+
super();
169+
this._register(logService.onDidChangeLogLevel(level => this.loggers.forEach(logger => logger.setLevel(level))));
170+
}
171+
172+
getLogger(resource: URI): ILogger {
173+
let logger = this.loggers.get(resource.toString());
174+
if (!logger) {
175+
logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel());
176+
this.loggers.set(resource.toString(), logger);
177+
}
178+
return logger;
179+
}
180+
181+
dispose(): void {
182+
this.loggers.forEach(logger => logger.dispose());
183+
this.loggers.clear();
184+
super.dispose();
185+
}
186+
}

src/vs/platform/log/common/log.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import { isWindows } from 'vs/base/common/platform';
99
import { Event, Emitter } from 'vs/base/common/event';
1010
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
1111
import { LoggerChannelClient } from 'vs/platform/log/common/logIpc';
12+
import { URI } from 'vs/base/common/uri';
1213

1314
export const ILogService = createServiceDecorator<ILogService>('logService');
15+
export const ILoggerService = createServiceDecorator<ILoggerService>('loggerService');
1416

1517
function now(): string {
1618
return new Date().toISOString();
@@ -28,12 +30,11 @@ export enum LogLevel {
2830

2931
export const DEFAULT_LOG_LEVEL: LogLevel = LogLevel.Info;
3032

31-
export interface ILogService extends IDisposable {
32-
_serviceBrand: undefined;
33+
export interface ILogger extends IDisposable {
3334
onDidChangeLogLevel: Event<LogLevel>;
34-
3535
getLevel(): LogLevel;
3636
setLevel(level: LogLevel): void;
37+
3738
trace(message: string, ...args: any[]): void;
3839
debug(message: string, ...args: any[]): void;
3940
info(message: string, ...args: any[]): void;
@@ -42,6 +43,16 @@ export interface ILogService extends IDisposable {
4243
critical(message: string | Error, ...args: any[]): void;
4344
}
4445

46+
export interface ILogService extends ILogger {
47+
_serviceBrand: undefined;
48+
}
49+
50+
export interface ILoggerService {
51+
_serviceBrand: undefined;
52+
53+
getLogger(file: URI): ILogger;
54+
}
55+
4556
export abstract class AbstractLogService extends Disposable {
4657

4758
private level: LogLevel = DEFAULT_LOG_LEVEL;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { ILogService, ILoggerService, ILogger } from 'vs/platform/log/common/log';
7+
import { Disposable } from 'vs/base/common/lifecycle';
8+
import { URI } from 'vs/base/common/uri';
9+
import { basename, extname, dirname } from 'vs/base/common/resources';
10+
import { Schemas } from 'vs/base/common/network';
11+
import { FileLogService } from 'vs/platform/log/common/fileLogService';
12+
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
13+
import { SpdLogService } from 'vs/platform/log/node/spdlogService';
14+
15+
export class LoggerService extends Disposable implements ILoggerService {
16+
17+
_serviceBrand: undefined;
18+
19+
private readonly loggers = new Map<string, ILogger>();
20+
21+
constructor(
22+
@ILogService private logService: ILogService,
23+
@IInstantiationService private instantiationService: IInstantiationService,
24+
) {
25+
super();
26+
this._register(logService.onDidChangeLogLevel(level => this.loggers.forEach(logger => logger.setLevel(level))));
27+
}
28+
29+
getLogger(resource: URI): ILogger {
30+
let logger = this.loggers.get(resource.toString());
31+
if (!logger) {
32+
if (resource.scheme === Schemas.file) {
33+
const baseName = basename(resource);
34+
const ext = extname(resource);
35+
logger = new SpdLogService(baseName.substring(0, baseName.length - ext.length), dirname(resource).path, this.logService.getLevel());
36+
} else {
37+
logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel());
38+
}
39+
this.loggers.set(resource.toString(), logger);
40+
}
41+
return logger;
42+
}
43+
44+
dispose(): void {
45+
this.loggers.forEach(logger => logger.dispose());
46+
this.loggers.clear();
47+
super.dispose();
48+
}
49+
}
50+

src/vs/platform/userDataSync/common/extensionsSync.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { Disposable } from 'vs/base/common/lifecycle';
7-
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, IUserDataSyncStoreService, ISyncExtension } from 'vs/platform/userDataSync/common/userDataSync';
7+
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync';
88
import { VSBuffer } from 'vs/base/common/buffer';
99
import { Emitter, Event } from 'vs/base/common/event';
10-
import { ILogService } from 'vs/platform/log/common/log';
1110
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
1211
import { URI } from 'vs/base/common/uri';
1312
import { joinPath } from 'vs/base/common/resources';
@@ -47,7 +46,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
4746
@IFileService private readonly fileService: IFileService,
4847
@IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,
4948
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
50-
@ILogService private readonly logService: ILogService,
49+
@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
5150
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
5251
@IConfigurationService private readonly configurationService: IConfigurationService,
5352
) {

src/vs/platform/userDataSync/common/settingsSync.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55

66
import { Disposable } from 'vs/base/common/lifecycle';
77
import { IFileService, FileSystemProviderErrorCode, FileSystemProviderError, IFileContent } from 'vs/platform/files/common/files';
8-
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, ISettingsMergeService, IUserDataSyncStoreService, DEFAULT_IGNORED_SETTINGS } from 'vs/platform/userDataSync/common/userDataSync';
8+
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, ISettingsMergeService, IUserDataSyncStoreService, DEFAULT_IGNORED_SETTINGS, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync';
99
import { VSBuffer } from 'vs/base/common/buffer';
1010
import { parse, ParseError } from 'vs/base/common/json';
1111
import { localize } from 'vs/nls';
1212
import { Emitter, Event } from 'vs/base/common/event';
13-
import { ILogService } from 'vs/platform/log/common/log';
1413
import { CancelablePromise, createCancelablePromise, ThrottledDelayer } from 'vs/base/common/async';
1514
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
1615
import { URI } from 'vs/base/common/uri';
@@ -49,7 +48,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
4948
@IEnvironmentService private readonly environmentService: IEnvironmentService,
5049
@IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,
5150
@ISettingsMergeService private readonly settingsMergeService: ISettingsMergeService,
52-
@ILogService private readonly logService: ILogService,
51+
@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
5352
@IConfigurationService private readonly configurationService: IConfigurationService,
5453
) {
5554
super();
@@ -93,11 +92,13 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
9392
return false;
9493
}
9594

95+
this.logService.trace('Synchronising Settings...');
9696
this.setStatus(SyncStatus.Syncing);
9797

9898
try {
9999
const result = await this.getPreview();
100100
if (result.hasConflicts) {
101+
this.logService.info('Detected conflicts while synchronising Settings. Suspended until conflicts are resolved.');
101102
this.setStatus(SyncStatus.HasConflicts);
102103
return false;
103104
}
@@ -126,6 +127,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
126127
this.syncPreviewResultPromise = null;
127128
}
128129
this.fileService.del(this.environmentService.settingsSyncPreviewResource);
130+
this.logService.trace('Stopped Synchronising Settings.');
129131
this.setStatus(SyncStatus.Idle);
130132
}
131133

@@ -166,6 +168,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
166168
await this.fileService.del(this.environmentService.settingsSyncPreviewResource);
167169
}
168170

171+
this.logService.trace('Finised Synchronising Settings.');
169172
this.syncPreviewResultPromise = null;
170173
this.setStatus(SyncStatus.Idle);
171174
}

src/vs/platform/userDataSync/common/userDataSync.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { localize } from 'vs/nls';
1313
import { IDisposable } from 'vs/base/common/lifecycle';
1414
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
1515
import { IJSONSchema } from 'vs/base/common/jsonSchema';
16+
import { ILogService } from 'vs/platform/log/common/log';
1617

1718
export const DEFAULT_IGNORED_SETTINGS = [
1819
'configurationSync.enable',
@@ -162,4 +163,10 @@ export interface ISettingsMergeService {
162163

163164
}
164165

166+
export const IUserDataSyncLogService = createDecorator<IUserDataSyncLogService>('IUserDataSyncLogService');
167+
168+
export interface IUserDataSyncLogService extends ILogService {
169+
170+
}
171+
165172
export const CONTEXT_SYNC_STATE = new RawContextKey<string>('syncStatus', SyncStatus.Uninitialized);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync';
7+
import { AbstractLogService, ILoggerService, ILogger } from 'vs/platform/log/common/log';
8+
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
9+
10+
export class UserDataSyncLogService extends AbstractLogService implements IUserDataSyncLogService {
11+
12+
_serviceBrand: undefined;
13+
private readonly logger: ILogger;
14+
15+
constructor(
16+
@ILoggerService loggerService: ILoggerService,
17+
@IEnvironmentService environmentService: IEnvironmentService
18+
) {
19+
super();
20+
this.logger = this._register(loggerService.getLogger(environmentService.userDataSyncLogResource));
21+
}
22+
23+
trace(message: string, ...args: any[]): void {
24+
this.logger.trace(message, ...args);
25+
}
26+
27+
debug(message: string, ...args: any[]): void {
28+
this.logger.debug(message, ...args);
29+
}
30+
31+
info(message: string, ...args: any[]): void {
32+
this.logger.info(message, ...args);
33+
}
34+
35+
warn(message: string, ...args: any[]): void {
36+
this.logger.warn(message, ...args);
37+
}
38+
39+
error(message: string | Error, ...args: any[]): void {
40+
this.logger.error(message, ...args);
41+
}
42+
43+
critical(message: string | Error, ...args: any[]): void {
44+
this.logger.critical(message, ...args);
45+
}
46+
47+
}

0 commit comments

Comments
 (0)