Skip to content

Commit 222994d

Browse files
authored
Enhance logger service (microsoft#171174)
- ILoggerService centrailised place for all loggers - Provide options to display logger while creating/registering logger - Listen to logger service and register log output channels accordingly - Adopt this at all places where loggers are created
1 parent 7c0e513 commit 222994d

File tree

50 files changed

+356
-329
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+356
-329
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ import { ISharedProcessLifecycleService, SharedProcessLifecycleService } from 'v
114114
import { UserDataSyncResourceProviderService } from 'vs/platform/userDataSync/common/userDataSyncResourceProvider';
115115
import { ExtensionsContributions } from 'vs/code/electron-browser/sharedProcess/contrib/extensions';
116116
import { ExtensionsProfileScannerService } from 'vs/platform/extensionManagement/electron-sandbox/extensionsProfileScannerService';
117+
import { localize } from 'vs/nls';
117118

118119
class SharedProcessMain extends Disposable {
119120

@@ -222,7 +223,7 @@ class SharedProcessMain extends Disposable {
222223
// Log
223224
const multiplexLogger = this._register(new MultiplexLogService([
224225
this._register(new ConsoleLogger(this.configuration.logLevel)),
225-
this._register(loggerService.createLogger(joinPath(URI.file(environmentService.logsPath), 'sharedprocess.log'), { name: 'sharedprocess' }))
226+
this._register(loggerService.createLogger(joinPath(URI.file(environmentService.logsPath), 'sharedprocess.log'), { id: 'sharedLog', name: localize('sharedLog', "Shared") }))
226227
]));
227228

228229
const logService = this._register(new FollowerLogService(logLevelClient, multiplexLogger));
@@ -304,7 +305,7 @@ class SharedProcessMain extends Disposable {
304305
const appenders: ITelemetryAppender[] = [];
305306
const internalTelemetry = isInternalTelemetry(productService, configurationService);
306307
if (supportsTelemetry(productService, environmentService)) {
307-
const logAppender = new TelemetryLogAppender(loggerService, environmentService);
308+
const logAppender = new TelemetryLogAppender(logService, loggerService, environmentService, productService);
308309
appenders.push(logAppender);
309310
const { installSourcePath } = environmentService;
310311
if (productService.aiConfig?.ariaKey) {
@@ -329,7 +330,7 @@ class SharedProcessMain extends Disposable {
329330
services.set(ITelemetryService, telemetryService);
330331

331332
// Custom Endpoint Telemetry
332-
const customEndpointTelemetryService = new CustomEndpointTelemetryService(configurationService, telemetryService, loggerService, environmentService, productService);
333+
const customEndpointTelemetryService = new CustomEndpointTelemetryService(configurationService, telemetryService, logService, loggerService, environmentService, productService);
333334
services.set(ICustomEndpointTelemetryService, customEndpointTelemetryService);
334335

335336
// Extension Management

src/vs/code/electron-main/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class CodeMain {
129129
});
130130

131131
// Delay creation of spdlog for perf reasons (https://github.com/microsoft/vscode/issues/72906)
132-
bufferLogService.logger = loggerService.createLogger(URI.file(join(environmentMainService.logsPath, 'main.log')), { name: 'main' });
132+
bufferLogService.logger = loggerService.createLogger(URI.file(join(environmentMainService.logsPath, 'main.log')), { id: 'mainLog', name: localize('mainLog', "Main") });
133133

134134
// Lifecycle
135135
once(lifecycleMainService.onWillShutdown)(evt => {

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ export class FileLogger extends AbstractMessageLogger implements ILogger {
2020
private backupIndex: number = 1;
2121

2222
constructor(
23-
name: string,
2423
private readonly resource: URI,
2524
level: LogLevel,
2625
private readonly donotUseFormatters: boolean,
@@ -107,7 +106,7 @@ export class FileLoggerService extends AbstractLoggerService implements ILoggerS
107106

108107
protected doCreateLogger(resource: URI, logLevel: LogLevel, options?: ILoggerOptions): ILogger {
109108
const logger = new BufferLogService(logLevel);
110-
whenProviderRegistered(resource, this.fileService).then(() => (<BufferLogService>logger).logger = new FileLogger(options?.name || basename(resource), resource, logger.getLevel(), !!options?.donotUseFormatters, this.fileService));
109+
whenProviderRegistered(resource, this.fileService).then(() => (<BufferLogService>logger).logger = new FileLogger(resource, logger.getLevel(), !!options?.donotUseFormatters, this.fileService));
111110
return logger;
112111
}
113112
}

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

Lines changed: 89 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ export interface ILogService extends ILogger {
8484

8585
export interface ILoggerOptions {
8686

87+
/**
88+
* Id of the logger.
89+
*/
90+
id?: string;
91+
8792
/**
8893
* Name of the logger.
8994
*/
@@ -100,19 +105,31 @@ export interface ILoggerOptions {
100105
donotUseFormatters?: boolean;
101106

102107
/**
103-
* If set, logger logs the message always.
108+
* When to log. Set to `always` to log always.
109+
*/
110+
logLevel?: 'always' | LogLevel;
111+
112+
/**
113+
* Whether the log should be hidden from the user.
104114
*/
105-
always?: boolean;
115+
hidden?: boolean;
116+
117+
/**
118+
* Id of the extension that created this logger.
119+
*/
120+
extensionId?: string;
106121
}
107122

108123
export interface ILoggerResource {
109124
readonly resource: URI;
125+
readonly id: string;
110126
readonly name?: string;
111-
readonly id?: string;
112127
readonly logLevel?: LogLevel;
128+
readonly hidden?: boolean;
129+
readonly extensionId?: string;
113130
}
114131

115-
export type DidChangeLoggerResourceEvent = {
132+
export type DidChangeLoggersEvent = {
116133
readonly added: Iterable<ILoggerResource>;
117134
readonly removed: Iterable<ILoggerResource>;
118135
};
@@ -123,14 +140,21 @@ export interface ILoggerService {
123140

124141
/**
125142
* Creates a logger, or gets one if it already exists.
143+
*
144+
* This will also register the logger with the logger service unless `donotRegister` is set to `true`.
126145
*/
127-
createLogger(resource: URI, options?: ILoggerOptions, logLevel?: LogLevel): ILogger;
146+
createLogger(resource: URI, options?: ILoggerOptions, donotRegister?: boolean): ILogger;
128147

129148
/**
130149
* Gets an existing logger, if any.
131150
*/
132151
getLogger(resource: URI): ILogger | undefined;
133152

153+
/**
154+
* An event which fires when the log level of a logger has changed
155+
*/
156+
readonly onDidChangeLogLevel: Event<[URI, LogLevel]>;
157+
134158
/**
135159
* Set log level for a logger.
136160
*/
@@ -142,29 +166,45 @@ export interface ILoggerService {
142166
getLogLevel(resource: URI): LogLevel | undefined;
143167

144168
/**
145-
* An event which fires when the log level of a logger has changed
169+
* An event which fires when the visibility of a logger has changed
170+
*/
171+
readonly onDidChangeVisibility: Event<[URI, boolean]>;
172+
173+
/**
174+
* Set the visibility of a logger.
146175
*/
147-
readonly onDidChangeLogLevel: Event<ILoggerResource>;
176+
setVisibility(resource: URI, visible: boolean): void;
148177

149178
/**
150179
* An event which fires when the logger resources are changed
151180
*/
152-
readonly onDidChangeLoggerResources: Event<DidChangeLoggerResourceEvent>;
181+
readonly onDidChangeLoggers: Event<DidChangeLoggersEvent>;
182+
183+
/**
184+
* Register a logger with the logger service.
185+
*
186+
* Note that this will not create a logger, but only register it.
187+
*
188+
* Use `createLogger` to create a logger and register it.
189+
*
190+
* Use it when you want to register a logger that is not created by the logger service.
191+
*/
192+
registerLogger(resource: ILoggerResource): void;
153193

154194
/**
155-
* Register the logger resoruce
195+
* Deregister the logger for the given resource.
156196
*/
157-
registerLoggerResource(resource: ILoggerResource): void;
197+
deregisterLogger(resource: URI): void;
158198

159199
/**
160-
* Deregister the logger resoruce
200+
* Get all registered loggers
161201
*/
162-
deregisterLoggerResource(resource: URI): void;
202+
getRegisteredLoggers(): Iterable<ILoggerResource>;
163203

164204
/**
165-
* Get all registered logger resources
205+
* Get the registered logger for the given resource.
166206
*/
167-
getLoggerResources(): Iterable<ILoggerResource>;
207+
getRegisteredLogger(resource: URI): ILoggerResource | undefined;
168208
}
169209

170210
export abstract class AbstractLogger extends Disposable implements ILogger {
@@ -532,12 +572,15 @@ export abstract class AbstractLoggerService extends Disposable implements ILogge
532572

533573
private readonly _loggerResources = new ResourceMap<Mutable<ILoggerResource>>();
534574

535-
private _onDidChangeLoggerResources = this._register(new Emitter<{ added: ILoggerResource[]; removed: ILoggerResource[] }>);
536-
readonly onDidChangeLoggerResources = this._onDidChangeLoggerResources.event;
575+
private _onDidChangeLoggers = this._register(new Emitter<{ added: ILoggerResource[]; removed: ILoggerResource[] }>);
576+
readonly onDidChangeLoggers = this._onDidChangeLoggers.event;
537577

538-
private _onDidChangeLogLevel = this._register(new Emitter<ILoggerResource>);
578+
private _onDidChangeLogLevel = this._register(new Emitter<[URI, LogLevel]>);
539579
readonly onDidChangeLogLevel = this._onDidChangeLogLevel.event;
540580

581+
private _onDidChangeVisibility = this._register(new Emitter<[URI, boolean]>);
582+
readonly onDidChangeVisibility = this._onDidChangeVisibility.event;
583+
541584
constructor(
542585
protected logLevel: LogLevel,
543586
onDidChangeLogLevel: Event<LogLevel>,
@@ -556,13 +599,15 @@ export abstract class AbstractLoggerService extends Disposable implements ILogge
556599
return this._loggers.get(resource);
557600
}
558601

559-
createLogger(resource: URI, options?: ILoggerOptions, logLevel?: LogLevel): ILogger {
602+
createLogger(resource: URI, options?: ILoggerOptions, donotRegister?: boolean): ILogger {
560603
let logger = this._loggers.get(resource);
561604
if (!logger) {
562-
logLevel = options?.always ? LogLevel.Trace : logLevel;
605+
const logLevel = options?.logLevel === 'always' ? LogLevel.Trace : options?.logLevel;
563606
logger = this.doCreateLogger(resource, logLevel ?? this.getLogLevel(resource) ?? this.logLevel, options);
564607
this._loggers.set(resource, logger);
565-
this.registerLoggerResource({ resource, logLevel, name: options?.name });
608+
if (!donotRegister) {
609+
this.registerLogger({ resource, id: options?.id ?? resource.toString(), logLevel, name: options?.name, hidden: options?.hidden, extensionId: options?.extensionId });
610+
}
566611
}
567612
return logger;
568613
}
@@ -573,7 +618,16 @@ export abstract class AbstractLoggerService extends Disposable implements ILogge
573618
loggerResource.logLevel = logLevel === this.logLevel ? undefined : logLevel;
574619
this._loggers.get(resource)?.setLevel(logLevel);
575620
this._loggerResources.set(loggerResource.resource, loggerResource);
576-
this._onDidChangeLogLevel.fire(loggerResource);
621+
this._onDidChangeLogLevel.fire([resource, logLevel]);
622+
}
623+
}
624+
625+
setVisibility(resource: URI, visibility: boolean): void {
626+
const loggerResource = this._loggerResources.get(resource);
627+
if (loggerResource && visibility !== !loggerResource.hidden) {
628+
loggerResource.hidden = !visibility;
629+
this._loggerResources.set(loggerResource.resource, loggerResource);
630+
this._onDidChangeVisibility.fire([resource, visibility]);
577631
}
578632
}
579633

@@ -590,26 +644,35 @@ export abstract class AbstractLoggerService extends Disposable implements ILogge
590644
return this._loggerResources.get(resource)?.logLevel;
591645
}
592646

593-
registerLoggerResource(resource: ILoggerResource): void {
647+
registerLogger(resource: ILoggerResource): void {
594648
const existing = this._loggerResources.get(resource.resource);
595649
if (!existing) {
596650
this._loggerResources.set(resource.resource, resource);
597-
this._onDidChangeLoggerResources.fire({ added: [resource], removed: [] });
651+
this._onDidChangeLoggers.fire({ added: [resource], removed: [] });
598652
}
599653
}
600654

601-
deregisterLoggerResource(resource: URI): void {
655+
deregisterLogger(resource: URI): void {
602656
const existing = this._loggerResources.get(resource);
603657
if (existing) {
604658
this._loggerResources.delete(resource);
605-
this._onDidChangeLoggerResources.fire({ added: [], removed: [existing] });
659+
const logger = this._loggers.get(resource);
660+
if (logger) {
661+
this._loggers.delete(resource);
662+
logger.dispose();
663+
}
664+
this._onDidChangeLoggers.fire({ added: [], removed: [existing] });
606665
}
607666
}
608667

609-
getLoggerResources(): Iterable<ILoggerResource> {
668+
getRegisteredLoggers(): Iterable<ILoggerResource> {
610669
return this._loggerResources.values();
611670
}
612671

672+
getRegisteredLogger(resource: URI): ILoggerResource | undefined {
673+
return this._loggerResources.get(resource);
674+
}
675+
613676
override dispose(): void {
614677
this._loggers.forEach(logger => logger.dispose());
615678
this._loggers.clear();

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

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { Event } from 'vs/base/common/event';
77
import { URI, UriDto } from 'vs/base/common/uri';
88
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
9-
import { AbstractLoggerService, AbstractMessageLogger, AdapterLogger, DidChangeLoggerResourceEvent, ILogger, ILoggerOptions, ILoggerResource, ILoggerService, ILogService, LogLevel, LogService } from 'vs/platform/log/common/log';
9+
import { AbstractLoggerService, AbstractMessageLogger, AdapterLogger, DidChangeLoggersEvent, ILogger, ILoggerOptions, ILoggerResource, ILoggerService, ILogService, LogLevel, LogService } from 'vs/platform/log/common/log';
1010

1111
export class LogLevelChannel implements IServerChannel {
1212

@@ -59,13 +59,14 @@ export class LoggerChannelClient extends AbstractLoggerService implements ILogge
5959

6060
constructor(private readonly windowId: number | undefined, logLevel: LogLevel, onDidChangeLogLevel: Event<LogLevel>, loggers: UriDto<ILoggerResource>[], private readonly channel: IChannel) {
6161
super(logLevel, onDidChangeLogLevel, loggers.map(loggerResource => ({ ...loggerResource, resource: URI.revive(loggerResource.resource) })));
62-
this._register(channel.listen<ILoggerResource>('onDidChangeLogLevel', windowId)((loggerResource) => super.setLogLevel(URI.revive(loggerResource.resource), loggerResource.logLevel ?? this.logLevel)));
63-
this._register(channel.listen<DidChangeLoggerResourceEvent>('onDidChangeLoggerResources', windowId)(({ added, removed }) => {
62+
this._register(channel.listen<[URI, LogLevel]>('onDidChangeLogLevel', windowId)(([resource, logLevel]) => super.setLogLevel(URI.revive(resource), logLevel)));
63+
this._register(channel.listen<[URI, boolean]>('onDidChangeVisibility', windowId)(([resource, visibility]) => super.setVisibility(URI.revive(resource), visibility)));
64+
this._register(channel.listen<DidChangeLoggersEvent>('onDidChangeLoggers', windowId)(({ added, removed }) => {
6465
for (const loggerResource of added) {
65-
super.registerLoggerResource({ ...loggerResource, resource: URI.revive(loggerResource.resource) });
66+
super.registerLogger({ ...loggerResource, resource: URI.revive(loggerResource.resource) });
6667
}
6768
for (const loggerResource of removed) {
68-
super.deregisterLoggerResource(loggerResource.resource);
69+
super.deregisterLogger(loggerResource.resource);
6970
}
7071
}));
7172
}
@@ -78,18 +79,26 @@ export class LoggerChannelClient extends AbstractLoggerService implements ILogge
7879
});
7980
}
8081

81-
override registerLoggerResource(resource: ILoggerResource): void {
82-
this.channel.call('registerLoggerResource', [resource, this.windowId]);
82+
override registerLogger(logger: ILoggerResource): void {
83+
super.registerLogger(logger);
84+
this.channel.call('registerLogger', [logger, this.windowId]);
8385
}
8486

85-
override deregisterLoggerResource(resource: URI): void {
86-
this.channel.call('deregisterLoggerResource', [resource, this.windowId]);
87+
override deregisterLogger(resource: URI): void {
88+
super.deregisterLogger(resource);
89+
this.channel.call('deregisterLogger', [resource, this.windowId]);
8790
}
8891

8992
override setLogLevel(resource: URI, logLevel: LogLevel): void {
93+
super.setLogLevel(resource, logLevel);
9094
this.channel.call('setLogLevel', [resource, logLevel]);
9195
}
9296

97+
override setVisibility(resource: URI, visibility: boolean): void {
98+
super.setVisibility(resource, visibility);
99+
this.channel.call('setVisibility', [resource, visibility]);
100+
}
101+
93102
protected doCreateLogger(file: URI, logLevel: LogLevel, options?: ILoggerOptions): ILogger {
94103
return new Logger(this.channel, file, logLevel, options);
95104
}
@@ -107,7 +116,7 @@ class Logger extends AbstractMessageLogger {
107116
logLevel: LogLevel,
108117
loggerOptions?: ILoggerOptions,
109118
) {
110-
super(loggerOptions?.always);
119+
super(loggerOptions?.logLevel === 'always');
111120
this.setLevel(logLevel);
112121
this.channel.call('createLogger', [file, loggerOptions])
113122
.then(() => {

src/vs/platform/log/electron-main/logIpc.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,29 @@ export class LoggerChannel implements IServerChannel {
1717

1818
listen(_: unknown, event: string, windowId?: number): Event<any> {
1919
switch (event) {
20-
case 'onDidChangeLoggerResources': return windowId ? this.loggerService.getOnDidChangeLoggerResourcesEvent(windowId) : this.loggerService.onDidChangeLoggerResources;
20+
case 'onDidChangeLoggers': return windowId ? this.loggerService.getOnDidChangeLoggersEvent(windowId) : this.loggerService.onDidChangeLoggers;
2121
case 'onDidChangeLogLevel': return windowId ? this.loggerService.getOnDidChangeLogLevelEvent(windowId) : this.loggerService.onDidChangeLogLevel;
22+
case 'onDidChangeVisibility': return windowId ? this.loggerService.getOnDidChangeVisibilityEvent(windowId) : this.loggerService.onDidChangeVisibility;
2223
}
2324
throw new Error(`Event not found: ${event}`);
2425
}
2526

2627
async call(_: unknown, command: string, arg?: any): Promise<any> {
2728
switch (command) {
28-
case 'createLogger': this.createLogger(URI.revive(arg[0]), arg[1]); return;
29+
case 'createLogger': this.createLogger(URI.revive(arg[0]), arg[1], arg[2]); return;
2930
case 'log': return this.log(URI.revive(arg[0]), arg[1]);
3031
case 'consoleLog': return this.consoleLog(arg[0], arg[1]);
3132
case 'setLogLevel': return this.loggerService.setLogLevel(URI.revive(arg[0]), arg[1]);
32-
case 'registerLoggerResource': return this.loggerService.registerLoggerResource({ ...arg[0], resource: URI.revive(arg[0].resource) }, arg[1]);
33-
case 'deregisterLoggerResource': return this.loggerService.deregisterLoggerResource(URI.revive(arg[0]));
33+
case 'setVisibility': return this.loggerService.setVisibility(URI.revive(arg[0]), arg[1]);
34+
case 'registerLogger': return this.loggerService.registerLogger({ ...arg[0], resource: URI.revive(arg[0].resource) }, arg[1]);
35+
case 'deregisterLogger': return this.loggerService.deregisterLogger(URI.revive(arg[0]));
3436
}
3537

3638
throw new Error(`Call not found: ${command}`);
3739
}
3840

39-
private createLogger(file: URI, options: ILoggerOptions): void {
40-
this.loggers.set(file.toString(), this.loggerService.createLogger(file, options));
41+
private createLogger(file: URI, options: ILoggerOptions, donotRegister?: boolean): void {
42+
this.loggers.set(file.toString(), this.loggerService.createLogger(file, options, donotRegister));
4143
}
4244

4345
private consoleLog(level: LogLevel, args: any[]): void {

0 commit comments

Comments
 (0)