mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-26 04:34:32 +00:00
Merge pull request #171129 from microsoft/sandy081/logLevel
Persist log level on reload for extension logs
This commit is contained in:
@@ -216,7 +216,7 @@ class SharedProcessMain extends Disposable {
|
||||
|
||||
// Logger
|
||||
const logLevelClient = new LogLevelChannelClient(this.server.getChannel('logLevel', mainRouter));
|
||||
const loggerService = new LoggerChannelClient(this.configuration.logLevel, logLevelClient.onDidChangeLogLevel, mainProcessService.getChannel('logger'));
|
||||
const loggerService = new LoggerChannelClient(undefined, this.configuration.logLevel, logLevelClient.onDidChangeLogLevel, this.configuration.loggers, mainProcessService.getChannel('logger'));
|
||||
services.set(ILoggerService, loggerService);
|
||||
|
||||
// Log
|
||||
@@ -275,7 +275,8 @@ class SharedProcessMain extends Disposable {
|
||||
]);
|
||||
|
||||
// URI Identity
|
||||
services.set(IUriIdentityService, new UriIdentityService(fileService));
|
||||
const uriIdentityService = new UriIdentityService(fileService);
|
||||
services.set(IUriIdentityService, uriIdentityService);
|
||||
|
||||
// Request
|
||||
services.set(IRequestService, new SharedProcessRequestService(mainProcessService, configurationService, productService, logService));
|
||||
@@ -374,7 +375,9 @@ class SharedProcessMain extends Disposable {
|
||||
},
|
||||
configurationService,
|
||||
environmentService,
|
||||
logService
|
||||
logService,
|
||||
loggerService,
|
||||
uriIdentityService
|
||||
);
|
||||
ptyHostService.initialize();
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platfo
|
||||
import { ILaunchMainService, LaunchMainService } from 'vs/platform/launch/electron-main/launchMainService';
|
||||
import { ILifecycleMainService, LifecycleMainPhase, ShutdownReason } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { ILoggerService, ILogService } from 'vs/platform/log/common/log';
|
||||
import { LoggerChannel, LogLevelChannel } from 'vs/platform/log/common/logIpc';
|
||||
import { LogLevelChannel } from 'vs/platform/log/common/logIpc';
|
||||
import { IMenubarMainService, MenubarMainService } from 'vs/platform/menubar/electron-main/menubarMainService';
|
||||
import { INativeHostMainService, NativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
@@ -110,6 +110,8 @@ import { ProfileStorageChangesListenerChannel } from 'vs/platform/userDataProfil
|
||||
import { Promises, RunOnceScheduler, runWhenIdle } from 'vs/base/common/async';
|
||||
import { resolveMachineId } from 'vs/platform/telemetry/electron-main/telemetryUtils';
|
||||
import { ExtensionsProfileScannerService } from 'vs/platform/extensionManagement/node/extensionsProfileScannerService';
|
||||
import { LoggerChannel } from 'vs/platform/log/electron-main/logIpc';
|
||||
import { ILoggerMainService } from 'vs/platform/log/electron-main/loggerService';
|
||||
|
||||
/**
|
||||
* The main VS Code application. There will only ever be one instance,
|
||||
@@ -804,7 +806,7 @@ export class CodeApplication extends Disposable {
|
||||
sharedProcessClient.then(client => client.registerChannel('logLevel', logLevelChannel));
|
||||
|
||||
// Logger
|
||||
const loggerChannel = new LoggerChannel(accessor.get(ILoggerService),);
|
||||
const loggerChannel = new LoggerChannel(accessor.get(ILoggerMainService),);
|
||||
mainProcessElectronServer.registerChannel('logger', loggerChannel);
|
||||
sharedProcessClient.then(client => client.registerChannel('logger', loggerChannel));
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainS
|
||||
import { ILifecycleMainService, LifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
|
||||
import { ConsoleMainLogger, getLogLevel, ILoggerService, ILogService, MultiplexLogService } from 'vs/platform/log/common/log';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IProtocolMainService } from 'vs/platform/protocol/electron-main/protocol';
|
||||
@@ -69,6 +68,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
|
||||
import { PROFILES_ENABLEMENT_CONFIG } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { ILoggerMainService, LoggerMainService } from 'vs/platform/log/electron-main/loggerService';
|
||||
|
||||
/**
|
||||
* The main VS Code entry point.
|
||||
@@ -177,7 +177,7 @@ class CodeMain {
|
||||
services.set(IUriIdentityService, uriIdentityService);
|
||||
|
||||
// Logger
|
||||
services.set(ILoggerService, new LoggerService(logService));
|
||||
services.set(ILoggerMainService, new LoggerMainService(logService));
|
||||
|
||||
// State
|
||||
const stateMainService = new StateMainService(environmentMainService, logService, fileService);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { Mutable } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -104,7 +105,20 @@ export interface ILoggerOptions {
|
||||
always?: boolean;
|
||||
}
|
||||
|
||||
export interface ILoggerResource {
|
||||
readonly resource: URI;
|
||||
readonly name?: string;
|
||||
readonly id?: string;
|
||||
readonly logLevel?: LogLevel;
|
||||
}
|
||||
|
||||
export type DidChangeLoggerResourceEvent = {
|
||||
readonly added: Iterable<ILoggerResource>;
|
||||
readonly removed: Iterable<ILoggerResource>;
|
||||
};
|
||||
|
||||
export interface ILoggerService {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
/**
|
||||
@@ -120,12 +134,37 @@ export interface ILoggerService {
|
||||
/**
|
||||
* Set log level for a logger.
|
||||
*/
|
||||
setLevel(resource: URI, level: LogLevel | undefined): void;
|
||||
setLogLevel(resource: URI, level: LogLevel): void;
|
||||
|
||||
/**
|
||||
* Get log level for a logger.
|
||||
*/
|
||||
getLogLevel(resource: URI): LogLevel | undefined;
|
||||
|
||||
/**
|
||||
* An event which fires when the log level of a logger has changed
|
||||
*/
|
||||
readonly onDidChangeLogLevel: Event<ILoggerResource>;
|
||||
|
||||
/**
|
||||
* An event which fires when the logger resources are changed
|
||||
*/
|
||||
readonly onDidChangeLoggerResources: Event<DidChangeLoggerResourceEvent>;
|
||||
|
||||
/**
|
||||
* Register the logger resoruce
|
||||
*/
|
||||
registerLoggerResource(resource: ILoggerResource): void;
|
||||
|
||||
/**
|
||||
* Deregister the logger resoruce
|
||||
*/
|
||||
deregisterLoggerResource(resource: URI): void;
|
||||
|
||||
/**
|
||||
* Get all registered logger resources
|
||||
*/
|
||||
getLoggerResources(): Iterable<ILoggerResource>;
|
||||
}
|
||||
|
||||
export abstract class AbstractLogger extends Disposable implements ILogger {
|
||||
@@ -485,74 +524,96 @@ export class LogService extends Disposable implements ILogService {
|
||||
}
|
||||
}
|
||||
|
||||
interface ILoggerItem {
|
||||
readonly logger: ILogger;
|
||||
logLevel: LogLevel | undefined;
|
||||
}
|
||||
|
||||
export abstract class AbstractLoggerService extends Disposable implements ILoggerService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly loggerItems = new ResourceMap<ILoggerItem>();
|
||||
private readonly _loggers = new ResourceMap<ILogger>();
|
||||
|
||||
private readonly _loggerResources = new ResourceMap<Mutable<ILoggerResource>>();
|
||||
|
||||
private _onDidChangeLoggerResources = this._register(new Emitter<{ added: ILoggerResource[]; removed: ILoggerResource[] }>);
|
||||
readonly onDidChangeLoggerResources = this._onDidChangeLoggerResources.event;
|
||||
|
||||
private _onDidChangeLogLevel = this._register(new Emitter<ILoggerResource>);
|
||||
readonly onDidChangeLogLevel = this._onDidChangeLogLevel.event;
|
||||
|
||||
constructor(
|
||||
private logLevel: LogLevel,
|
||||
protected logLevel: LogLevel,
|
||||
onDidChangeLogLevel: Event<LogLevel>,
|
||||
loggerResources?: Iterable<ILoggerResource>,
|
||||
) {
|
||||
super();
|
||||
this._register(onDidChangeLogLevel(logLevel => this.setLevel(logLevel)));
|
||||
}
|
||||
|
||||
getLoggers(): ILogger[] {
|
||||
return [...this.loggerItems.values()].map(({ logger }) => logger);
|
||||
this._register(onDidChangeLogLevel(logLevel => this.setGlobalLogLevel(logLevel)));
|
||||
if (loggerResources) {
|
||||
for (const loggerResource of loggerResources) {
|
||||
this._loggerResources.set(loggerResource.resource, loggerResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getLogger(resource: URI): ILogger | undefined {
|
||||
return this.loggerItems.get(resource)?.logger;
|
||||
return this._loggers.get(resource);
|
||||
}
|
||||
|
||||
createLogger(resource: URI, options?: ILoggerOptions, logLevel?: LogLevel): ILogger {
|
||||
let logger = this.loggerItems.get(resource)?.logger;
|
||||
let logger = this._loggers.get(resource);
|
||||
if (!logger) {
|
||||
logLevel = options?.always ? LogLevel.Trace : logLevel;
|
||||
logger = this.doCreateLogger(resource, logLevel ?? this.logLevel, options);
|
||||
this.loggerItems.set(resource, { logger, logLevel });
|
||||
logger = this.doCreateLogger(resource, logLevel ?? this.getLogLevel(resource) ?? this.logLevel, options);
|
||||
this._loggers.set(resource, logger);
|
||||
this.registerLoggerResource({ resource, logLevel, name: options?.name });
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
setLevel(logLevel: LogLevel): void;
|
||||
setLevel(resource: URI, logLevel: LogLevel): void;
|
||||
setLevel(arg1: any, arg2?: any): void {
|
||||
const resource = URI.isUri(arg1) ? arg1 : undefined;
|
||||
const logLevel = resource ? arg2 : arg1;
|
||||
|
||||
if (resource) {
|
||||
const logger = this.loggerItems.get(resource);
|
||||
if (logger && logger.logLevel !== logLevel) {
|
||||
logger.logLevel = logLevel;
|
||||
logger.logger.setLevel(logLevel);
|
||||
}
|
||||
} else {
|
||||
this.logLevel = logLevel;
|
||||
this.loggerItems.forEach(({ logLevel, logger }) => {
|
||||
if (logLevel === undefined) {
|
||||
logger.setLevel(this.logLevel);
|
||||
}
|
||||
});
|
||||
setLogLevel(resource: URI, logLevel: LogLevel): void {
|
||||
const loggerResource = this._loggerResources.get(resource);
|
||||
if (loggerResource && logLevel !== loggerResource.logLevel) {
|
||||
loggerResource.logLevel = logLevel === this.logLevel ? undefined : logLevel;
|
||||
this._loggers.get(resource)?.setLevel(logLevel);
|
||||
this._loggerResources.set(loggerResource.resource, loggerResource);
|
||||
this._onDidChangeLogLevel.fire(loggerResource);
|
||||
}
|
||||
}
|
||||
|
||||
protected setGlobalLogLevel(logLevel: LogLevel): void {
|
||||
this.logLevel = logLevel;
|
||||
for (const [resource, logger] of this._loggers.entries()) {
|
||||
if (this._loggerResources.get(resource)?.logLevel === undefined) {
|
||||
logger.setLevel(this.logLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getLogLevel(resource: URI): LogLevel | undefined {
|
||||
const logger = this.loggerItems.get(resource);
|
||||
return logger?.logLevel;
|
||||
return this._loggerResources.get(resource)?.logLevel;
|
||||
}
|
||||
|
||||
registerLoggerResource(resource: ILoggerResource): void {
|
||||
const existing = this._loggerResources.get(resource.resource);
|
||||
if (!existing) {
|
||||
this._loggerResources.set(resource.resource, resource);
|
||||
this._onDidChangeLoggerResources.fire({ added: [resource], removed: [] });
|
||||
}
|
||||
}
|
||||
|
||||
deregisterLoggerResource(resource: URI): void {
|
||||
const existing = this._loggerResources.get(resource);
|
||||
if (existing) {
|
||||
this._loggerResources.delete(resource);
|
||||
this._onDidChangeLoggerResources.fire({ added: [], removed: [existing] });
|
||||
}
|
||||
}
|
||||
|
||||
getLoggerResources(): Iterable<ILoggerResource> {
|
||||
return this._loggerResources.values();
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
this.loggerItems.forEach(({ logger }) => logger.dispose());
|
||||
this.loggerItems.clear();
|
||||
this._loggers.forEach(logger => logger.dispose());
|
||||
this._loggers.clear();
|
||||
this._loggerResources.clear();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { URI, UriDto } from 'vs/base/common/uri';
|
||||
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { AbstractLoggerService, AbstractMessageLogger, AdapterLogger, ILogger, ILoggerOptions, ILoggerService, ILogService, log, LogLevel, LogService } from 'vs/platform/log/common/log';
|
||||
import { AbstractLoggerService, AbstractMessageLogger, AdapterLogger, DidChangeLoggerResourceEvent, ILogger, ILoggerOptions, ILoggerResource, ILoggerService, ILogService, LogLevel, LogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class LogLevelChannel implements IServerChannel {
|
||||
|
||||
@@ -29,7 +29,7 @@ export class LogLevelChannel implements IServerChannel {
|
||||
|
||||
async call(_: unknown, command: string, arg?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'setLevel': return arg[1] ? this.loggerService.setLevel(URI.revive(arg[1]), arg[0]) : this.logService.setLevel(arg[0]);
|
||||
case 'setLevel': return arg[1] ? this.loggerService.setLogLevel(URI.revive(arg[1]), arg[0]) : this.logService.setLevel(arg[0]);
|
||||
}
|
||||
|
||||
throw new Error(`Call not found: ${command}`);
|
||||
@@ -55,63 +55,19 @@ export class LogLevelChannelClient {
|
||||
|
||||
}
|
||||
|
||||
export class LoggerChannel implements IServerChannel {
|
||||
|
||||
private readonly loggers = new Map<string, ILogger>();
|
||||
|
||||
constructor(private readonly loggerService: ILoggerService) { }
|
||||
|
||||
listen(_: unknown, event: string): Event<any> {
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
}
|
||||
|
||||
async call(_: unknown, command: string, arg?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'createLogger': this.createLogger(URI.revive(arg[0]), arg[1]); return;
|
||||
case 'log': return this.log(URI.revive(arg[0]), arg[1]);
|
||||
case 'consoleLog': return this.consoleLog(arg[0], arg[1]);
|
||||
}
|
||||
|
||||
throw new Error(`Call not found: ${command}`);
|
||||
}
|
||||
|
||||
private createLogger(file: URI, options: ILoggerOptions): void {
|
||||
this.loggers.set(file.toString(), this.loggerService.createLogger(file, options));
|
||||
}
|
||||
|
||||
private consoleLog(level: LogLevel, args: any[]): void {
|
||||
let consoleFn = console.log;
|
||||
|
||||
switch (level) {
|
||||
case LogLevel.Error:
|
||||
consoleFn = console.error;
|
||||
break;
|
||||
case LogLevel.Warning:
|
||||
consoleFn = console.warn;
|
||||
break;
|
||||
case LogLevel.Info:
|
||||
consoleFn = console.info;
|
||||
break;
|
||||
}
|
||||
|
||||
consoleFn.call(console, ...args);
|
||||
}
|
||||
|
||||
private log(file: URI, messages: [LogLevel, string][]): void {
|
||||
const logger = this.loggers.get(file.toString());
|
||||
if (!logger) {
|
||||
throw new Error('Create the logger before logging');
|
||||
}
|
||||
for (const [level, message] of messages) {
|
||||
log(logger, level, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class LoggerChannelClient extends AbstractLoggerService implements ILoggerService {
|
||||
|
||||
constructor(logLevel: LogLevel, onDidChangeLogLevel: Event<LogLevel>, private readonly channel: IChannel) {
|
||||
super(logLevel, onDidChangeLogLevel);
|
||||
constructor(private readonly windowId: number | undefined, logLevel: LogLevel, onDidChangeLogLevel: Event<LogLevel>, loggers: UriDto<ILoggerResource>[], private readonly channel: IChannel) {
|
||||
super(logLevel, onDidChangeLogLevel, loggers.map(loggerResource => ({ ...loggerResource, resource: URI.revive(loggerResource.resource) })));
|
||||
this._register(channel.listen<ILoggerResource>('onDidChangeLogLevel', windowId)((loggerResource) => super.setLogLevel(URI.revive(loggerResource.resource), loggerResource.logLevel ?? this.logLevel)));
|
||||
this._register(channel.listen<DidChangeLoggerResourceEvent>('onDidChangeLoggerResources', windowId)(({ added, removed }) => {
|
||||
for (const loggerResource of added) {
|
||||
super.registerLoggerResource({ ...loggerResource, resource: URI.revive(loggerResource.resource) });
|
||||
}
|
||||
for (const loggerResource of removed) {
|
||||
super.deregisterLoggerResource(loggerResource.resource);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
createConsoleMainLogger(): ILogger {
|
||||
@@ -122,6 +78,18 @@ export class LoggerChannelClient extends AbstractLoggerService implements ILogge
|
||||
});
|
||||
}
|
||||
|
||||
override registerLoggerResource(resource: ILoggerResource): void {
|
||||
this.channel.call('registerLoggerResource', [resource, this.windowId]);
|
||||
}
|
||||
|
||||
override deregisterLoggerResource(resource: URI): void {
|
||||
this.channel.call('deregisterLoggerResource', [resource, this.windowId]);
|
||||
}
|
||||
|
||||
override setLogLevel(resource: URI, logLevel: LogLevel): void {
|
||||
this.channel.call('setLogLevel', [resource, logLevel]);
|
||||
}
|
||||
|
||||
protected doCreateLogger(file: URI, logLevel: LogLevel, options?: ILoggerOptions): ILogger {
|
||||
return new Logger(this.channel, file, logLevel, options);
|
||||
}
|
||||
|
||||
71
src/vs/platform/log/electron-main/logIpc.ts
Normal file
71
src/vs/platform/log/electron-main/logIpc.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { ILogger, ILoggerOptions, log, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { ILoggerMainService } from 'vs/platform/log/electron-main/loggerService';
|
||||
|
||||
export class LoggerChannel implements IServerChannel {
|
||||
|
||||
private readonly loggers = new Map<string, ILogger>();
|
||||
|
||||
constructor(private readonly loggerService: ILoggerMainService) { }
|
||||
|
||||
listen(_: unknown, event: string, windowId?: number): Event<any> {
|
||||
switch (event) {
|
||||
case 'onDidChangeLoggerResources': return windowId ? this.loggerService.getOnDidChangeLoggerResourcesEvent(windowId) : this.loggerService.onDidChangeLoggerResources;
|
||||
case 'onDidChangeLogLevel': return windowId ? this.loggerService.getOnDidChangeLogLevelEvent(windowId) : this.loggerService.onDidChangeLogLevel;
|
||||
}
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
}
|
||||
|
||||
async call(_: unknown, command: string, arg?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'createLogger': this.createLogger(URI.revive(arg[0]), arg[1]); return;
|
||||
case 'log': return this.log(URI.revive(arg[0]), arg[1]);
|
||||
case 'consoleLog': return this.consoleLog(arg[0], arg[1]);
|
||||
case 'setLogLevel': return this.loggerService.setLogLevel(URI.revive(arg[0]), arg[1]);
|
||||
case 'registerLoggerResource': return this.loggerService.registerLoggerResource({ ...arg[0], resource: URI.revive(arg[0].resource) }, arg[1]);
|
||||
case 'deregisterLoggerResource': return this.loggerService.deregisterLoggerResource(URI.revive(arg[0]));
|
||||
}
|
||||
|
||||
throw new Error(`Call not found: ${command}`);
|
||||
}
|
||||
|
||||
private createLogger(file: URI, options: ILoggerOptions): void {
|
||||
this.loggers.set(file.toString(), this.loggerService.createLogger(file, options));
|
||||
}
|
||||
|
||||
private consoleLog(level: LogLevel, args: any[]): void {
|
||||
let consoleFn = console.log;
|
||||
|
||||
switch (level) {
|
||||
case LogLevel.Error:
|
||||
consoleFn = console.error;
|
||||
break;
|
||||
case LogLevel.Warning:
|
||||
consoleFn = console.warn;
|
||||
break;
|
||||
case LogLevel.Info:
|
||||
consoleFn = console.info;
|
||||
break;
|
||||
}
|
||||
|
||||
consoleFn.call(console, ...args);
|
||||
}
|
||||
|
||||
private log(file: URI, messages: [LogLevel, string][]): void {
|
||||
const logger = this.loggers.get(file.toString());
|
||||
if (!logger) {
|
||||
throw new Error('Create the logger before logging');
|
||||
}
|
||||
for (const [level, message] of messages) {
|
||||
log(logger, level, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
88
src/vs/platform/log/electron-main/loggerService.ts
Normal file
88
src/vs/platform/log/electron-main/loggerService.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { refineServiceDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { DidChangeLoggerResourceEvent, ILoggerResource, ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
|
||||
export const ILoggerMainService = refineServiceDecorator<ILoggerService, ILoggerMainService>(ILoggerService);
|
||||
|
||||
export interface ILoggerMainService extends ILoggerService {
|
||||
|
||||
getOnDidChangeLogLevelEvent(windowId: number): Event<ILoggerResource>;
|
||||
|
||||
getOnDidChangeLoggerResourcesEvent(windowId: number): Event<DidChangeLoggerResourceEvent>;
|
||||
|
||||
registerLoggerResource(resource: ILoggerResource, windowId?: number): void;
|
||||
|
||||
getLoggerResources(windowId?: number): ILoggerResource[];
|
||||
|
||||
deregisterLoggerResources(windowId: number): void;
|
||||
|
||||
}
|
||||
|
||||
export class LoggerMainService extends LoggerService implements ILoggerMainService {
|
||||
|
||||
private readonly loggerResourcesByWindow = new ResourceMap<number>();
|
||||
|
||||
override registerLoggerResource(resource: ILoggerResource, windowId?: number): void {
|
||||
if (windowId !== undefined) {
|
||||
this.loggerResourcesByWindow.set(resource.resource, windowId);
|
||||
}
|
||||
super.registerLoggerResource(resource);
|
||||
}
|
||||
|
||||
override deregisterLoggerResource(resource: URI): void {
|
||||
this.loggerResourcesByWindow.delete(resource);
|
||||
super.deregisterLoggerResource(resource);
|
||||
}
|
||||
|
||||
override getLoggerResources(windowId?: number): ILoggerResource[] {
|
||||
const resources: ILoggerResource[] = [];
|
||||
for (const resource of super.getLoggerResources()) {
|
||||
if (this.isInterestedLoggerResource(resource.resource, windowId)) {
|
||||
resources.push(resource);
|
||||
}
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
|
||||
getOnDidChangeLogLevelEvent(windowId: number): Event<ILoggerResource> {
|
||||
return Event.filter(this.onDidChangeLogLevel, e => this.isInterestedLoggerResource(e.resource, windowId));
|
||||
}
|
||||
|
||||
getOnDidChangeLoggerResourcesEvent(windowId: number): Event<DidChangeLoggerResourceEvent> {
|
||||
return Event.filter(
|
||||
Event.map(this.onDidChangeLoggerResources, e => {
|
||||
const r = {
|
||||
added: [...e.added].filter(loggerResource => this.isInterestedLoggerResource(loggerResource.resource, windowId)),
|
||||
removed: [...e.removed].filter(loggerResource => this.isInterestedLoggerResource(loggerResource.resource, windowId)),
|
||||
};
|
||||
return r;
|
||||
}), e => e.added.length > 0 || e.removed.length > 0);
|
||||
}
|
||||
|
||||
deregisterLoggerResources(windowId: number): void {
|
||||
for (const [resource, resourceWindow] of this.loggerResourcesByWindow) {
|
||||
if (resourceWindow === windowId) {
|
||||
this.deregisterLoggerResource(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private isInterestedLoggerResource(resource: URI, windowId: number | undefined): boolean {
|
||||
const loggerWindowId = this.loggerResourcesByWindow.get(resource);
|
||||
return loggerWindowId === undefined || loggerWindowId === windowId;
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
this.loggerResourcesByWindow.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import { WindowError } from 'vs/platform/window/electron-main/window';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { IPolicyService } from 'vs/platform/policy/common/policy';
|
||||
import { ILoggerMainService } from 'vs/platform/log/electron-main/loggerService';
|
||||
|
||||
export class SharedProcess extends Disposable implements ISharedProcess {
|
||||
|
||||
@@ -42,6 +43,7 @@ export class SharedProcess extends Disposable implements ISharedProcess {
|
||||
@IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService,
|
||||
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@ILoggerMainService private readonly loggerMainService: ILoggerMainService,
|
||||
@IPolicyService private readonly policyService: IPolicyService,
|
||||
@IThemeMainService private readonly themeMainService: IThemeMainService,
|
||||
@IProtocolMainService private readonly protocolMainService: IProtocolMainService
|
||||
@@ -245,6 +247,7 @@ export class SharedProcess extends Disposable implements ISharedProcess {
|
||||
userEnv: this.userEnv,
|
||||
args: this.environmentMainService.args,
|
||||
logLevel: this.logService.getLevel(),
|
||||
loggers: this.loggerMainService.getLoggerResources(),
|
||||
product,
|
||||
policiesData: this.policyService.serialize()
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { ISandboxConfiguration } from 'vs/base/parts/sandbox/common/sandboxTypes';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { LogLevel } from 'vs/platform/log/common/log';
|
||||
import { ILoggerResource, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { PolicyDefinition, PolicyValue } from 'vs/platform/policy/common/policy';
|
||||
import { UriDto } from 'vs/base/common/uri';
|
||||
@@ -27,6 +27,8 @@ export interface ISharedProcessConfiguration extends ISandboxConfiguration {
|
||||
|
||||
readonly logLevel: LogLevel;
|
||||
|
||||
readonly loggers: UriDto<ILoggerResource>[];
|
||||
|
||||
readonly profiles: readonly UriDto<IUserDataProfile>[];
|
||||
|
||||
readonly policiesData?: IStringDictionary<{ definition: PolicyDefinition; value: PolicyValue }>;
|
||||
|
||||
@@ -72,9 +72,13 @@ export class TestTelemetryLoggerService implements ILoggerService {
|
||||
}
|
||||
|
||||
onDidChangeLogLevel = Event.None;
|
||||
setLevel(): void { }
|
||||
onDidChangeLoggerResources = Event.None;
|
||||
setLogLevel(): void { }
|
||||
getLogLevel() { return undefined; }
|
||||
getDefaultLogLevel() { return this.logLevel; }
|
||||
registerLoggerResource() { }
|
||||
deregisterLoggerResource(): void { }
|
||||
getLoggerResources() { return []; }
|
||||
}
|
||||
|
||||
suite('TelemetryLogAdapter', () => {
|
||||
|
||||
@@ -13,14 +13,18 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { parsePtyHostPort } from 'vs/platform/environment/common/environmentService';
|
||||
import { getResolvedShellEnv } from 'vs/platform/shell/node/shellEnv';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ILogService, ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { LogLevelChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { RequestStore } from 'vs/platform/terminal/common/requestStore';
|
||||
import { HeartbeatConstants, IHeartbeatService, IProcessDataEvent, IPtyService, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalLaunchError, ITerminalProfile, ITerminalsLayoutInfo, TerminalIcon, TerminalIpcChannels, IProcessProperty, TitleEventSource, ProcessPropertyType, IProcessPropertyMap, TerminalSettingId, ISerializedTerminalState, ITerminalProcessOptions } from 'vs/platform/terminal/common/terminal';
|
||||
import { HeartbeatConstants, IHeartbeatService, IProcessDataEvent, IPtyService, IReconnectConstants, IRequestResolveVariablesEvent, IShellLaunchConfig, ITerminalLaunchError, ITerminalProfile, ITerminalsLayoutInfo, TerminalIcon, TerminalIpcChannels, IProcessProperty, TitleEventSource, ProcessPropertyType, IProcessPropertyMap, TerminalSettingId, ISerializedTerminalState, ITerminalProcessOptions, TerminalLogConstants } from 'vs/platform/terminal/common/terminal';
|
||||
import { registerTerminalPlatformConfiguration } from 'vs/platform/terminal/common/terminalPlatformConfiguration';
|
||||
import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISetTerminalLayoutInfoArgs } from 'vs/platform/terminal/common/terminalProcess';
|
||||
import { detectAvailableProfiles } from 'vs/platform/terminal/node/terminalProfiles';
|
||||
import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { localize } from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
|
||||
enum Constants {
|
||||
MaxRestarts = 5
|
||||
@@ -82,6 +86,8 @@ export class PtyHostService extends Disposable implements IPtyService {
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@IEnvironmentService private readonly _environmentService: INativeEnvironmentService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@ILoggerService private readonly _loggerService: ILoggerService,
|
||||
@IUriIdentityService private readonly _uriIdentityService: IUriIdentityService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -180,9 +186,16 @@ export class PtyHostService extends Disposable implements IPtyService {
|
||||
// Setup logging
|
||||
const logChannel = client.getChannel(TerminalIpcChannels.Log);
|
||||
LogLevelChannelClient.setLevel(logChannel, this._logService.getLevel());
|
||||
const ptyHostLogResource = URI.file(join(this._environmentService.logsPath, `${TerminalLogConstants.FileName}.log`));
|
||||
this._loggerService.registerLoggerResource({ id: 'ptyHostLog', name: localize('ptyHost', "Pty Host"), resource: ptyHostLogResource });
|
||||
this._register(this._logService.onDidChangeLogLevel(() => {
|
||||
LogLevelChannelClient.setLevel(logChannel, this._logService.getLevel());
|
||||
}));
|
||||
this._register(this._loggerService.onDidChangeLogLevel(({ resource, logLevel }) => {
|
||||
if (this._uriIdentityService.extUri.isEqual(ptyHostLogResource, resource)) {
|
||||
LogLevelChannelClient.setLevel(logChannel, logLevel ?? this._logService.getLevel());
|
||||
}
|
||||
}));
|
||||
|
||||
// Create proxy and forward events
|
||||
const proxy = ProxyChannel.toService<IPtyService>(client.getChannel(TerminalIpcChannels.PtyHost));
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { FileType } from 'vs/platform/files/common/files';
|
||||
import { LogLevel } from 'vs/platform/log/common/log';
|
||||
import { ILoggerResource, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { PolicyDefinition, PolicyValue } from 'vs/platform/policy/common/policy';
|
||||
import { IPartsSplash } from 'vs/platform/theme/common/themeService';
|
||||
import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
@@ -299,6 +299,7 @@ export interface INativeWindowConfiguration extends IWindowConfiguration, Native
|
||||
|
||||
isInitialStartup?: boolean;
|
||||
logLevel: LogLevel;
|
||||
loggers: UriDto<ILoggerResource>[];
|
||||
|
||||
fullscreen?: boolean;
|
||||
maximized?: boolean;
|
||||
|
||||
@@ -50,6 +50,7 @@ import { getPiiPathsFromEnvironment, isInternalTelemetry, ITelemetryAppender, su
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
|
||||
import { hostname, release } from 'os';
|
||||
import { resolveMachineId } from 'vs/platform/telemetry/electron-main/telemetryUtils';
|
||||
import { ILoggerMainService } from 'vs/platform/log/electron-main/loggerService';
|
||||
|
||||
export interface IWindowCreationOptions {
|
||||
readonly state: IWindowState;
|
||||
@@ -183,6 +184,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
constructor(
|
||||
config: IWindowCreationOptions,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@ILoggerMainService private readonly loggerMainService: ILoggerMainService,
|
||||
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService,
|
||||
@IPolicyService private readonly policyService: IPolicyService,
|
||||
@IUserDataProfilesMainService private readonly userDataProfilesService: IUserDataProfilesMainService,
|
||||
@@ -1085,6 +1087,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
profile: this.profile || this.userDataProfilesService.defaultProfile
|
||||
};
|
||||
configuration.logLevel = this.logService.getLevel();
|
||||
configuration.loggers = this.loggerMainService.getLoggerResources(this.id);
|
||||
|
||||
// Load config
|
||||
this.load(configuration, { isReload: true, disableExtensions: cli?.['disable-extensions'] });
|
||||
@@ -1657,6 +1660,9 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
// Deregister the loggers for this window
|
||||
this.loggerMainService.deregisterLoggerResources(this.id);
|
||||
|
||||
this._win = null!; // Important to dereference the window object to allow for GC
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/ed
|
||||
import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { IPolicyService } from 'vs/platform/policy/common/policy';
|
||||
import { IUserDataProfilesMainService } from 'vs/platform/userDataProfile/electron-main/userDataProfile';
|
||||
import { ILoggerMainService } from 'vs/platform/log/electron-main/loggerService';
|
||||
|
||||
//#region Helper Interfaces
|
||||
|
||||
@@ -201,6 +202,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
private readonly machineId: string,
|
||||
private readonly initialUserEnv: IProcessEnvironment,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@ILoggerMainService private readonly loggerService: ILoggerMainService,
|
||||
@IStateMainService private readonly stateMainService: IStateMainService,
|
||||
@IPolicyService private readonly policyService: IPolicyService,
|
||||
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService,
|
||||
@@ -1370,6 +1372,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
filesToWait: options.filesToOpen?.filesToWait,
|
||||
|
||||
logLevel: this.logService.getLevel(),
|
||||
loggers: this.loggerService.getLoggerResources(),
|
||||
logsPath: this.environmentMainService.logsPath,
|
||||
|
||||
product,
|
||||
@@ -1446,6 +1449,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
configuration['extensions-dir'] = currentWindowConfig['extensions-dir'];
|
||||
configuration['disable-extensions'] = currentWindowConfig['disable-extensions'];
|
||||
}
|
||||
configuration.loggers = currentWindowConfig?.loggers ?? configuration.loggers;
|
||||
}
|
||||
|
||||
// Update window identifier and session now
|
||||
|
||||
@@ -38,7 +38,7 @@ import { InstantiationService } from 'vs/platform/instantiation/common/instantia
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
|
||||
import { NativeLanguagePackService } from 'vs/platform/languagePacks/node/languagePacks';
|
||||
import { AbstractLogger, DEFAULT_LOG_LEVEL, getLogLevel, ILogService, LogLevel, MultiplexLogService } from 'vs/platform/log/common/log';
|
||||
import { AbstractLogger, DEFAULT_LOG_LEVEL, getLogLevel, ILoggerService, ILogService, LogLevel, MultiplexLogService } from 'vs/platform/log/common/log';
|
||||
import { LogLevelChannel } from 'vs/platform/log/common/logIpc';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
@@ -98,6 +98,8 @@ export async function setupServerServices(connectionToken: ServerConnectionToken
|
||||
setTimeout(() => cleanupOlderLogs(environmentService.logsPath).then(null, err => logService.error(err)), 10000);
|
||||
|
||||
const loggerService = new LoggerService(logService);
|
||||
services.set(ILoggerService, loggerService);
|
||||
|
||||
bufferLogService.logger = loggerService.createLogger(URI.file(path.join(environmentService.logsPath, `${RemoteExtensionLogFileName}.log`)), { name: RemoteExtensionLogFileName });
|
||||
|
||||
logService.trace(`Remote configuration data at ${REMOTE_DATA_FOLDER}`);
|
||||
|
||||
@@ -11,9 +11,7 @@ import { UriComponents, URI } from 'vs/base/common/uri';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ILogLevelService } from 'vs/workbench/contrib/logs/common/logLevelService';
|
||||
import { IOutputService } from 'vs/workbench/services/output/common/output';
|
||||
import { localExtHostLog, remoteExtHostLog, webWorkerExtHostLog } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadLogger)
|
||||
export class MainThreadLoggerService implements MainThreadLoggerShape {
|
||||
@@ -24,18 +22,11 @@ export class MainThreadLoggerService implements MainThreadLoggerShape {
|
||||
extHostContext: IExtHostContext,
|
||||
@ILogService logService: ILogService,
|
||||
@ILoggerService private readonly loggerService: ILoggerService,
|
||||
@ILogLevelService extensionLoggerService: ILogLevelService,
|
||||
@IOutputService outputService: IOutputService,
|
||||
) {
|
||||
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostLogLevelServiceShape);
|
||||
this.disposables.add(logService.onDidChangeLogLevel(level => proxy.$setLevel(level)));
|
||||
this.disposables.add(extensionLoggerService.onDidChangeLogLevel(({ id, logLevel }) => {
|
||||
const channel = outputService.getChannelDescriptor(id);
|
||||
const resource = channel?.log ? channel.file : undefined;
|
||||
if (resource && (channel?.extensionId || id === localExtHostLog || id === remoteExtHostLog || id === webWorkerExtHostLog)) {
|
||||
proxy.$setLevel(logLevel, resource);
|
||||
}
|
||||
}));
|
||||
this.disposables.add(loggerService.onDidChangeLogLevel(loggerResource => proxy.$setLevel(loggerResource.logLevel ?? logService.getLevel(), loggerResource.resource)));
|
||||
}
|
||||
|
||||
$log(file: UriComponents, messages: [LogLevel, string][]): void {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IViewsService } from 'vs/workbench/common/views';
|
||||
import { isNumber } from 'vs/base/common/types';
|
||||
import { ILoggerService } from 'vs/platform/log/common/log';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadOutputService)
|
||||
export class MainThreadOutputService extends Disposable implements MainThreadOutputServiceShape {
|
||||
@@ -21,15 +22,18 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
|
||||
private readonly _proxy: ExtHostOutputServiceShape;
|
||||
private readonly _outputService: IOutputService;
|
||||
private readonly _viewsService: IViewsService;
|
||||
private readonly _loggerService: ILoggerService;
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IOutputService outputService: IOutputService,
|
||||
@IViewsService viewsService: IViewsService
|
||||
@IViewsService viewsService: IViewsService,
|
||||
@ILoggerService loggerService: ILoggerService,
|
||||
) {
|
||||
super();
|
||||
this._outputService = outputService;
|
||||
this._viewsService = viewsService;
|
||||
this._loggerService = loggerService;
|
||||
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostOutputService);
|
||||
|
||||
@@ -45,8 +49,12 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
|
||||
const idCounter = (MainThreadOutputService._extensionIdPool.get(extensionId) || 0) + 1;
|
||||
MainThreadOutputService._extensionIdPool.set(extensionId, idCounter);
|
||||
const id = `extension-output-${extensionId}-#${idCounter}-${label}`;
|
||||
const resource = URI.revive(file);
|
||||
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id, label, file: URI.revive(file), log, languageId, extensionId });
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id, label, file: resource, log, languageId, extensionId });
|
||||
if (log) {
|
||||
this._loggerService.registerLoggerResource({ resource, id, name: label });
|
||||
}
|
||||
this._register(toDisposable(() => this.$dispose(id)));
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { isUndefined } from 'vs/base/common/types';
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
|
||||
export class ExtHostLoggerService extends AbstractLoggerService implements ExtHostLogLevelServiceShape {
|
||||
|
||||
@@ -20,15 +21,15 @@ export class ExtHostLoggerService extends AbstractLoggerService implements ExtHo
|
||||
@IExtHostRpcService rpc: IExtHostRpcService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
) {
|
||||
super(initData.logLevel, Event.None);
|
||||
super(initData.logLevel, Event.None, initData.loggers.map(logger => revive(logger)));
|
||||
this._proxy = rpc.getProxy(MainContext.MainThreadLogger);
|
||||
}
|
||||
|
||||
$setLevel(level: LogLevel, resource?: UriComponents): void {
|
||||
if (resource) {
|
||||
this.setLevel(URI.revive(resource), level);
|
||||
this.setLogLevel(URI.revive(resource), level);
|
||||
} else if (!isUndefined(level)) {
|
||||
this.setLevel(level);
|
||||
this.setGlobalLogLevel(level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -246,12 +246,16 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
|
||||
}
|
||||
};
|
||||
const onDidChangeLogLevel = disposables.add(new Emitter<LogLevel>());
|
||||
function setLogLevel(newLogLevel: LogLevel): void {
|
||||
logLevel = newLogLevel;
|
||||
onDidChangeLogLevel.fire(newLogLevel);
|
||||
}
|
||||
channelPromise.then(channel => {
|
||||
disposables.add(channel);
|
||||
disposables.add(channel.onDidChangeLogLevel(e => {
|
||||
logLevel = e;
|
||||
onDidChangeLogLevel.fire(e);
|
||||
}));
|
||||
if (channel.logLevel !== logLevel) {
|
||||
setLogLevel(channel.logLevel);
|
||||
}
|
||||
disposables.add(channel.onDidChangeLogLevel(e => setLogLevel(e)));
|
||||
});
|
||||
return {
|
||||
...this.createExtHostOutputChannel(name, channelPromise),
|
||||
|
||||
@@ -12,10 +12,6 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { LogsDataCleaner } from 'vs/workbench/contrib/logs/common/logsDataCleaner';
|
||||
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ILogLevelService, LogLevelService } from 'vs/workbench/contrib/logs/common/logLevelService';
|
||||
|
||||
registerSingleton(ILogLevelService, LogLevelService, InstantiationType.Delayed);
|
||||
|
||||
class WebLogOutputChannels extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ILoggerService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IOutputService } from 'vs/workbench/services/output/common/output';
|
||||
|
||||
export const ILogLevelService = createDecorator<ILogLevelService>('ILogLevelService');
|
||||
export interface ILogLevelService {
|
||||
readonly _serviceBrand: undefined;
|
||||
readonly onDidChangeLogLevel: Event<{ readonly id: string; logLevel: LogLevel }>;
|
||||
setLogLevel(id: string, logLevel: LogLevel): void;
|
||||
getLogLevel(id: string): LogLevel | undefined;
|
||||
}
|
||||
|
||||
export class LogLevelService extends Disposable implements ILogLevelService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _onDidChangeLogLevel = this._register(new Emitter<{ readonly id: string; logLevel: LogLevel }>());
|
||||
readonly onDidChangeLogLevel = this._onDidChangeLogLevel.event;
|
||||
|
||||
private readonly logLevels = new Map<string, LogLevel>();
|
||||
|
||||
constructor(
|
||||
@IOutputService protected readonly outputService: IOutputService,
|
||||
@ILoggerService private readonly loggerService: ILoggerService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
getLogLevel(id: string): LogLevel | undefined {
|
||||
return this.logLevels.get(id);
|
||||
}
|
||||
|
||||
setLogLevel(id: string, logLevel: LogLevel): boolean {
|
||||
if (this.getLogLevel(id) === logLevel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.logLevels.set(id, logLevel);
|
||||
const channel = this.outputService.getChannelDescriptor(id);
|
||||
const resource = channel?.log ? channel.file : undefined;
|
||||
if (resource) {
|
||||
this.loggerService.setLevel(resource, logLevel);
|
||||
}
|
||||
this._onDidChangeLogLevel.fire({ id, logLevel });
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,22 +5,21 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { ILogService, LogLevel, getLogLevel, parseLogLevel } from 'vs/platform/log/common/log';
|
||||
import { ILogService, ILoggerService, LogLevel, getLogLevel, parseLogLevel } from 'vs/platform/log/common/log';
|
||||
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { dirname, basename, isEqual } from 'vs/base/common/resources';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IOutputChannelDescriptor, IOutputService } from 'vs/workbench/services/output/common/output';
|
||||
import { IOutputService } from 'vs/workbench/services/output/common/output';
|
||||
import { isNumber } from 'vs/base/common/types';
|
||||
import { ILogLevelService } from 'vs/workbench/contrib/logs/common/logLevelService';
|
||||
import { extensionTelemetryLogChannelId, telemetryLogChannelId } from 'vs/workbench/contrib/logs/common/logConstants';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
|
||||
type LogLevelQuickPickItem = IQuickPickItem & { level: LogLevel };
|
||||
type LogChannelQuickPickItem = IQuickPickItem & { channel: IOutputChannelDescriptor };
|
||||
type LogChannelQuickPickItem = IQuickPickItem & { id: string; resource: URI; extensionId?: string };
|
||||
|
||||
function isLogLevel(thing: unknown): thing is LogLevel {
|
||||
return isNumber(thing);
|
||||
@@ -34,7 +33,7 @@ export class SetLogLevelAction extends Action {
|
||||
constructor(id: string, label: string,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@ILogLevelService private readonly logLevelService: ILogLevelService,
|
||||
@ILoggerService private readonly loggerService: ILoggerService,
|
||||
@IOutputService private readonly outputService: IOutputService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
) {
|
||||
@@ -52,54 +51,44 @@ export class SetLogLevelAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
private async selectLogLevelOrChannel(): Promise<IOutputChannelDescriptor | LogLevel | null> {
|
||||
const extensionLogs = [], logs = [];
|
||||
private async selectLogLevelOrChannel(): Promise<LogChannelQuickPickItem | LogLevel | null> {
|
||||
const extensionLogs: LogChannelQuickPickItem[] = [], logs: LogChannelQuickPickItem[] = [];
|
||||
const logLevel = this.logService.getLevel();
|
||||
for (const channel of this.outputService.getChannelDescriptors()) {
|
||||
if (!channel.log || channel.id === telemetryLogChannelId || channel.id === extensionTelemetryLogChannelId) {
|
||||
if (!channel.log || !channel.file || channel.id === telemetryLogChannelId || channel.id === extensionTelemetryLogChannelId) {
|
||||
continue;
|
||||
}
|
||||
const channelLogLevel = this.loggerService.getLogLevel(channel.file) ?? logLevel;
|
||||
const item: LogChannelQuickPickItem = { id: channel.id, resource: channel.file, label: channel.label, description: channelLogLevel !== logLevel ? this.getLabel(channelLogLevel) : undefined, extensionId: channel.extensionId };
|
||||
if (channel.extensionId) {
|
||||
extensionLogs.push(channel);
|
||||
extensionLogs.push(item);
|
||||
} else {
|
||||
logs.push(channel);
|
||||
logs.push(item);
|
||||
}
|
||||
}
|
||||
const entries: (LogLevelQuickPickItem | LogChannelQuickPickItem | IQuickPickSeparator)[] = [];
|
||||
entries.push({ type: 'separator', label: nls.localize('all', "All") });
|
||||
entries.push(...this.getLogLevelEntries(this.getDefaultLogLevel(null), this.logService.getLevel()));
|
||||
entries.push(...this.getLogLevelEntries(this.getDefaultLogLevel(), this.logService.getLevel()));
|
||||
entries.push({ type: 'separator', label: nls.localize('loggers', "Logs") });
|
||||
const logLevel = this.logService.getLevel();
|
||||
for (const channel of logs.sort((a, b) => a.label.localeCompare(b.label))) {
|
||||
const channelLogLevel = this.logLevelService.getLogLevel(channel.id) ?? logLevel;
|
||||
entries.push({ label: channel.label, channel, description: channelLogLevel !== logLevel ? this.getLabel(channelLogLevel) : undefined });
|
||||
}
|
||||
entries.push(...logs.sort((a, b) => a.label.localeCompare(b.label)));
|
||||
if (extensionLogs.length && logs.length) {
|
||||
entries.push({ type: 'separator', label: nls.localize('extensionLogs', "Extension Logs") });
|
||||
}
|
||||
for (const channel of extensionLogs.sort((a, b) => a.label.localeCompare(b.label))) {
|
||||
const channelLogLevel = this.logLevelService.getLogLevel(channel.id) ?? logLevel;
|
||||
entries.push({ label: channel.label, channel, description: channelLogLevel !== logLevel ? this.getLabel(channelLogLevel) : undefined });
|
||||
}
|
||||
entries.push(...extensionLogs.sort((a, b) => a.label.localeCompare(b.label)));
|
||||
const entry = await this.quickInputService.pick(entries, { placeHolder: nls.localize('selectlog', "Set Log Level") });
|
||||
if (entry) {
|
||||
if ((<LogLevelQuickPickItem>entry).level) {
|
||||
return (<LogLevelQuickPickItem>entry).level;
|
||||
}
|
||||
if ((<LogChannelQuickPickItem>entry).channel) {
|
||||
return (<LogChannelQuickPickItem>entry).channel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return entry
|
||||
? (<LogLevelQuickPickItem>entry).level ? (<LogLevelQuickPickItem>entry).level : <LogChannelQuickPickItem>entry
|
||||
: null;
|
||||
}
|
||||
|
||||
private async setLogLevelForChannel(logChannel: IOutputChannelDescriptor): Promise<void> {
|
||||
const defaultLogLevel = this.getDefaultLogLevel(logChannel);
|
||||
const currentLogLevel = this.logLevelService.getLogLevel(logChannel.id) ?? defaultLogLevel;
|
||||
private async setLogLevelForChannel(logChannel: LogChannelQuickPickItem): Promise<void> {
|
||||
const defaultLogLevel = this.getDefaultLogLevel(logChannel.extensionId);
|
||||
const currentLogLevel = this.loggerService.getLogLevel(logChannel.resource) ?? defaultLogLevel;
|
||||
const entries = this.getLogLevelEntries(defaultLogLevel, currentLogLevel);
|
||||
|
||||
const entry = await this.quickInputService.pick(entries, { placeHolder: logChannel ? nls.localize('selectLogLevelFor', " {0}: Select log level", logChannel?.label) : nls.localize('selectLogLevel', "Select log level"), activeItem: entries[this.logService.getLevel()] });
|
||||
if (entry) {
|
||||
this.logLevelService.setLogLevel(logChannel.id, entry.level);
|
||||
this.loggerService.setLogLevel(logChannel.resource, entry.level);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,10 +121,10 @@ export class SetLogLevelAction extends Action {
|
||||
return defaultLogLevel === level ? nls.localize('default', "Default") : undefined;
|
||||
}
|
||||
|
||||
private getDefaultLogLevel(outputChannel: IOutputChannelDescriptor | null): LogLevel {
|
||||
private getDefaultLogLevel(extensionId?: string): LogLevel {
|
||||
let logLevel: LogLevel | undefined;
|
||||
if (outputChannel?.extensionId) {
|
||||
const logLevelValue = this.environmentService.extensionLogLevel?.find(([id]) => areSameExtensions({ id }, { id: outputChannel.extensionId! }))?.[1];
|
||||
if (extensionId) {
|
||||
const logLevelValue = this.environmentService.extensionLogLevel?.find(([id]) => areSameExtensions({ id }, { id: extensionId }))?.[1];
|
||||
if (logLevelValue) {
|
||||
logLevel = parseLogLevel(logLevelValue);
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ILoggerService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { IOutputService } from 'vs/workbench/services/output/common/output';
|
||||
import { IMainProcessService, ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/services';
|
||||
import { LogLevelService as CommonLogLevelService } from 'vs/workbench/contrib/logs/common/logLevelService';
|
||||
import { remotePtyHostLog, remoteServerLog, sharedLogChannelId, userDataSyncLogChannelId } from 'vs/workbench/contrib/logs/common/logConstants';
|
||||
import { LogLevelChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { LOG_CHANNEL_ID as remoteTunnelLogChannelId } from 'vs/platform/remoteTunnel/common/remoteTunnel';
|
||||
|
||||
export class LogLevelService extends CommonLogLevelService {
|
||||
|
||||
constructor(
|
||||
@IOutputService outputService: IOutputService,
|
||||
@ILoggerService loggerService: ILoggerService,
|
||||
@ISharedProcessService private readonly sharedProcessService: ISharedProcessService,
|
||||
@IMainProcessService private readonly mainProcessService: IMainProcessService,
|
||||
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
|
||||
) {
|
||||
super(outputService, loggerService);
|
||||
}
|
||||
|
||||
override setLogLevel(id: string, logLevel: LogLevel): boolean {
|
||||
if (!super.setLogLevel(id, logLevel)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const channel = this.outputService.getChannelDescriptor(id);
|
||||
const resource = channel?.log ? channel.file : undefined;
|
||||
|
||||
LogLevelChannelClient.setLevel(this.mainProcessService.getChannel('logLevel'), logLevel, resource);
|
||||
if (id === sharedLogChannelId || id === userDataSyncLogChannelId || id === remoteTunnelLogChannelId) {
|
||||
LogLevelChannelClient.setLevel(this.sharedProcessService.getChannel('logLevel'), logLevel, resource);
|
||||
return true;
|
||||
}
|
||||
|
||||
const connection = this.remoteAgentService.getConnection();
|
||||
if ((id === remoteServerLog || id === remotePtyHostLog) && connection) {
|
||||
connection.withChannel('logger', (channel) => LogLevelChannelClient.setLevel(channel, logLevel, resource));
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,11 +20,6 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
|
||||
import { registerLogChannel } from 'vs/workbench/services/output/common/output';
|
||||
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ILogLevelService } from 'vs/workbench/contrib/logs/common/logLevelService';
|
||||
import { LogLevelService } from 'vs/workbench/contrib/logs/electron-sandbox/logLevelService';
|
||||
|
||||
registerSingleton(ILogLevelService, LogLevelService, InstantiationType.Delayed);
|
||||
|
||||
class NativeLogOutputChannels extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import { DownloadServiceChannel } from 'vs/platform/download/common/downloadIpc'
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { TerminalLogConstants } from 'vs/platform/terminal/common/terminal';
|
||||
import { remotePtyHostLog, remoteServerLog } from 'vs/workbench/contrib/logs/common/logConstants';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
|
||||
export class LabelContribution implements IWorkbenchContribution {
|
||||
constructor(
|
||||
@@ -93,18 +94,36 @@ class RemoteChannelsContribution extends Disposable implements IWorkbenchContrib
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteLogOutputChannels implements IWorkbenchContribution {
|
||||
class RemoteLogOutputChannels extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
constructor(
|
||||
@IRemoteAgentService remoteAgentService: IRemoteAgentService
|
||||
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
|
||||
@ILoggerService loggerService: ILoggerService,
|
||||
@ILogService logService: ILogService,
|
||||
@IUriIdentityService uriIdentityService: IUriIdentityService,
|
||||
) {
|
||||
remoteAgentService.getEnvironment().then(remoteEnv => {
|
||||
if (remoteEnv) {
|
||||
const outputChannelRegistry = Registry.as<IOutputChannelRegistry>(OutputExt.OutputChannels);
|
||||
outputChannelRegistry.registerChannel({ id: remoteServerLog, label: localize('remoteExtensionLog', "Remote Server"), file: joinPath(remoteEnv.logsPath, `${RemoteExtensionLogFileName}.log`), log: true });
|
||||
outputChannelRegistry.registerChannel({ id: remotePtyHostLog, label: localize('remotePtyHostLog', "Remote Pty Host"), file: joinPath(remoteEnv.logsPath, `${TerminalLogConstants.FileName}.log`), log: true });
|
||||
}
|
||||
});
|
||||
super();
|
||||
const connection = remoteAgentService.getConnection();
|
||||
if (connection) {
|
||||
remoteAgentService.getEnvironment().then(remoteEnv => {
|
||||
if (remoteEnv) {
|
||||
const outputChannelRegistry = Registry.as<IOutputChannelRegistry>(OutputExt.OutputChannels);
|
||||
const remoteExtensionHostLogFile = joinPath(remoteEnv.logsPath, `${RemoteExtensionLogFileName}.log`);
|
||||
const remotePtyLogFile = joinPath(remoteEnv.logsPath, `${TerminalLogConstants.FileName}.log`);
|
||||
const remoteServerLoggerResource = { id: remoteServerLog, name: localize('remoteExtensionLog', "Remote Server"), resource: remoteExtensionHostLogFile };
|
||||
loggerService.registerLoggerResource(remoteServerLoggerResource);
|
||||
outputChannelRegistry.registerChannel({ id: remoteServerLoggerResource.id, label: remoteServerLoggerResource.name, file: remoteServerLoggerResource.resource, log: true });
|
||||
const remotePtyHostLoggerResource = { id: remotePtyHostLog, name: localize('remotePtyHostLog', "Remote Pty Host"), resource: remotePtyLogFile };
|
||||
loggerService.registerLoggerResource(remotePtyHostLoggerResource);
|
||||
outputChannelRegistry.registerChannel({ id: remotePtyHostLoggerResource.id, label: remotePtyHostLoggerResource.name, file: remotePtyHostLoggerResource.resource, log: true });
|
||||
this._register(loggerService.onDidChangeLogLevel(({ resource, logLevel }) => {
|
||||
if (uriIdentityService.extUri.isEqual(resource, remoteExtensionHostLogFile) || uriIdentityService.extUri.isEqual(resource, remotePtyLogFile)) {
|
||||
connection.withChannel('logger', (channel) => LogLevelChannelClient.setLevel(channel, logLevel ?? logService.getLevel(), resource));
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ export class DesktopMain extends Disposable {
|
||||
|
||||
// Logger
|
||||
const logLevelChannelClient = new LogLevelChannelClient(mainProcessService.getChannel('logLevel'));
|
||||
const loggerService = new LoggerChannelClient(this.configuration.logLevel, logLevelChannelClient.onDidChangeLogLevel, mainProcessService.getChannel('logger'));
|
||||
const loggerService = new LoggerChannelClient(this.configuration.windowId, this.configuration.logLevel, logLevelChannelClient.onDidChangeLogLevel, this.configuration.loggers, mainProcessService.getChannel('logger'));
|
||||
serviceCollection.set(ILoggerService, loggerService);
|
||||
|
||||
// Log
|
||||
|
||||
@@ -11,7 +11,7 @@ import { createMessageOfType, MessageType, isMessageOfType, ExtensionHostExitCod
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ILogService, ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
@@ -66,6 +66,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
||||
@IWorkspaceContextService private readonly _contextService: IWorkspaceContextService,
|
||||
@ILabelService private readonly _labelService: ILabelService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@ILoggerService private readonly _loggerService: ILoggerService,
|
||||
@IBrowserWorkbenchEnvironmentService private readonly _environmentService: IBrowserWorkbenchEnvironmentService,
|
||||
@IUserDataProfilesService private readonly _userDataProfilesService: IUserDataProfilesService,
|
||||
@IProductService private readonly _productService: IProductService,
|
||||
@@ -251,7 +252,9 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
||||
}
|
||||
|
||||
// Register log channel for web worker exthost log
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id: webWorkerExtHostLog, label: localize('name', "Worker Extension Host"), file: this._extensionHostLogFile, log: true });
|
||||
const webWorkerExtHostLoggerResource = { id: webWorkerExtHostLog, name: localize('name', "Worker Extension Host"), resource: this._extensionHostLogFile };
|
||||
this._loggerService.registerLoggerResource(webWorkerExtHostLoggerResource);
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id: webWorkerExtHostLoggerResource.id, label: webWorkerExtHostLoggerResource.name, file: webWorkerExtHostLoggerResource.resource, log: true });
|
||||
|
||||
return protocol;
|
||||
}
|
||||
@@ -315,6 +318,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
||||
nlsBaseUrl: nlsUrlWithDetails,
|
||||
telemetryInfo,
|
||||
logLevel: this._logService.getLevel(),
|
||||
loggers: [...this._loggerService.getLoggerResources()],
|
||||
logsLocation: this._extensionHostLogsLocation,
|
||||
logFile: this._extensionHostLogFile,
|
||||
autoStart: initData.autoStart,
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { URI, UriComponents, UriDto } from 'vs/base/common/uri';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { LogLevel } from 'vs/platform/log/common/log';
|
||||
import { ILoggerResource, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { IRemoteConnectionData } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
@@ -31,6 +31,7 @@ export interface IExtensionHostInitData {
|
||||
nlsBaseUrl?: URI;
|
||||
telemetryInfo: ITelemetryInfo;
|
||||
logLevel: LogLevel;
|
||||
loggers: UriDto<ILoggerResource>[];
|
||||
logsLocation: URI;
|
||||
logFile: URI;
|
||||
autoStart: boolean;
|
||||
|
||||
@@ -16,7 +16,7 @@ import { localize } from 'vs/nls';
|
||||
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ILogService, ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { connectRemoteAgentExtensionHost, IConnectionOptions, IRemoteExtensionHostStartParams, ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
@@ -68,6 +68,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
|
||||
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@ILoggerService protected readonly _loggerService: ILoggerService,
|
||||
@ILabelService private readonly _labelService: ILabelService,
|
||||
@IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService,
|
||||
@IExtensionHostDebugService private readonly _extensionHostDebugService: IExtensionHostDebugService,
|
||||
@@ -171,7 +172,9 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
|
||||
disposable.dispose();
|
||||
|
||||
// Register log channel for remote exthost log
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id: remoteExtHostLog, label: localize('remote extension host Log', "Remote Extension Host"), file: logFile, log: true });
|
||||
const remoteExtHostLoggerResource = { id: remoteExtHostLog, name: localize('remote extension host Log', "Remote Extension Host"), resource: logFile };
|
||||
this._loggerService.registerLoggerResource(remoteExtHostLoggerResource);
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id: remoteExtHostLoggerResource.id, label: remoteExtHostLoggerResource.name, file: remoteExtHostLoggerResource.resource, log: true });
|
||||
|
||||
// release this promise
|
||||
this._protocol = protocol;
|
||||
@@ -248,6 +251,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
|
||||
myExtensions: deltaExtensions.myToAdd,
|
||||
telemetryInfo,
|
||||
logLevel: this._logService.getLevel(),
|
||||
loggers: [...this._loggerService.getLoggerResources()],
|
||||
logsLocation: remoteInitData.extensionHostLogsPath,
|
||||
logFile: joinPath(remoteInitData.extensionHostLogsPath, `${ExtensionHostLogFileName}.log`),
|
||||
autoStart: true,
|
||||
|
||||
@@ -16,7 +16,7 @@ import { BufferedEmitter } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { ILifecycleService, WillShutdownEvent } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ILogService, ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
@@ -139,6 +139,7 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {
|
||||
@IUserDataProfilesService private readonly _userDataProfilesService: IUserDataProfilesService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@ILogService protected readonly _logService: ILogService,
|
||||
@ILoggerService protected readonly _loggerService: ILoggerService,
|
||||
@ILabelService private readonly _labelService: ILabelService,
|
||||
@IExtensionHostDebugService private readonly _extensionHostDebugService: IExtensionHostDebugService,
|
||||
@IHostService private readonly _hostService: IHostService,
|
||||
@@ -417,7 +418,9 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {
|
||||
disposable.dispose();
|
||||
|
||||
// Register log channel for exthost log
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id: localExtHostLog, label: nls.localize('extension host Log', "Extension Host"), file: this._extensionHostLogFile, log: true });
|
||||
const localExtHostLoggerResource = { id: localExtHostLog, name: nls.localize('extension host Log', "Extension Host"), resource: this._extensionHostLogFile };
|
||||
this._loggerService.registerLoggerResource(localExtHostLoggerResource);
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id: localExtHostLoggerResource.id, label: localExtHostLoggerResource.name, file: localExtHostLoggerResource.resource, log: true });
|
||||
|
||||
// release this promise
|
||||
resolve();
|
||||
@@ -472,6 +475,7 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {
|
||||
myExtensions: deltaExtensions.myToAdd,
|
||||
telemetryInfo,
|
||||
logLevel: this._logService.getLevel(),
|
||||
loggers: [...this._loggerService.getLoggerResources()],
|
||||
logsLocation: this._environmentService.extHostLogsPath,
|
||||
logFile: this._extensionHostLogFile,
|
||||
autoStart: initData.autoStart,
|
||||
|
||||
@@ -75,6 +75,7 @@ export const TestNativeWindowConfiguration: INativeWindowConfiguration = {
|
||||
windowId: 0,
|
||||
machineId: 'testMachineId',
|
||||
logLevel: LogLevel.Error,
|
||||
loggers: [],
|
||||
mainPid: 0,
|
||||
appRoot: '',
|
||||
userEnv: {},
|
||||
|
||||
Reference in New Issue
Block a user