Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/log/common/logIpc.ts
3296 views
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 { URI } from '../../../base/common/uri.js';
7
import { Event } from '../../../base/common/event.js';
8
import { IChannel, IServerChannel } from '../../../base/parts/ipc/common/ipc.js';
9
import { AbstractLoggerService, AbstractMessageLogger, AdapterLogger, DidChangeLoggersEvent, ILogger, ILoggerOptions, ILoggerResource, ILoggerService, isLogLevel, LogLevel } from './log.js';
10
import { Disposable } from '../../../base/common/lifecycle.js';
11
import { IURITransformer } from '../../../base/common/uriIpc.js';
12
13
export class LoggerChannelClient extends AbstractLoggerService implements ILoggerService {
14
15
constructor(private readonly windowId: number | undefined, logLevel: LogLevel, logsHome: URI, loggers: ILoggerResource[], private readonly channel: IChannel) {
16
super(logLevel, logsHome, loggers);
17
this._register(channel.listen<LogLevel | [URI, LogLevel]>('onDidChangeLogLevel', windowId)(arg => {
18
if (isLogLevel(arg)) {
19
super.setLogLevel(arg);
20
} else {
21
super.setLogLevel(URI.revive(arg[0]), arg[1]);
22
}
23
}));
24
this._register(channel.listen<[URI, boolean]>('onDidChangeVisibility', windowId)(([resource, visibility]) => super.setVisibility(URI.revive(resource), visibility)));
25
this._register(channel.listen<DidChangeLoggersEvent>('onDidChangeLoggers', windowId)(({ added, removed }) => {
26
for (const loggerResource of added) {
27
super.registerLogger({ ...loggerResource, resource: URI.revive(loggerResource.resource) });
28
}
29
for (const loggerResource of removed) {
30
super.deregisterLogger(loggerResource.resource);
31
}
32
}));
33
}
34
35
createConsoleMainLogger(): ILogger {
36
return new AdapterLogger({
37
log: (level: LogLevel, args: any[]) => {
38
this.channel.call('consoleLog', [level, args]);
39
}
40
});
41
}
42
43
override registerLogger(logger: ILoggerResource): void {
44
super.registerLogger(logger);
45
this.channel.call('registerLogger', [logger, this.windowId]);
46
}
47
48
override deregisterLogger(resource: URI): void {
49
super.deregisterLogger(resource);
50
this.channel.call('deregisterLogger', [resource, this.windowId]);
51
}
52
53
override setLogLevel(logLevel: LogLevel): void;
54
override setLogLevel(resource: URI, logLevel: LogLevel): void;
55
override setLogLevel(arg1: any, arg2?: any): void {
56
super.setLogLevel(arg1, arg2);
57
this.channel.call('setLogLevel', [arg1, arg2]);
58
}
59
60
override setVisibility(resourceOrId: URI | string, visibility: boolean): void {
61
super.setVisibility(resourceOrId, visibility);
62
this.channel.call('setVisibility', [this.toResource(resourceOrId), visibility]);
63
}
64
65
protected doCreateLogger(file: URI, logLevel: LogLevel, options?: ILoggerOptions): ILogger {
66
return new Logger(this.channel, file, logLevel, options, this.windowId);
67
}
68
69
public static setLogLevel(channel: IChannel, level: LogLevel): Promise<void>;
70
public static setLogLevel(channel: IChannel, resource: URI, level: LogLevel): Promise<void>;
71
public static setLogLevel(channel: IChannel, arg1: any, arg2?: any): Promise<void> {
72
return channel.call('setLogLevel', [arg1, arg2]);
73
}
74
75
}
76
77
class Logger extends AbstractMessageLogger {
78
79
private isLoggerCreated: boolean = false;
80
private buffer: [LogLevel, string][] = [];
81
82
constructor(
83
private readonly channel: IChannel,
84
private readonly file: URI,
85
logLevel: LogLevel,
86
loggerOptions?: ILoggerOptions,
87
windowId?: number | undefined
88
) {
89
super(loggerOptions?.logLevel === 'always');
90
this.setLevel(logLevel);
91
this.channel.call('createLogger', [file, loggerOptions, windowId])
92
.then(() => {
93
this.doLog(this.buffer);
94
this.isLoggerCreated = true;
95
});
96
}
97
98
protected log(level: LogLevel, message: string) {
99
const messages: [LogLevel, string][] = [[level, message]];
100
if (this.isLoggerCreated) {
101
this.doLog(messages);
102
} else {
103
this.buffer.push(...messages);
104
}
105
}
106
107
private doLog(messages: [LogLevel, string][]) {
108
this.channel.call('log', [this.file, messages]);
109
}
110
}
111
112
export class LoggerChannel implements IServerChannel {
113
114
constructor(private readonly loggerService: ILoggerService, private getUriTransformer: (requestContext: any) => IURITransformer) { }
115
116
listen(context: any, event: string): Event<any> {
117
const uriTransformer = this.getUriTransformer(context);
118
switch (event) {
119
case 'onDidChangeLoggers': return Event.map<DidChangeLoggersEvent, DidChangeLoggersEvent>(this.loggerService.onDidChangeLoggers, (e) =>
120
({
121
added: [...e.added].map(logger => this.transformLogger(logger, uriTransformer)),
122
removed: [...e.removed].map(logger => this.transformLogger(logger, uriTransformer)),
123
}));
124
case 'onDidChangeVisibility': return Event.map<[URI, boolean], [URI, boolean]>(this.loggerService.onDidChangeVisibility, e => [uriTransformer.transformOutgoingURI(e[0]), e[1]]);
125
case 'onDidChangeLogLevel': return Event.map<LogLevel | [URI, LogLevel], LogLevel | [URI, LogLevel]>(this.loggerService.onDidChangeLogLevel, e => isLogLevel(e) ? e : [uriTransformer.transformOutgoingURI(e[0]), e[1]]);
126
}
127
throw new Error(`Event not found: ${event}`);
128
}
129
130
async call(context: any, command: string, arg?: any): Promise<any> {
131
const uriTransformer: IURITransformer | null = this.getUriTransformer(context);
132
switch (command) {
133
case 'setLogLevel': return isLogLevel(arg[0]) ? this.loggerService.setLogLevel(arg[0]) : this.loggerService.setLogLevel(URI.revive(uriTransformer.transformIncoming(arg[0][0])), arg[0][1]);
134
case 'getRegisteredLoggers': return Promise.resolve([...this.loggerService.getRegisteredLoggers()].map(logger => this.transformLogger(logger, uriTransformer)));
135
}
136
137
throw new Error(`Call not found: ${command}`);
138
}
139
140
private transformLogger(logger: ILoggerResource, transformer: IURITransformer): ILoggerResource {
141
return {
142
...logger,
143
resource: transformer.transformOutgoingURI(logger.resource)
144
};
145
}
146
147
}
148
149
export class RemoteLoggerChannelClient extends Disposable {
150
151
constructor(loggerService: ILoggerService, channel: IChannel) {
152
super();
153
154
channel.call('setLogLevel', [loggerService.getLogLevel()]);
155
this._register(loggerService.onDidChangeLogLevel(arg => channel.call('setLogLevel', [arg])));
156
157
channel.call<ILoggerResource[]>('getRegisteredLoggers').then(loggers => {
158
for (const loggerResource of loggers) {
159
loggerService.registerLogger({ ...loggerResource, resource: URI.revive(loggerResource.resource) });
160
}
161
});
162
163
this._register(channel.listen<[URI, boolean]>('onDidChangeVisibility')(([resource, visibility]) => loggerService.setVisibility(URI.revive(resource), visibility)));
164
165
this._register(channel.listen<DidChangeLoggersEvent>('onDidChangeLoggers')(({ added, removed }) => {
166
for (const loggerResource of added) {
167
loggerService.registerLogger({ ...loggerResource, resource: URI.revive(loggerResource.resource) });
168
}
169
for (const loggerResource of removed) {
170
loggerService.deregisterLogger(loggerResource.resource);
171
}
172
}));
173
174
}
175
}
176
177