mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-20 00:04:14 +08:00
Log: Enhancements and cleaup (#171325)
- Make logger service primary source for log level - Automatically register output channels for loggers from anywhere - Use logger channels on remote processes (server, pty) - clean up loggers and log service
This commit is contained in:
parent
a2bdb408ba
commit
05d59b893e
@ -48,8 +48,8 @@ import { MessagePortMainProcessService } from 'vs/platform/ipc/electron-browser/
|
||||
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/services';
|
||||
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
|
||||
import { NativeLanguagePackService } from 'vs/platform/languagePacks/node/languagePacks';
|
||||
import { ConsoleLogger, ILoggerService, ILogService, MultiplexLogService } from 'vs/platform/log/common/log';
|
||||
import { FollowerLogService, LoggerChannelClient, LogLevelChannel, LogLevelChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { ConsoleLogger, ILoggerService, ILogService } from 'vs/platform/log/common/log';
|
||||
import { LoggerChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
@ -115,6 +115,7 @@ import { UserDataSyncResourceProviderService } from 'vs/platform/userDataSync/co
|
||||
import { ExtensionsContributions } from 'vs/code/electron-browser/sharedProcess/contrib/extensions';
|
||||
import { ExtensionsProfileScannerService } from 'vs/platform/extensionManagement/electron-sandbox/extensionsProfileScannerService';
|
||||
import { localize } from 'vs/nls';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
|
||||
class SharedProcessMain extends Disposable {
|
||||
|
||||
@ -216,17 +217,13 @@ class SharedProcessMain extends Disposable {
|
||||
services.set(INativeEnvironmentService, environmentService);
|
||||
|
||||
// Logger
|
||||
const logLevelClient = new LogLevelChannelClient(this.server.getChannel('logLevel', mainRouter));
|
||||
const loggerService = new LoggerChannelClient(undefined, this.configuration.logLevel, logLevelClient.onDidChangeLogLevel, this.configuration.loggers, mainProcessService.getChannel('logger'));
|
||||
const loggerService = new LoggerChannelClient(undefined, this.configuration.logLevel, this.configuration.loggers, mainProcessService.getChannel('logger'));
|
||||
services.set(ILoggerService, loggerService);
|
||||
|
||||
// Log
|
||||
const multiplexLogger = this._register(new MultiplexLogService([
|
||||
this._register(new ConsoleLogger(this.configuration.logLevel)),
|
||||
this._register(loggerService.createLogger(joinPath(URI.file(environmentService.logsPath), 'sharedprocess.log'), { id: 'sharedLog', name: localize('sharedLog', "Shared") }))
|
||||
]));
|
||||
|
||||
const logService = this._register(new FollowerLogService(logLevelClient, multiplexLogger));
|
||||
const logger = this._register(loggerService.createLogger(joinPath(URI.file(environmentService.logsPath), 'sharedprocess.log'), { id: 'sharedLog', name: localize('sharedLog', "Shared") }));
|
||||
const consoleLogger = this._register(new ConsoleLogger(this.configuration.logLevel));
|
||||
const logService = this._register(new LogService(logger, [consoleLogger]));
|
||||
services.set(ILogService, logService);
|
||||
|
||||
// Lifecycle
|
||||
@ -374,11 +371,11 @@ class SharedProcessMain extends Disposable {
|
||||
shortGraceTime: LocalReconnectConstants.ShortGraceTime,
|
||||
scrollback: configurationService.getValue<number>(TerminalSettingId.PersistentSessionScrollback) ?? 100
|
||||
},
|
||||
localize('ptyHost', "Pty Host"),
|
||||
configurationService,
|
||||
environmentService,
|
||||
logService,
|
||||
loggerService,
|
||||
uriIdentityService
|
||||
loggerService
|
||||
);
|
||||
ptyHostService.initialize();
|
||||
|
||||
@ -399,10 +396,6 @@ class SharedProcessMain extends Disposable {
|
||||
|
||||
private initChannels(accessor: ServicesAccessor): void {
|
||||
|
||||
// Log Level
|
||||
const logLevelChannel = new LogLevelChannel(accessor.get(ILogService), accessor.get(ILoggerService));
|
||||
this.server.registerChannel('logLevel', logLevelChannel);
|
||||
|
||||
// Extensions Management
|
||||
const channel = new ExtensionManagementChannel(accessor.get(IExtensionManagementService), () => null);
|
||||
this.server.registerChannel('extensions', channel);
|
||||
|
||||
@ -58,8 +58,7 @@ import { IIssueMainService, IssueMainService } from 'vs/platform/issue/electron-
|
||||
import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService';
|
||||
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 { LogLevelChannel } from 'vs/platform/log/common/logIpc';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
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';
|
||||
@ -800,11 +799,6 @@ export class CodeApplication extends Disposable {
|
||||
const externalTerminalChannel = ProxyChannel.fromService(accessor.get(IExternalTerminalMainService));
|
||||
mainProcessElectronServer.registerChannel('externalTerminal', externalTerminalChannel);
|
||||
|
||||
// Log Level (main & shared process)
|
||||
const logLevelChannel = new LogLevelChannel(accessor.get(ILogService), accessor.get(ILoggerService));
|
||||
mainProcessElectronServer.registerChannel('logLevel', logLevelChannel);
|
||||
sharedProcessClient.then(client => client.registerChannel('logLevel', logLevelChannel));
|
||||
|
||||
// Logger
|
||||
const loggerChannel = new LoggerChannel(accessor.get(ILoggerMainService),);
|
||||
mainProcessElectronServer.registerChannel('logger', loggerChannel);
|
||||
|
||||
@ -44,8 +44,8 @@ import { InstantiationService } from 'vs/platform/instantiation/common/instantia
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService';
|
||||
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 { BufferLogger } from 'vs/platform/log/common/bufferLog';
|
||||
import { ConsoleMainLogger, getLogLevel, ILoggerService, ILogService } from 'vs/platform/log/common/log';
|
||||
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 +69,7 @@ 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';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
|
||||
/**
|
||||
* The main VS Code entry point.
|
||||
@ -145,7 +146,7 @@ class CodeMain {
|
||||
}
|
||||
}
|
||||
|
||||
private createServices(): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateMainService, BufferLogService, IProductService, UserDataProfilesMainService] {
|
||||
private createServices(): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateMainService, BufferLogger, IProductService, UserDataProfilesMainService] {
|
||||
const services = new ServiceCollection();
|
||||
const disposables = new DisposableStore();
|
||||
process.once('exit', () => disposables.dispose());
|
||||
@ -159,11 +160,15 @@ class CodeMain {
|
||||
const instanceEnvironment = this.patchEnvironment(environmentMainService); // Patch `process.env` with the instance's environment
|
||||
services.set(IEnvironmentMainService, environmentMainService);
|
||||
|
||||
// Logger
|
||||
const loggerService = new LoggerMainService(getLogLevel(environmentMainService));
|
||||
services.set(ILoggerMainService, loggerService);
|
||||
|
||||
// Log: We need to buffer the spdlog logs until we are sure
|
||||
// we are the only instance running, otherwise we'll have concurrent
|
||||
// log file access on Windows (https://github.com/microsoft/vscode/issues/41218)
|
||||
const bufferLogService = new BufferLogService();
|
||||
const logService = disposables.add(new MultiplexLogService([new ConsoleMainLogger(getLogLevel(environmentMainService)), bufferLogService]));
|
||||
const bufferLogger = new BufferLogger(loggerService.getLogLevel());
|
||||
const logService = disposables.add(new LogService(bufferLogger, [new ConsoleMainLogger(loggerService.getLogLevel())]));
|
||||
services.set(ILogService, logService);
|
||||
|
||||
// Files
|
||||
@ -176,9 +181,6 @@ class CodeMain {
|
||||
const uriIdentityService = new UriIdentityService(fileService);
|
||||
services.set(IUriIdentityService, uriIdentityService);
|
||||
|
||||
// Logger
|
||||
services.set(ILoggerMainService, new LoggerMainService(logService));
|
||||
|
||||
// State
|
||||
const stateMainService = new StateMainService(environmentMainService, logService, fileService);
|
||||
services.set(IStateMainService, stateMainService);
|
||||
@ -215,7 +217,7 @@ class CodeMain {
|
||||
// Protocol (instantiated early and not using sync descriptor for security reasons)
|
||||
services.set(IProtocolMainService, new ProtocolMainService(environmentMainService, userDataProfilesMainService, logService));
|
||||
|
||||
return [new InstantiationService(services, true), instanceEnvironment, environmentMainService, configurationService, stateMainService, bufferLogService, productService, userDataProfilesMainService];
|
||||
return [new InstantiationService(services, true), instanceEnvironment, environmentMainService, configurationService, stateMainService, bufferLogger, productService, userDataProfilesMainService];
|
||||
}
|
||||
|
||||
private patchEnvironment(environmentMainService: IEnvironmentMainService): IProcessEnvironment {
|
||||
|
||||
@ -39,7 +39,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 { ConsoleLogger, getLogLevel, ILogger, ILogService, LogLevel, MultiplexLogService } from 'vs/platform/log/common/log';
|
||||
import { ConsoleLogger, getLogLevel, ILogger, ILogService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog';
|
||||
import { FilePolicyService } from 'vs/platform/policy/common/filePolicyService';
|
||||
import { IPolicyService, NullPolicyService } from 'vs/platform/policy/common/policy';
|
||||
@ -62,6 +62,7 @@ import { IUserDataProfilesService, PROFILES_ENABLEMENT_CONFIG } from 'vs/platfor
|
||||
import { UserDataProfilesService } from 'vs/platform/userDataProfile/node/userDataProfile';
|
||||
import { resolveMachineId } from 'vs/platform/telemetry/node/telemetryUtils';
|
||||
import { ExtensionsProfileScannerService } from 'vs/platform/extensionManagement/node/extensionsProfileScannerService';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
|
||||
class CliMain extends Disposable {
|
||||
|
||||
@ -126,13 +127,13 @@ class CliMain extends Disposable {
|
||||
|
||||
// Log
|
||||
const logLevel = getLogLevel(environmentService);
|
||||
const loggers: ILogger[] = [];
|
||||
loggers.push(new SpdLogLogger('cli', join(environmentService.logsPath, 'cli.log'), true, false, logLevel));
|
||||
const spdLogLogger = new SpdLogLogger('cli', join(environmentService.logsPath, 'cli.log'), true, false, logLevel);
|
||||
const otherLoggers: ILogger[] = [];
|
||||
if (logLevel === LogLevel.Trace) {
|
||||
loggers.push(new ConsoleLogger(logLevel));
|
||||
otherLoggers.push(new ConsoleLogger(logLevel));
|
||||
}
|
||||
|
||||
const logService = this._register(new MultiplexLogService(loggers));
|
||||
const logService = this._register(new LogService(spdLogLogger, otherLoggers));
|
||||
services.set(ILogService, logService);
|
||||
|
||||
// Files
|
||||
|
||||
@ -49,7 +49,7 @@ import { StandaloneServicesNLS } from 'vs/editor/common/standaloneStrings';
|
||||
import { ClassifiedEvent, StrictPropertyCheck, OmitMetadata, IGDPRProperty } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { basename } from 'vs/base/common/resources';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { ConsoleLogger, ILogService, LogService } from 'vs/platform/log/common/log';
|
||||
import { ConsoleLogger, ILogService } from 'vs/platform/log/common/log';
|
||||
import { IWorkspaceTrustManagementService, IWorkspaceTrustTransitionParticipant, IWorkspaceTrustUriInfo } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
|
||||
@ -90,6 +90,7 @@ import 'vs/editor/common/services/languageFeaturesService';
|
||||
import { DefaultConfiguration } from 'vs/platform/configuration/common/configurations';
|
||||
import { WorkspaceEdit } from 'vs/editor/common/languages';
|
||||
import { AudioCue, IAudioCueService, Sound } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
|
||||
class SimpleModel implements IResolvedTextEditorModel {
|
||||
|
||||
|
||||
@ -20,11 +20,12 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
|
||||
import { EnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService';
|
||||
import { OPTIONS, parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { HotExitConfiguration } from 'vs/platform/files/common/files';
|
||||
import { ConsoleMainLogger, LogService } from 'vs/platform/log/common/log';
|
||||
import { ConsoleMainLogger } from 'vs/platform/log/common/log';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IFolderBackupInfo, isFolderBackupInfo, IWorkspaceBackupInfo } from 'vs/platform/backup/common/backup';
|
||||
import { IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { InMemoryTestStateMainService } from 'vs/platform/test/electron-main/workbenchTestServices';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
|
||||
flakySuite('BackupMainService', () => {
|
||||
|
||||
|
||||
@ -3,14 +3,14 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AbstractMessageLogger, DEFAULT_LOG_LEVEL, ILogger, ILogService, log, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { AbstractMessageLogger, DEFAULT_LOG_LEVEL, ILogger, log, LogLevel } from 'vs/platform/log/common/log';
|
||||
|
||||
interface ILog {
|
||||
level: LogLevel;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export class BufferLogService extends AbstractMessageLogger implements ILogService {
|
||||
export class BufferLogger extends AbstractMessageLogger {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
private buffer: ILog[] = [];
|
||||
|
||||
@ -8,8 +8,8 @@ import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { basename, dirname, joinPath } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ByteSize, FileOperationError, FileOperationResult, IFileService, whenProviderRegistered } from 'vs/platform/files/common/files';
|
||||
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
|
||||
import { AbstractLoggerService, AbstractMessageLogger, ILogger, ILoggerOptions, ILoggerService, ILogService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { BufferLogger } from 'vs/platform/log/common/bufferLog';
|
||||
import { AbstractLoggerService, AbstractMessageLogger, ILogger, ILoggerOptions, ILoggerService, LogLevel } from 'vs/platform/log/common/log';
|
||||
|
||||
const MAX_FILE_SIZE = 5 * ByteSize.MB;
|
||||
|
||||
@ -98,15 +98,15 @@ export class FileLogger extends AbstractMessageLogger implements ILogger {
|
||||
export class FileLoggerService extends AbstractLoggerService implements ILoggerService {
|
||||
|
||||
constructor(
|
||||
@ILogService logService: ILogService,
|
||||
logLevel: LogLevel,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
) {
|
||||
super(logService.getLevel(), logService.onDidChangeLogLevel);
|
||||
super(logLevel);
|
||||
}
|
||||
|
||||
protected doCreateLogger(resource: URI, logLevel: LogLevel, options?: ILoggerOptions): ILogger {
|
||||
const logger = new BufferLogService(logLevel);
|
||||
whenProviderRegistered(resource, this.fileService).then(() => (<BufferLogService>logger).logger = new FileLogger(resource, logger.getLevel(), !!options?.donotUseFormatters, this.fileService));
|
||||
const logger = new BufferLogger(logLevel);
|
||||
whenProviderRegistered(resource, this.fileService).then(() => logger.logger = new FileLogger(resource, logger.getLevel(), !!options?.donotUseFormatters, this.fileService));
|
||||
return logger;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +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 { Mutable, isNumber } 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';
|
||||
@ -20,6 +20,10 @@ function now(): string {
|
||||
return new Date().toISOString();
|
||||
}
|
||||
|
||||
export function isLogLevel(thing: unknown): thing is LogLevel {
|
||||
return isNumber(thing);
|
||||
}
|
||||
|
||||
export enum LogLevel {
|
||||
Off,
|
||||
Trace,
|
||||
@ -141,9 +145,9 @@ export interface ILoggerService {
|
||||
/**
|
||||
* Creates a logger, or gets one if it already exists.
|
||||
*
|
||||
* This will also register the logger with the logger service unless `donotRegister` is set to `true`.
|
||||
* This will also register the logger with the logger service.
|
||||
*/
|
||||
createLogger(resource: URI, options?: ILoggerOptions, donotRegister?: boolean): ILogger;
|
||||
createLogger(resource: URI, options?: ILoggerOptions): ILogger;
|
||||
|
||||
/**
|
||||
* Gets an existing logger, if any.
|
||||
@ -153,7 +157,12 @@ export interface ILoggerService {
|
||||
/**
|
||||
* An event which fires when the log level of a logger has changed
|
||||
*/
|
||||
readonly onDidChangeLogLevel: Event<[URI, LogLevel]>;
|
||||
readonly onDidChangeLogLevel: Event<LogLevel | [URI, LogLevel]>;
|
||||
|
||||
/**
|
||||
* Set default log level.
|
||||
*/
|
||||
setLogLevel(level: LogLevel): void;
|
||||
|
||||
/**
|
||||
* Set log level for a logger.
|
||||
@ -161,9 +170,9 @@ export interface ILoggerService {
|
||||
setLogLevel(resource: URI, level: LogLevel): void;
|
||||
|
||||
/**
|
||||
* Get log level for a logger.
|
||||
* Get log level for a logger or the default log level.
|
||||
*/
|
||||
getLogLevel(resource: URI): LogLevel | undefined;
|
||||
getLogLevel(resource?: URI): LogLevel;
|
||||
|
||||
/**
|
||||
* An event which fires when the visibility of a logger has changed
|
||||
@ -459,111 +468,65 @@ export class AdapterLogger extends AbstractLogger implements ILogger {
|
||||
}
|
||||
}
|
||||
|
||||
export class MultiplexLogService extends AbstractLogger implements ILogService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
export class MultiplexLogger extends AbstractLogger implements ILogger {
|
||||
|
||||
constructor(private readonly logServices: ReadonlyArray<ILogger>) {
|
||||
constructor(private readonly loggers: ReadonlyArray<ILogger>) {
|
||||
super();
|
||||
if (logServices.length) {
|
||||
this.setLevel(logServices[0].getLevel());
|
||||
if (loggers.length) {
|
||||
this.setLevel(loggers[0].getLevel());
|
||||
}
|
||||
}
|
||||
|
||||
override setLevel(level: LogLevel): void {
|
||||
for (const logService of this.logServices) {
|
||||
logService.setLevel(level);
|
||||
for (const logger of this.loggers) {
|
||||
logger.setLevel(level);
|
||||
}
|
||||
super.setLevel(level);
|
||||
}
|
||||
|
||||
trace(message: string, ...args: any[]): void {
|
||||
for (const logService of this.logServices) {
|
||||
logService.trace(message, ...args);
|
||||
for (const logger of this.loggers) {
|
||||
logger.trace(message, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
debug(message: string, ...args: any[]): void {
|
||||
for (const logService of this.logServices) {
|
||||
logService.debug(message, ...args);
|
||||
for (const logger of this.loggers) {
|
||||
logger.debug(message, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
info(message: string, ...args: any[]): void {
|
||||
for (const logService of this.logServices) {
|
||||
logService.info(message, ...args);
|
||||
for (const logger of this.loggers) {
|
||||
logger.info(message, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
warn(message: string, ...args: any[]): void {
|
||||
for (const logService of this.logServices) {
|
||||
logService.warn(message, ...args);
|
||||
for (const logger of this.loggers) {
|
||||
logger.warn(message, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
error(message: string | Error, ...args: any[]): void {
|
||||
for (const logService of this.logServices) {
|
||||
logService.error(message, ...args);
|
||||
for (const logger of this.loggers) {
|
||||
logger.error(message, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
flush(): void {
|
||||
for (const logService of this.logServices) {
|
||||
logService.flush();
|
||||
for (const logger of this.loggers) {
|
||||
logger.flush();
|
||||
}
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
for (const logService of this.logServices) {
|
||||
logService.dispose();
|
||||
for (const logger of this.loggers) {
|
||||
logger.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class LogService extends Disposable implements ILogService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
constructor(private logger: ILogger) {
|
||||
super();
|
||||
this._register(logger);
|
||||
}
|
||||
|
||||
get onDidChangeLogLevel(): Event<LogLevel> {
|
||||
return this.logger.onDidChangeLogLevel;
|
||||
}
|
||||
|
||||
setLevel(level: LogLevel): void {
|
||||
this.logger.setLevel(level);
|
||||
}
|
||||
|
||||
getLevel(): LogLevel {
|
||||
return this.logger.getLevel();
|
||||
}
|
||||
|
||||
trace(message: string, ...args: any[]): void {
|
||||
this.logger.trace(message, ...args);
|
||||
}
|
||||
|
||||
debug(message: string, ...args: any[]): void {
|
||||
this.logger.debug(message, ...args);
|
||||
}
|
||||
|
||||
info(message: string, ...args: any[]): void {
|
||||
this.logger.info(message, ...args);
|
||||
}
|
||||
|
||||
warn(message: string, ...args: any[]): void {
|
||||
this.logger.warn(message, ...args);
|
||||
}
|
||||
|
||||
error(message: string | Error, ...args: any[]): void {
|
||||
this.logger.error(message, ...args);
|
||||
}
|
||||
|
||||
flush(): void {
|
||||
this.logger.flush();
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractLoggerService extends Disposable implements ILoggerService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
@ -575,7 +538,7 @@ export abstract class AbstractLoggerService extends Disposable implements ILogge
|
||||
private _onDidChangeLoggers = this._register(new Emitter<{ added: ILoggerResource[]; removed: ILoggerResource[] }>);
|
||||
readonly onDidChangeLoggers = this._onDidChangeLoggers.event;
|
||||
|
||||
private _onDidChangeLogLevel = this._register(new Emitter<[URI, LogLevel]>);
|
||||
private _onDidChangeLogLevel = this._register(new Emitter<LogLevel | [URI, LogLevel]>);
|
||||
readonly onDidChangeLogLevel = this._onDidChangeLogLevel.event;
|
||||
|
||||
private _onDidChangeVisibility = this._register(new Emitter<[URI, boolean]>);
|
||||
@ -583,11 +546,9 @@ export abstract class AbstractLoggerService extends Disposable implements ILogge
|
||||
|
||||
constructor(
|
||||
protected logLevel: LogLevel,
|
||||
onDidChangeLogLevel: Event<LogLevel>,
|
||||
loggerResources?: Iterable<ILoggerResource>,
|
||||
) {
|
||||
super();
|
||||
this._register(onDidChangeLogLevel(logLevel => this.setGlobalLogLevel(logLevel)));
|
||||
if (loggerResources) {
|
||||
for (const loggerResource of loggerResources) {
|
||||
this._loggerResources.set(loggerResource.resource, loggerResource);
|
||||
@ -612,13 +573,27 @@ export abstract class AbstractLoggerService extends Disposable implements ILogge
|
||||
return logger;
|
||||
}
|
||||
|
||||
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([resource, logLevel]);
|
||||
setLogLevel(logLevel: LogLevel): void;
|
||||
setLogLevel(resource: URI, logLevel: LogLevel): void;
|
||||
setLogLevel(arg1: any, arg2?: any): void {
|
||||
if (URI.isUri(arg1)) {
|
||||
const resource = arg1;
|
||||
const logLevel = arg2;
|
||||
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([resource, logLevel]);
|
||||
}
|
||||
} else {
|
||||
this.logLevel = arg1;
|
||||
for (const [resource, logger] of this._loggers.entries()) {
|
||||
if (this._loggerResources.get(resource)?.logLevel === undefined) {
|
||||
logger.setLevel(this.logLevel);
|
||||
}
|
||||
}
|
||||
this._onDidChangeLogLevel.fire(this.logLevel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -631,22 +606,21 @@ export abstract class AbstractLoggerService extends Disposable implements ILogge
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
let logLevel;
|
||||
if (resource) {
|
||||
logLevel = this._loggerResources.get(resource)?.logLevel;
|
||||
}
|
||||
}
|
||||
|
||||
getLogLevel(resource: URI): LogLevel | undefined {
|
||||
return this._loggerResources.get(resource)?.logLevel;
|
||||
return logLevel ?? this.logLevel;
|
||||
}
|
||||
|
||||
registerLogger(resource: ILoggerResource): void {
|
||||
const existing = this._loggerResources.get(resource.resource);
|
||||
if (!existing) {
|
||||
if (existing) {
|
||||
if (existing.hidden !== resource.hidden) {
|
||||
this.setVisibility(resource.resource, !resource.hidden);
|
||||
}
|
||||
} else {
|
||||
this._loggerResources.set(resource.resource, resource);
|
||||
this._onDidChangeLoggers.fire({ added: [resource], removed: [] });
|
||||
}
|
||||
@ -703,7 +677,7 @@ export class NullLogService extends NullLogger implements ILogService {
|
||||
|
||||
export class NullLoggerService extends AbstractLoggerService {
|
||||
|
||||
constructor() { super(LogLevel.Info, Event.None); }
|
||||
constructor() { super(LogLevel.Info); }
|
||||
|
||||
protected doCreateLogger(resource: URI, logLevel: LogLevel, options?: ILoggerOptions | undefined): ILogger {
|
||||
return new NullLogger();
|
||||
@ -753,3 +727,11 @@ export function parseLogLevel(logLevel: string): LogLevel | undefined {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function setLogLevel(loggerService: ILoggerService, logLevel: LogLevel | [URI, LogLevel]): void {
|
||||
if (isLogLevel(logLevel)) {
|
||||
loggerService.setLogLevel(logLevel);
|
||||
} else {
|
||||
loggerService.setLogLevel(logLevel[0], logLevel[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,63 +3,23 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { URI, UriDto } from 'vs/base/common/uri';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { AbstractLoggerService, AbstractMessageLogger, AdapterLogger, DidChangeLoggersEvent, ILogger, ILoggerOptions, ILoggerResource, ILoggerService, ILogService, LogLevel, LogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class LogLevelChannel implements IServerChannel {
|
||||
|
||||
onDidChangeLogLevel: Event<LogLevel>;
|
||||
|
||||
constructor(
|
||||
private readonly logService: ILogService,
|
||||
private readonly loggerService: ILoggerService
|
||||
) {
|
||||
this.onDidChangeLogLevel = Event.buffer(logService.onDidChangeLogLevel, true);
|
||||
}
|
||||
|
||||
listen(_: unknown, event: string): Event<any> {
|
||||
switch (event) {
|
||||
case 'onDidChangeLogLevel': return this.onDidChangeLogLevel;
|
||||
}
|
||||
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
}
|
||||
|
||||
async call(_: unknown, command: string, arg?: any): Promise<any> {
|
||||
switch (command) {
|
||||
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}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class LogLevelChannelClient {
|
||||
|
||||
constructor(private channel: IChannel) { }
|
||||
|
||||
get onDidChangeLogLevel(): Event<LogLevel> {
|
||||
return this.channel.listen('onDidChangeLogLevel');
|
||||
}
|
||||
|
||||
setLevel(level: LogLevel, resource?: URI): void {
|
||||
LogLevelChannelClient.setLevel(this.channel, level, resource);
|
||||
}
|
||||
|
||||
public static setLevel(channel: IChannel, level: LogLevel, resource?: URI): Promise<void> {
|
||||
return channel.call('setLevel', [level, resource]);
|
||||
}
|
||||
|
||||
}
|
||||
import { AbstractLoggerService, AbstractMessageLogger, AdapterLogger, DidChangeLoggersEvent, ILogger, ILoggerOptions, ILoggerResource, ILoggerService, isLogLevel, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export class LoggerChannelClient extends AbstractLoggerService implements ILoggerService {
|
||||
|
||||
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<[URI, LogLevel]>('onDidChangeLogLevel', windowId)(([resource, logLevel]) => super.setLogLevel(URI.revive(resource), logLevel)));
|
||||
constructor(private readonly windowId: number | undefined, logLevel: LogLevel, loggers: UriDto<ILoggerResource>[], private readonly channel: IChannel) {
|
||||
super(logLevel, loggers.map(loggerResource => ({ ...loggerResource, resource: URI.revive(loggerResource.resource), hidden: loggerResource.hidden || !!loggerResource.extensionId })));
|
||||
this._register(channel.listen<LogLevel | [URI, LogLevel]>('onDidChangeLogLevel', windowId)(arg => {
|
||||
if (isLogLevel(arg)) {
|
||||
super.setLogLevel(arg);
|
||||
} else {
|
||||
super.setLogLevel(URI.revive(arg[0]), arg[1]);
|
||||
}
|
||||
}));
|
||||
this._register(channel.listen<[URI, boolean]>('onDidChangeVisibility', windowId)(([resource, visibility]) => super.setVisibility(URI.revive(resource), visibility)));
|
||||
this._register(channel.listen<DidChangeLoggersEvent>('onDidChangeLoggers', windowId)(({ added, removed }) => {
|
||||
for (const loggerResource of added) {
|
||||
@ -89,9 +49,11 @@ export class LoggerChannelClient extends AbstractLoggerService implements ILogge
|
||||
this.channel.call('deregisterLogger', [resource, this.windowId]);
|
||||
}
|
||||
|
||||
override setLogLevel(resource: URI, logLevel: LogLevel): void {
|
||||
super.setLogLevel(resource, logLevel);
|
||||
this.channel.call('setLogLevel', [resource, logLevel]);
|
||||
override setLogLevel(logLevel: LogLevel): void;
|
||||
override setLogLevel(resource: URI, logLevel: LogLevel): void;
|
||||
override setLogLevel(arg1: any, arg2?: any): void {
|
||||
super.setLogLevel(arg1, arg2);
|
||||
this.channel.call('setLogLevel', [arg1, arg2]);
|
||||
}
|
||||
|
||||
override setVisibility(resource: URI, visibility: boolean): void {
|
||||
@ -103,6 +65,12 @@ export class LoggerChannelClient extends AbstractLoggerService implements ILogge
|
||||
return new Logger(this.channel, file, logLevel, options);
|
||||
}
|
||||
|
||||
public static setLogLevel(channel: IChannel, level: LogLevel): Promise<void>;
|
||||
public static setLogLevel(channel: IChannel, resource: URI, level: LogLevel): Promise<void>;
|
||||
public static setLogLevel(channel: IChannel, arg1: any, arg2?: any): Promise<void> {
|
||||
return channel.call('setLogLevel', [arg1, arg2]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Logger extends AbstractMessageLogger {
|
||||
@ -139,16 +107,54 @@ class Logger extends AbstractMessageLogger {
|
||||
}
|
||||
}
|
||||
|
||||
export class FollowerLogService extends LogService implements ILogService {
|
||||
export class LoggerChannel implements IServerChannel {
|
||||
|
||||
constructor(private parent: LogLevelChannelClient, logService: ILogService) {
|
||||
super(logService);
|
||||
this._register(parent.onDidChangeLogLevel(level => logService.setLevel(level)));
|
||||
constructor(private readonly loggerService: ILoggerService) { }
|
||||
|
||||
listen(_: unknown, event: string, windowId?: number): Event<any> {
|
||||
switch (event) {
|
||||
case 'onDidChangeLoggers': return this.loggerService.onDidChangeLoggers;
|
||||
case 'onDidChangeVisibility': return this.loggerService.onDidChangeVisibility;
|
||||
case 'onDidChangeLogLevel': return this.loggerService.onDidChangeLogLevel;
|
||||
}
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
}
|
||||
|
||||
override setLevel(level: LogLevel): void {
|
||||
super.setLevel(level);
|
||||
async call(_: unknown, command: string, arg?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'setLogLevel': return isLogLevel(arg[0]) ? this.loggerService.setLogLevel(arg[0]) : this.loggerService.setLogLevel(URI.revive(arg[0]), arg[1]);
|
||||
case 'getRegisteredLoggers': return Promise.resolve([...this.loggerService.getRegisteredLoggers()]);
|
||||
}
|
||||
|
||||
throw new Error(`Call not found: ${command}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class RemoteLoggerChannelClient extends Disposable {
|
||||
|
||||
constructor(loggerService: ILoggerService, channel: IChannel) {
|
||||
super();
|
||||
|
||||
channel.call('setLogLevel', [loggerService.getLogLevel()]);
|
||||
this._register(loggerService.onDidChangeLogLevel(arg => channel.call('setLogLevel', [arg])));
|
||||
|
||||
channel.call<ILoggerResource[]>('getRegisteredLoggers').then(loggers => {
|
||||
for (const loggerResource of loggers) {
|
||||
loggerService.registerLogger({ ...loggerResource, resource: URI.revive(loggerResource.resource) });
|
||||
}
|
||||
});
|
||||
|
||||
this._register(channel.listen<[URI, boolean]>('onDidChangeVisibility')(([resource, visibility]) => loggerService.setVisibility(URI.revive(resource), visibility)));
|
||||
|
||||
this._register(channel.listen<DidChangeLoggersEvent>('onDidChangeLoggers')(({ added, removed }) => {
|
||||
for (const loggerResource of added) {
|
||||
loggerService.registerLogger({ ...loggerResource, resource: URI.revive(loggerResource.resource) });
|
||||
}
|
||||
for (const loggerResource of removed) {
|
||||
loggerService.deregisterLogger(loggerResource.resource);
|
||||
}
|
||||
}));
|
||||
|
||||
this.parent.setLevel(level);
|
||||
}
|
||||
}
|
||||
|
||||
57
src/vs/platform/log/common/logService.ts
Normal file
57
src/vs/platform/log/common/logService.ts
Normal file
@ -0,0 +1,57 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ILogger, ILogService, LogLevel, MultiplexLogger } from 'vs/platform/log/common/log';
|
||||
|
||||
export class LogService extends Disposable implements ILogService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly logger: ILogger;
|
||||
|
||||
constructor(primaryLogger: ILogger, otherLoggers: ILogger[] = []) {
|
||||
super();
|
||||
this.logger = new MultiplexLogger([primaryLogger, ...otherLoggers]);
|
||||
this._register(primaryLogger.onDidChangeLogLevel(level => this.setLevel(level)));
|
||||
}
|
||||
|
||||
get onDidChangeLogLevel(): Event<LogLevel> {
|
||||
return this.logger.onDidChangeLogLevel;
|
||||
}
|
||||
|
||||
setLevel(level: LogLevel): void {
|
||||
this.logger.setLevel(level);
|
||||
}
|
||||
|
||||
getLevel(): LogLevel {
|
||||
return this.logger.getLevel();
|
||||
}
|
||||
|
||||
trace(message: string, ...args: any[]): void {
|
||||
this.logger.trace(message, ...args);
|
||||
}
|
||||
|
||||
debug(message: string, ...args: any[]): void {
|
||||
this.logger.debug(message, ...args);
|
||||
}
|
||||
|
||||
info(message: string, ...args: any[]): void {
|
||||
this.logger.info(message, ...args);
|
||||
}
|
||||
|
||||
warn(message: string, ...args: any[]): void {
|
||||
this.logger.warn(message, ...args);
|
||||
}
|
||||
|
||||
error(message: string | Error, ...args: any[]): void {
|
||||
this.logger.error(message, ...args);
|
||||
}
|
||||
|
||||
flush(): void {
|
||||
this.logger.flush();
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,7 @@ export class LoggerChannel implements IServerChannel {
|
||||
|
||||
async call(_: unknown, command: string, arg?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'createLogger': this.createLogger(URI.revive(arg[0]), arg[1], arg[2]); return;
|
||||
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]);
|
||||
@ -38,8 +38,8 @@ export class LoggerChannel implements IServerChannel {
|
||||
throw new Error(`Call not found: ${command}`);
|
||||
}
|
||||
|
||||
private createLogger(file: URI, options: ILoggerOptions, donotRegister?: boolean): void {
|
||||
this.loggers.set(file.toString(), this.loggerService.createLogger(file, options, donotRegister));
|
||||
private createLogger(file: URI, options: ILoggerOptions): void {
|
||||
this.loggers.set(file.toString(), this.loggerService.createLogger(file, options));
|
||||
}
|
||||
|
||||
private consoleLog(level: LogLevel, args: any[]): void {
|
||||
|
||||
@ -7,14 +7,14 @@ 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 { DidChangeLoggersEvent, ILoggerResource, ILoggerService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { DidChangeLoggersEvent, ILoggerResource, ILoggerService, LogLevel, isLogLevel } 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<[URI, LogLevel]>;
|
||||
getOnDidChangeLogLevelEvent(windowId: number): Event<LogLevel | [URI, LogLevel]>;
|
||||
|
||||
getOnDidChangeVisibilityEvent(windowId: number): Event<[URI, boolean]>;
|
||||
|
||||
@ -54,8 +54,8 @@ export class LoggerMainService extends LoggerService implements ILoggerMainServi
|
||||
return resources;
|
||||
}
|
||||
|
||||
getOnDidChangeLogLevelEvent(windowId: number): Event<[URI, LogLevel]> {
|
||||
return Event.filter(this.onDidChangeLogLevel, ([resource]) => this.isInterestedLoggerResource(resource, windowId));
|
||||
getOnDidChangeLogLevelEvent(windowId: number): Event<LogLevel | [URI, LogLevel]> {
|
||||
return Event.filter(this.onDidChangeLogLevel, arg => isLogLevel(arg) || this.isInterestedLoggerResource(arg[0], windowId));
|
||||
}
|
||||
|
||||
getOnDidChangeVisibilityEvent(windowId: number): Event<[URI, boolean]> {
|
||||
|
||||
@ -5,19 +5,12 @@
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { AbstractLoggerService, ILogger, ILoggerOptions, ILoggerService, ILogService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { AbstractLoggerService, ILogger, ILoggerOptions, ILoggerService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog';
|
||||
|
||||
export class LoggerService extends AbstractLoggerService implements ILoggerService {
|
||||
|
||||
constructor(
|
||||
@ILogService logService: ILogService
|
||||
) {
|
||||
super(logService.getLevel(), logService.onDidChangeLogLevel);
|
||||
}
|
||||
|
||||
protected doCreateLogger(resource: URI, logLevel: LogLevel, options?: ILoggerOptions): ILogger {
|
||||
return new SpdLogLogger(options?.name || generateUuid(), resource.fsPath, !options?.donotRotate, !!options?.donotUseFormatters, logLevel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -76,7 +76,7 @@ export class TestTelemetryLoggerService implements ILoggerService {
|
||||
onDidChangeLogLevel = Event.None;
|
||||
onDidChangeLoggers = Event.None;
|
||||
setLogLevel(): void { }
|
||||
getLogLevel() { return undefined; }
|
||||
getLogLevel() { return LogLevel.Info; }
|
||||
setVisibility(): void { }
|
||||
getDefaultLogLevel() { return this.logLevel; }
|
||||
registerLogger() { }
|
||||
|
||||
@ -209,7 +209,7 @@ export enum TerminalIpcChannels {
|
||||
/**
|
||||
* Deals with logging from the pty host process.
|
||||
*/
|
||||
Log = 'log',
|
||||
Logger = 'logger',
|
||||
/**
|
||||
* Enables the detection of unresponsive pty hosts.
|
||||
*/
|
||||
|
||||
@ -7,11 +7,12 @@ import { join } from 'vs/base/common/path';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { Server } from 'vs/base/parts/ipc/node/ipc.cp';
|
||||
import { localize } from 'vs/nls';
|
||||
import { OPTIONS, parseArgs } from 'vs/platform/environment/node/argv';
|
||||
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
|
||||
import { ConsoleLogger, LogService, MultiplexLogService } from 'vs/platform/log/common/log';
|
||||
import { LogLevelChannel } from 'vs/platform/log/common/logIpc';
|
||||
import { ConsoleLogger, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { LoggerChannel } from 'vs/platform/log/common/logIpc';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
@ -24,18 +25,15 @@ const server = new Server('ptyHost');
|
||||
const lastPtyId = parseInt(process.env.VSCODE_LAST_PTY_ID || '0');
|
||||
delete process.env.VSCODE_LAST_PTY_ID;
|
||||
|
||||
// Logging
|
||||
const productService: IProductService = { _serviceBrand: undefined, ...product };
|
||||
const environmentService = new NativeEnvironmentService(parseArgs(process.argv, OPTIONS), productService);
|
||||
const bufferLogService = new BufferLogService();
|
||||
const logService = new LogService(new MultiplexLogService([
|
||||
new ConsoleLogger(),
|
||||
bufferLogService
|
||||
]));
|
||||
const loggerService = new LoggerService(logService);
|
||||
bufferLogService.logger = loggerService.createLogger(URI.file(join(environmentService.logsPath, `${TerminalLogConstants.FileName}.log`)), { name: TerminalLogConstants.FileName });
|
||||
const logLevelChannel = new LogLevelChannel(logService, loggerService);
|
||||
server.registerChannel(TerminalIpcChannels.Log, logLevelChannel);
|
||||
|
||||
// Logging
|
||||
const loggerService = new LoggerService(LogLevel.Info);
|
||||
server.registerChannel(TerminalIpcChannels.Logger, new LoggerChannel(loggerService));
|
||||
const logger = loggerService.createLogger(URI.file(join(environmentService.logsPath, `${TerminalLogConstants.FileName}.log`)), { name: process.env.VSCODE_PTY_LOG_NAME ?? localize('ptyHost', "Pty Host") });
|
||||
delete process.env.VSCODE_PTY_LOG_NAME;
|
||||
const logService = new LogService(logger, [new ConsoleLogger()]);
|
||||
|
||||
const heartbeatService = new HeartbeatService();
|
||||
server.registerChannel(TerminalIpcChannels.Heartbeat, ProxyChannel.fromService(heartbeatService));
|
||||
|
||||
@ -14,17 +14,13 @@ import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/envi
|
||||
import { parsePtyHostPort } from 'vs/platform/environment/common/environmentService';
|
||||
import { getResolvedShellEnv } from 'vs/platform/shell/node/shellEnv';
|
||||
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, TerminalLogConstants } 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 } 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';
|
||||
import { RemoteLoggerChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
|
||||
enum Constants {
|
||||
MaxRestarts = 5
|
||||
@ -83,11 +79,11 @@ export class PtyHostService extends Disposable implements IPtyService {
|
||||
|
||||
constructor(
|
||||
private readonly _reconnectConstants: IReconnectConstants,
|
||||
private readonly loggerName: string,
|
||||
@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();
|
||||
|
||||
@ -143,6 +139,7 @@ export class PtyHostService extends Disposable implements IPtyService {
|
||||
args: ['--type=ptyHost', '--logsPath', this._environmentService.logsPath],
|
||||
env: {
|
||||
VSCODE_LAST_PTY_ID: lastPtyId,
|
||||
VSCODE_PTY_LOG_NAME: this.loggerName,
|
||||
VSCODE_AMD_ENTRYPOINT: 'vs/platform/terminal/node/ptyHostMain',
|
||||
VSCODE_PIPE_LOGGING: 'true',
|
||||
VSCODE_VERBOSE_LOGGING: 'true', // transmit console logs from server to client,
|
||||
@ -184,18 +181,7 @@ 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.registerLogger({ 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._register(new RemoteLoggerChannelClient(this._loggerService, client.getChannel(TerminalIpcChannels.Logger)));
|
||||
|
||||
// Create proxy and forward events
|
||||
const proxy = ProxyChannel.toService<IPtyService>(client.getChannel(TerminalIpcChannels.PtyHost));
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
|
||||
import { fail, strictEqual } from 'assert';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ConsoleLogger, ILogService, LogService } from 'vs/platform/log/common/log';
|
||||
import { ConsoleLogger, ILogService } from 'vs/platform/log/common/log';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
import { RequestStore } from 'vs/platform/terminal/common/requestStore';
|
||||
|
||||
suite('RequestStore', () => {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { getLogLevel, ILogService, LogService } from 'vs/platform/log/common/log';
|
||||
import { getLogLevel, ILogService } from 'vs/platform/log/common/log';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@ -48,6 +48,7 @@ import { IExtensionsProfileScannerService } from 'vs/platform/extensionManagemen
|
||||
import { NullPolicyService } from 'vs/platform/policy/common/policy';
|
||||
import { ServerUserDataProfilesService } from 'vs/platform/userDataProfile/node/userDataProfile';
|
||||
import { ExtensionsProfileScannerService } from 'vs/platform/extensionManagement/node/extensionsProfileScannerService';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
|
||||
class CliMain extends Disposable {
|
||||
|
||||
@ -84,7 +85,7 @@ class CliMain extends Disposable {
|
||||
|
||||
const environmentService = new ServerEnvironmentService(this.args, productService);
|
||||
services.set(IServerEnvironmentService, environmentService);
|
||||
const logService: ILogService = new LogService(new SpdLogLogger(RemoteExtensionLogFileName, join(environmentService.logsPath, `${RemoteExtensionLogFileName}.log`), true, false, getLogLevel(environmentService)));
|
||||
const logService = new LogService(new SpdLogLogger(RemoteExtensionLogFileName, join(environmentService.logsPath, `${RemoteExtensionLogFileName}.log`), true, false, getLogLevel(environmentService)));
|
||||
services.set(ILogService, logService);
|
||||
logService.trace(`Remote configuration data at ${this.remoteDataFolder}`);
|
||||
logService.trace('process arguments:', this.args);
|
||||
|
||||
@ -38,8 +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, ILoggerService, ILogService, LogLevel, MultiplexLogService } from 'vs/platform/log/common/log';
|
||||
import { LogLevelChannel } from 'vs/platform/log/common/logIpc';
|
||||
import { AbstractLogger, DEFAULT_LOG_LEVEL, getLogLevel, ILoggerService, ILogService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment';
|
||||
@ -75,9 +74,11 @@ import { NullPolicyService } from 'vs/platform/policy/common/policy';
|
||||
import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
|
||||
import { ServerUserDataProfilesService } from 'vs/platform/userDataProfile/node/userDataProfile';
|
||||
import { ExtensionsProfileScannerService } from 'vs/platform/extensionManagement/node/extensionsProfileScannerService';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
import { LoggerChannel } from 'vs/platform/log/common/logIpc';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
const eventPrefix = 'monacoworkbench';
|
||||
|
||||
@ -92,16 +93,15 @@ export async function setupServerServices(connectionToken: ServerConnectionToken
|
||||
services.set(IEnvironmentService, environmentService);
|
||||
services.set(INativeEnvironmentService, environmentService);
|
||||
|
||||
const bufferLogService = new BufferLogService();
|
||||
const logService = new MultiplexLogService([new ServerLogService(getLogLevel(environmentService)), bufferLogService]);
|
||||
const loggerService = new LoggerService(getLogLevel(environmentService));
|
||||
services.set(ILoggerService, loggerService);
|
||||
socketServer.registerChannel('logger', new LoggerChannel(loggerService));
|
||||
|
||||
const logger = loggerService.createLogger(URI.file(path.join(environmentService.logsPath, `${RemoteExtensionLogFileName}.log`)), { id: 'remoteServerLog', name: localize('remoteExtensionLog', "Remote Server") });
|
||||
const logService = new LogService(logger, [new ServerLogger(getLogLevel(environmentService))]);
|
||||
services.set(ILogService, logService);
|
||||
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}`);
|
||||
logService.trace('process arguments:', environmentService.args);
|
||||
if (Array.isArray(productService.serverGreeting)) {
|
||||
@ -113,7 +113,6 @@ export async function setupServerServices(connectionToken: ServerConnectionToken
|
||||
|
||||
// TODO: @Sandy @Joao need dynamic context based router
|
||||
const router = new StaticRouter<RemoteAgentConnectionContext>(ctx => ctx.clientId === 'renderer');
|
||||
socketServer.registerChannel('logger', new LogLevelChannel(logService, loggerService));
|
||||
|
||||
// Files
|
||||
const fileService = disposables.add(new FileService(logService));
|
||||
@ -189,7 +188,8 @@ export async function setupServerServices(connectionToken: ServerConnectionToken
|
||||
graceTime: ProtocolConstants.ReconnectionGraceTime,
|
||||
shortGraceTime: ProtocolConstants.ReconnectionShortGraceTime,
|
||||
scrollback: configurationService.getValue<number>(TerminalSettingId.PersistentSessionScrollback) ?? 100
|
||||
}
|
||||
},
|
||||
localize('ptyHost', "Remote Pty Host")
|
||||
);
|
||||
services.set(IPtyService, ptyService);
|
||||
|
||||
@ -259,8 +259,7 @@ export class SocketServer<TContext = string> extends IPCServer<TContext> {
|
||||
}
|
||||
}
|
||||
|
||||
class ServerLogService extends AbstractLogger implements ILogService {
|
||||
_serviceBrand: undefined;
|
||||
class ServerLogger extends AbstractLogger {
|
||||
private useColors: boolean;
|
||||
|
||||
constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
|
||||
|
||||
@ -4,14 +4,13 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
||||
import { ILoggerOptions, ILoggerService, ILogService, log, LogLevel, LogLevelToString, parseLogLevel } from 'vs/platform/log/common/log';
|
||||
import { ILoggerOptions, ILoggerResource, ILoggerService, ILogService, isLogLevel, log, LogLevel, LogLevelToString, parseLogLevel } from 'vs/platform/log/common/log';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostContext, MainThreadLoggerShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { UriComponents, URI } from 'vs/base/common/uri';
|
||||
import { UriComponents, URI, UriDto } 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 { IOutputService } from 'vs/workbench/services/output/common/output';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadLogger)
|
||||
export class MainThreadLoggerService implements MainThreadLoggerShape {
|
||||
@ -20,13 +19,16 @@ export class MainThreadLoggerService implements MainThreadLoggerShape {
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@ILogService logService: ILogService,
|
||||
@ILoggerService private readonly loggerService: ILoggerService,
|
||||
@IOutputService outputService: IOutputService,
|
||||
) {
|
||||
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostLogLevelServiceShape);
|
||||
this.disposables.add(logService.onDidChangeLogLevel(level => proxy.$setLevel(level)));
|
||||
this.disposables.add(loggerService.onDidChangeLogLevel(([resource, logLevel]) => proxy.$setLevel(logLevel, resource)));
|
||||
this.disposables.add(loggerService.onDidChangeLogLevel(arg => {
|
||||
if (isLogLevel(arg)) {
|
||||
proxy.$setLogLevel(arg);
|
||||
} else {
|
||||
proxy.$setLogLevel(arg[1], arg[0]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
$log(file: UriComponents, messages: [LogLevel, string][]): void {
|
||||
@ -40,7 +42,18 @@ export class MainThreadLoggerService implements MainThreadLoggerShape {
|
||||
}
|
||||
|
||||
async $createLogger(file: UriComponents, options?: ILoggerOptions): Promise<void> {
|
||||
this.loggerService.createLogger(URI.revive(file), options, true /* do not register the loggers from the extension host */);
|
||||
this.loggerService.createLogger(URI.revive(file), options);
|
||||
}
|
||||
|
||||
async $registerLogger(logResource: UriDto<ILoggerResource>): Promise<void> {
|
||||
this.loggerService.registerLogger({
|
||||
...logResource,
|
||||
resource: URI.revive(logResource.resource)
|
||||
});
|
||||
}
|
||||
|
||||
async $deregisterLogger(resource: UriComponents): Promise<void> {
|
||||
this.loggerService.deregisterLogger(URI.revive(resource));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
@ -51,13 +64,13 @@ export class MainThreadLoggerService implements MainThreadLoggerShape {
|
||||
// --- Internal commands to improve extension test runs
|
||||
|
||||
CommandsRegistry.registerCommand('_extensionTests.setLogLevel', function (accessor: ServicesAccessor, level: string) {
|
||||
const logService = accessor.get(ILogService);
|
||||
const loggerService = accessor.get(ILoggerService);
|
||||
const environmentService = accessor.get(IEnvironmentService);
|
||||
|
||||
if (environmentService.isExtensionDevelopment && !!environmentService.extensionTestsLocationURI) {
|
||||
const logLevel = parseLogLevel(level);
|
||||
if (logLevel !== undefined) {
|
||||
logService.setLevel(logLevel);
|
||||
loggerService.setLogLevel(logLevel);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -12,7 +12,6 @@ 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 {
|
||||
@ -22,18 +21,15 @@ 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,
|
||||
@ILoggerService loggerService: ILoggerService,
|
||||
) {
|
||||
super();
|
||||
this._outputService = outputService;
|
||||
this._viewsService = viewsService;
|
||||
this._loggerService = loggerService;
|
||||
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostOutputService);
|
||||
|
||||
@ -45,17 +41,13 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
|
||||
setVisibleChannel();
|
||||
}
|
||||
|
||||
public async $register(label: string, file: UriComponents, log: boolean, languageId: string | undefined, extensionId: string): Promise<string> {
|
||||
public async $register(label: string, file: UriComponents, languageId: string | undefined, extensionId: string): Promise<string> {
|
||||
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);
|
||||
|
||||
if (log) {
|
||||
this._loggerService.registerLogger({ resource, id, name: label, extensionId });
|
||||
} else {
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id, label, file: resource, log, languageId, extensionId });
|
||||
}
|
||||
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id, label, file: resource, log: false, languageId, extensionId });
|
||||
this._register(toDisposable(() => this.$dispose(id)));
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ import { IExtensionIdWithVersion } from 'vs/platform/extensionManagement/common/
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
|
||||
import { ILoggerOptions, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { ILoggerOptions, ILoggerResource, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
|
||||
import * as quickInput from 'vs/platform/quickinput/common/quickInput';
|
||||
@ -427,7 +427,7 @@ export interface MainThreadMessageServiceShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadOutputServiceShape extends IDisposable {
|
||||
$register(label: string, file: UriComponents, log: boolean, languageId: string | undefined, extensionId: string): Promise<string>;
|
||||
$register(label: string, file: UriComponents, languageId: string | undefined, extensionId: string): Promise<string>;
|
||||
$update(channelId: string, mode: OutputChannelUpdateMode, till?: number): Promise<void>;
|
||||
$reveal(channelId: string, preserveFocus: boolean): Promise<void>;
|
||||
$close(channelId: string): Promise<void>;
|
||||
@ -1988,12 +1988,14 @@ export interface ExtHostWindowShape {
|
||||
}
|
||||
|
||||
export interface ExtHostLogLevelServiceShape {
|
||||
$setLevel(level: LogLevel, resource?: UriComponents): void;
|
||||
$setLogLevel(level: LogLevel, resource?: UriComponents): void;
|
||||
}
|
||||
|
||||
export interface MainThreadLoggerShape {
|
||||
$log(file: UriComponents, messages: [LogLevel, string][]): void;
|
||||
$createLogger(file: UriComponents, options?: ILoggerOptions): Promise<void>;
|
||||
$registerLogger(logger: UriDto<ILoggerResource>): Promise<void>;
|
||||
$deregisterLogger(resource: UriComponents): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ExtHostOutputServiceShape {
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ILoggerService, LogService } from 'vs/platform/log/common/log';
|
||||
import { ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { ExtensionHostLogFileName } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
export class ExtHostLogService extends LogService {
|
||||
|
||||
@ -15,7 +15,7 @@ export class ExtHostLogService extends LogService {
|
||||
@ILoggerService loggerService: ILoggerService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
) {
|
||||
super(loggerService.createLogger(initData.logFile, { name: ExtensionHostLogFileName }));
|
||||
super(loggerService.createLogger(initData.logFile, { name: initData.logName }));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -8,28 +8,26 @@ import { MainThreadLoggerShape, MainContext, ExtHostLogLevelServiceShape as ExtH
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
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 {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
private readonly _proxy: MainThreadLoggerShape;
|
||||
protected readonly _proxy: MainThreadLoggerShape;
|
||||
|
||||
constructor(
|
||||
@IExtHostRpcService rpc: IExtHostRpcService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
) {
|
||||
super(initData.logLevel, Event.None, initData.loggers.map(logger => revive(logger)));
|
||||
super(initData.logLevel, initData.loggers.map(logger => revive(logger)));
|
||||
this._proxy = rpc.getProxy(MainContext.MainThreadLogger);
|
||||
}
|
||||
|
||||
$setLevel(level: LogLevel, resource?: UriComponents): void {
|
||||
$setLogLevel(logLevel: LogLevel, resource?: UriComponents): void {
|
||||
if (resource) {
|
||||
this.setLogLevel(URI.revive(resource), level);
|
||||
} else if (!isUndefined(level)) {
|
||||
this.setGlobalLogLevel(level);
|
||||
this.setLogLevel(URI.revive(resource), logLevel);
|
||||
} else {
|
||||
this.setLogLevel(logLevel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -167,16 +167,16 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
|
||||
}
|
||||
const outputDir = await this.outputDirectoryPromise;
|
||||
const file = this.extHostFileSystemInfo.extUri.joinPath(outputDir, `${this.namePool++}-${name.replace(/[\\/:\*\?"<>\|]/g, '')}.log`);
|
||||
const logger = this.loggerService.createLogger(file, { logLevel: 'always', donotRotate: true, donotUseFormatters: true });
|
||||
const id = await this.proxy.$register(name, file, false, languageId, extension.identifier.value);
|
||||
const logger = this.loggerService.createLogger(file, { logLevel: 'always', donotRotate: true, donotUseFormatters: true, hidden: true });
|
||||
const id = await this.proxy.$register(name, file, languageId, extension.identifier.value);
|
||||
return new ExtHostOutputChannel(id, name, logger, this.proxy, extension);
|
||||
}
|
||||
|
||||
private async doCreateLogOutputChannel(name: string, logLevel: LogLevel | undefined, extension: IExtensionDescription): Promise<ExtHostLogOutputChannel> {
|
||||
const extensionLogDir = await this.createExtensionLogDirectory(extension);
|
||||
const file = this.extHostFileSystemInfo.extUri.joinPath(extensionLogDir, `${name.replace(/[\\/:\*\?"<>\|]/g, '')}.log`);
|
||||
const logger = this.loggerService.createLogger(file, { name, logLevel });
|
||||
const id = await this.proxy.$register(name, file, true, undefined, extension.identifier.value);
|
||||
const id = file.toString();
|
||||
const logger = this.loggerService.createLogger(file, { id, name, logLevel, extensionId: extension.identifier.value });
|
||||
return new ExtHostLogOutputChannel(id, name, logger, this.proxy, extension);
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ export class ExtHostTelemetry implements ExtHostTelemetryShape {
|
||||
@IExtHostInitDataService private readonly initData: IExtHostInitDataService,
|
||||
@ILoggerService loggerService: ILoggerService,
|
||||
) {
|
||||
this._outputLogger = loggerService.createLogger(URI.revive(this.initData.environment.extensionTelemetryLogResource));
|
||||
this._outputLogger = loggerService.createLogger(URI.revive(this.initData.environment.extensionTelemetryLogResource), { hidden: true });
|
||||
this._outputLogger.info('Below are logs for extension telemetry events sent to the telemetry output channel API once the log level is set to trace.');
|
||||
this._outputLogger.info('===========================================================');
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ILogger, ILoggerOptions, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { ILogger, ILoggerOptions, ILoggerResource, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtHostLoggerService as BaseExtHostLoggerService } from 'vs/workbench/api/common/extHostLoggerService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
@ -20,4 +20,14 @@ export class ExtHostLoggerService extends BaseExtHostLoggerService {
|
||||
return super.doCreateLogger(resource, logLevel, options);
|
||||
}
|
||||
|
||||
override registerLogger(resource: ILoggerResource): void {
|
||||
super.registerLogger(resource);
|
||||
this._proxy.$registerLogger(resource);
|
||||
}
|
||||
|
||||
override deregisterLogger(resource: URI): void {
|
||||
super.deregisterLogger(resource);
|
||||
this._proxy.$deregisterLogger(resource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import { mark } from 'vs/base/common/performance';
|
||||
import { domContentLoaded, detectFullscreen, getCookieValue } from 'vs/base/browser/dom';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { ILogService, ConsoleLogger, MultiplexLogService, getLogLevel, ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { ILogService, ConsoleLogger, getLogLevel, ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { ConsoleLogInAutomationLogger } from 'vs/platform/log/browser/log';
|
||||
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { BrowserWorkbenchEnvironmentService, IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
|
||||
@ -35,12 +35,11 @@ import { SignService } from 'vs/platform/sign/browser/signService';
|
||||
import { IWorkbenchConstructionOptions, IWorkbench, ITunnel } from 'vs/workbench/browser/web.api';
|
||||
import { BrowserStorageService } from 'vs/workbench/services/storage/browser/storageService';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
|
||||
import { BufferLogger } from 'vs/platform/log/common/bufferLog';
|
||||
import { FileLoggerService } from 'vs/platform/log/common/fileLog';
|
||||
import { toLocalISOString } from 'vs/base/common/date';
|
||||
import { isWorkspaceToOpen, isFolderToOpen } from 'vs/platform/window/common/window';
|
||||
import { getSingleFolderWorkspaceIdentifier, getWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser/workspaces';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IndexedDBFileSystemProviderErrorDataClassification, IndexedDBFileSystemProvider, IndexedDBFileSystemProviderErrorData } from 'vs/platform/files/browser/indexedDBFileSystemProvider';
|
||||
@ -85,6 +84,7 @@ import { BrowserUserDataProfilesService } from 'vs/platform/userDataProfile/brow
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { rendererLogId } from 'vs/workbench/common/logConstants';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
|
||||
export class BrowserMain extends Disposable {
|
||||
|
||||
@ -243,7 +243,13 @@ export class BrowserMain extends Disposable {
|
||||
serviceCollection.set(IBrowserWorkbenchEnvironmentService, environmentService);
|
||||
|
||||
// Log
|
||||
const logService = new BufferLogService(getLogLevel(environmentService));
|
||||
const logLevel = getLogLevel(environmentService);
|
||||
const bufferLogger = new BufferLogger(logLevel);
|
||||
const otherLoggers = [new ConsoleLogger(logLevel)];
|
||||
if (environmentService.isExtensionDevelopment && !!environmentService.extensionTestsLocationURI) {
|
||||
otherLoggers.push(new ConsoleLogInAutomationLogger(logLevel));
|
||||
}
|
||||
const logService = new LogService(bufferLogger, otherLoggers);
|
||||
serviceCollection.set(ILogService, logService);
|
||||
|
||||
// Remote
|
||||
@ -275,10 +281,10 @@ export class BrowserMain extends Disposable {
|
||||
serviceCollection.set(IWorkbenchFileService, fileService);
|
||||
|
||||
// Logger
|
||||
const loggerService = new FileLoggerService(logService, fileService);
|
||||
const loggerService = new FileLoggerService(logLevel, fileService);
|
||||
serviceCollection.set(ILoggerService, loggerService);
|
||||
|
||||
await this.registerFileSystemProviders(environmentService, fileService, remoteAgentService, logService, loggerService, logsPath);
|
||||
await this.registerFileSystemProviders(environmentService, fileService, remoteAgentService, bufferLogger, logService, loggerService, logsPath);
|
||||
|
||||
// URI Identity
|
||||
const uriIdentityService = new UriIdentityService(fileService);
|
||||
@ -412,7 +418,7 @@ export class BrowserMain extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private async registerFileSystemProviders(environmentService: IWorkbenchEnvironmentService, fileService: IWorkbenchFileService, remoteAgentService: IRemoteAgentService, logService: BufferLogService, loggerService: ILoggerService, logsPath: URI): Promise<void> {
|
||||
private async registerFileSystemProviders(environmentService: IWorkbenchEnvironmentService, fileService: IWorkbenchFileService, remoteAgentService: IRemoteAgentService, bufferLogger: BufferLogger, logService: ILogService, loggerService: ILoggerService, logsPath: URI): Promise<void> {
|
||||
|
||||
// IndexedDB is used for logging and user data
|
||||
let indexedDB: IndexedDB | undefined;
|
||||
@ -437,12 +443,7 @@ export class BrowserMain extends Disposable {
|
||||
fileService.registerProvider(logsPath.scheme, new InMemoryFileSystemProvider());
|
||||
}
|
||||
|
||||
logService.logger = new MultiplexLogService(coalesce([
|
||||
new ConsoleLogger(logService.getLevel()),
|
||||
loggerService.createLogger(environmentService.logFile, { id: rendererLogId, name: localize('rendererLog', "Window") }),
|
||||
// Extension development test CLI: forward everything to test runner
|
||||
environmentService.isExtensionDevelopment && !!environmentService.extensionTestsLocationURI ? new ConsoleLogInAutomationLogger(logService.getLevel()) : undefined
|
||||
]));
|
||||
bufferLogger.logger = loggerService.createLogger(environmentService.logFile, { id: rendererLogId, name: localize('rendererLog', "Window") });
|
||||
|
||||
// User data
|
||||
let userDataProvider;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { ILogService, ILoggerService, LogLevel, getLogLevel, parseLogLevel } from 'vs/platform/log/common/log';
|
||||
import { ILoggerService, LogLevel, getLogLevel, isLogLevel, 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';
|
||||
@ -13,7 +13,6 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
|
||||
import { dirname, basename, isEqual } from 'vs/base/common/resources';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IOutputService } from 'vs/workbench/services/output/common/output';
|
||||
import { isNumber } from 'vs/base/common/types';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { extensionTelemetryLogChannelId, telemetryLogChannelId } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
@ -21,10 +20,6 @@ import { extensionTelemetryLogChannelId, telemetryLogChannelId } from 'vs/platfo
|
||||
type LogLevelQuickPickItem = IQuickPickItem & { level: LogLevel };
|
||||
type LogChannelQuickPickItem = IQuickPickItem & { id: string; resource: URI; extensionId?: string };
|
||||
|
||||
function isLogLevel(thing: unknown): thing is LogLevel {
|
||||
return isNumber(thing);
|
||||
}
|
||||
|
||||
export class SetLogLevelAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.setLogLevel';
|
||||
@ -32,7 +27,6 @@ export class SetLogLevelAction extends Action {
|
||||
|
||||
constructor(id: string, label: string,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@ILoggerService private readonly loggerService: ILoggerService,
|
||||
@IOutputService private readonly outputService: IOutputService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@ -44,7 +38,7 @@ export class SetLogLevelAction extends Action {
|
||||
const logLevelOrChannel = await this.selectLogLevelOrChannel();
|
||||
if (logLevelOrChannel !== null) {
|
||||
if (isLogLevel(logLevelOrChannel)) {
|
||||
this.logService.setLevel(logLevelOrChannel);
|
||||
this.loggerService.setLogLevel(logLevelOrChannel);
|
||||
} else {
|
||||
await this.setLogLevelForChannel(logLevelOrChannel);
|
||||
}
|
||||
@ -53,7 +47,7 @@ export class SetLogLevelAction extends Action {
|
||||
|
||||
private async selectLogLevelOrChannel(): Promise<LogChannelQuickPickItem | LogLevel | null> {
|
||||
const extensionLogs: LogChannelQuickPickItem[] = [], logs: LogChannelQuickPickItem[] = [];
|
||||
const logLevel = this.logService.getLevel();
|
||||
const logLevel = this.loggerService.getLogLevel();
|
||||
for (const channel of this.outputService.getChannelDescriptors()) {
|
||||
if (!channel.log || !channel.file || channel.id === telemetryLogChannelId || channel.id === extensionTelemetryLogChannelId) {
|
||||
continue;
|
||||
@ -68,7 +62,7 @@ export class SetLogLevelAction extends Action {
|
||||
}
|
||||
const entries: (LogLevelQuickPickItem | LogChannelQuickPickItem | IQuickPickSeparator)[] = [];
|
||||
entries.push({ type: 'separator', label: nls.localize('all', "All") });
|
||||
entries.push(...this.getLogLevelEntries(this.getDefaultLogLevel(), this.logService.getLevel()));
|
||||
entries.push(...this.getLogLevelEntries(this.getDefaultLogLevel(), this.loggerService.getLogLevel()));
|
||||
entries.push({ type: 'separator', label: nls.localize('loggers', "Logs") });
|
||||
entries.push(...logs.sort((a, b) => a.label.localeCompare(b.label)));
|
||||
if (extensionLogs.length && logs.length) {
|
||||
@ -86,7 +80,7 @@ export class SetLogLevelAction extends Action {
|
||||
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()] });
|
||||
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.loggerService.getLogLevel()] });
|
||||
if (entry) {
|
||||
this.loggerService.setLogLevel(logChannel.resource, entry.level);
|
||||
}
|
||||
|
||||
@ -9,11 +9,9 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle
|
||||
import { ILabelService, ResourceLabelFormatting } from 'vs/platform/label/common/label';
|
||||
import { OperatingSystem, isWeb, OS } from 'vs/base/common/platform';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IRemoteAgentService, RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { ILoggerService, ILogService } from 'vs/platform/log/common/log';
|
||||
import { LogLevelChannel, LogLevelChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { localize } from 'vs/nls';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
@ -31,7 +29,7 @@ import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { IDownloadService } from 'vs/platform/download/common/download';
|
||||
import { DownloadServiceChannel } from 'vs/platform/download/common/downloadIpc';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { TerminalLogConstants } from 'vs/platform/terminal/common/terminal';
|
||||
import { RemoteLoggerChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
|
||||
export class LabelContribution implements IWorkbenchContribution {
|
||||
constructor(
|
||||
@ -74,19 +72,9 @@ class RemoteChannelsContribution extends Disposable implements IWorkbenchContrib
|
||||
@ILoggerService loggerService: ILoggerService,
|
||||
) {
|
||||
super();
|
||||
const updateRemoteLogLevel = () => {
|
||||
const connection = remoteAgentService.getConnection();
|
||||
if (!connection) {
|
||||
return;
|
||||
}
|
||||
connection.withChannel('logger', (channel) => LogLevelChannelClient.setLevel(channel, logService.getLevel()));
|
||||
};
|
||||
updateRemoteLogLevel();
|
||||
this._register(logService.onDidChangeLogLevel(updateRemoteLogLevel));
|
||||
const connection = remoteAgentService.getConnection();
|
||||
if (connection) {
|
||||
connection.registerChannel('download', new DownloadServiceChannel(downloadService));
|
||||
connection.registerChannel('logger', new LogLevelChannel(logService, loggerService));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,20 +88,7 @@ class RemoteLogOutputChannels extends Disposable implements IWorkbenchContributi
|
||||
super();
|
||||
const connection = remoteAgentService.getConnection();
|
||||
if (connection) {
|
||||
remoteAgentService.getEnvironment().then(remoteEnv => {
|
||||
if (remoteEnv) {
|
||||
const remoteServerLog = 'remoteServerLog';
|
||||
const remotePtyHostLog = 'remotePtyHostLog';
|
||||
loggerService.registerLogger({ id: remoteServerLog, name: localize('remoteExtensionLog', "Remote Server"), resource: joinPath(remoteEnv.logsPath, `${RemoteExtensionLogFileName}.log`) });
|
||||
loggerService.registerLogger({ id: remotePtyHostLog, name: localize('remotePtyHostLog', "Remote Pty Host"), resource: joinPath(remoteEnv.logsPath, `${TerminalLogConstants.FileName}.log`) });
|
||||
this._register(loggerService.onDidChangeLogLevel(([resource, logLevel]) => {
|
||||
const logger = loggerService.getRegisteredLogger(resource);
|
||||
if (logger?.id === remoteServerLog || logger?.id === remotePtyHostLog) {
|
||||
connection.withChannel('logger', (channel) => LogLevelChannelClient.setLevel(channel, logLevel, resource));
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
connection.withChannel('logger', async channel => this._register(new RemoteLoggerChannelClient(loggerService, channel)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'
|
||||
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
|
||||
import { INativeKeyboardLayoutService, NativeKeyboardLayoutService } from 'vs/workbench/services/keybinding/electron-sandbox/nativeKeyboardLayoutService';
|
||||
import { ElectronIPCMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
|
||||
import { LoggerChannelClient, LogLevelChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { LoggerChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { NativeLogService } from 'vs/workbench/services/log/electron-sandbox/logService';
|
||||
import { WorkspaceTrustEnablementService, WorkspaceTrustManagementService } from 'vs/workbench/services/workspaces/common/workspaceTrust';
|
||||
@ -170,12 +170,11 @@ export class DesktopMain extends Disposable {
|
||||
serviceCollection.set(INativeWorkbenchEnvironmentService, environmentService);
|
||||
|
||||
// Logger
|
||||
const logLevelChannelClient = new LogLevelChannelClient(mainProcessService.getChannel('logLevel'));
|
||||
const loggerService = new LoggerChannelClient(this.configuration.windowId, this.configuration.logLevel, logLevelChannelClient.onDidChangeLogLevel, this.configuration.loggers, mainProcessService.getChannel('logger'));
|
||||
const loggerService = new LoggerChannelClient(this.configuration.windowId, this.configuration.logLevel, this.configuration.loggers, mainProcessService.getChannel('logger'));
|
||||
serviceCollection.set(ILoggerService, loggerService);
|
||||
|
||||
// Log
|
||||
const logService = this._register(new NativeLogService(`renderer${this.configuration.windowId}`, this.configuration.logLevel, loggerService, logLevelChannelClient, environmentService));
|
||||
const logService = this._register(new NativeLogService(this.configuration.logLevel, loggerService, environmentService));
|
||||
serviceCollection.set(ILogService, logService);
|
||||
if (isCI) {
|
||||
logService.info('workbench#open()'); // marking workbench open helps to diagnose flaky integration/smoke tests
|
||||
|
||||
@ -249,9 +249,6 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
||||
throw canceled();
|
||||
}
|
||||
|
||||
// Register logger for web worker exthost log
|
||||
this._loggerService.registerLogger({ id: 'webWorkerExtHostLog', name: localize('name', "Worker Extension Host"), resource: this._extensionHostLogFile });
|
||||
|
||||
return protocol;
|
||||
}
|
||||
|
||||
@ -317,6 +314,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
||||
loggers: [...this._loggerService.getRegisteredLoggers()],
|
||||
logsLocation: this._extensionHostLogsLocation,
|
||||
logFile: this._extensionHostLogFile,
|
||||
logName: localize('name', "Worker Extension Host"),
|
||||
autoStart: initData.autoStart,
|
||||
remote: {
|
||||
authority: this._environmentService.remoteAuthority,
|
||||
|
||||
@ -34,6 +34,7 @@ export interface IExtensionHostInitData {
|
||||
loggers: UriDto<ILoggerResource>[];
|
||||
logsLocation: URI;
|
||||
logFile: URI;
|
||||
logName: string;
|
||||
autoStart: boolean;
|
||||
remote: { isRemote: boolean; authority: string | undefined; connectionData: IRemoteConnectionData | null };
|
||||
consoleForward: { includeStack: boolean; logNative: boolean };
|
||||
|
||||
@ -148,14 +148,11 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
|
||||
reject('The remote extenion host took longer than 60s to send its ready message.');
|
||||
}, 60 * 1000);
|
||||
|
||||
let logFile: URI;
|
||||
|
||||
const disposable = protocol.onMessage(msg => {
|
||||
|
||||
if (isMessageOfType(msg, MessageType.Ready)) {
|
||||
// 1) Extension Host is ready to receive messages, initialize it
|
||||
this._createExtHostInitData(isExtensionDevelopmentDebug).then(data => {
|
||||
logFile = data.logFile;
|
||||
protocol.send(VSBuffer.fromString(JSON.stringify(data)));
|
||||
});
|
||||
return;
|
||||
@ -169,9 +166,6 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
|
||||
// stop listening for messages here
|
||||
disposable.dispose();
|
||||
|
||||
// Register logger for remote exthost log
|
||||
this._loggerService.registerLogger({ id: 'remoteExtHostLog', name: localize('remote extension host Log', "Remote Extension Host"), resource: logFile });
|
||||
|
||||
// release this promise
|
||||
this._protocol = protocol;
|
||||
resolve(protocol);
|
||||
@ -250,6 +244,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost {
|
||||
loggers: [...this._loggerService.getRegisteredLoggers()],
|
||||
logsLocation: remoteInitData.extensionHostLogsPath,
|
||||
logFile: joinPath(remoteInitData.extensionHostLogsPath, `${ExtensionHostLogFileName}.log`),
|
||||
logName: localize('remote extension host Log', "Remote Extension Host"),
|
||||
autoStart: true,
|
||||
uiKind: platform.isWeb ? UIKind.Web : UIKind.Desktop
|
||||
};
|
||||
|
||||
@ -415,9 +415,6 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {
|
||||
// stop listening for messages here
|
||||
disposable.dispose();
|
||||
|
||||
// Register logger for exthost log
|
||||
this._loggerService.registerLogger({ id: 'extHostLog', name: nls.localize('extension host Log', "Extension Host"), resource: this._extensionHostLogFile });
|
||||
|
||||
// release this promise
|
||||
resolve();
|
||||
return;
|
||||
@ -474,6 +471,7 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost {
|
||||
loggers: [...this._loggerService.getRegisteredLoggers()],
|
||||
logsLocation: this._environmentService.extHostLogsPath,
|
||||
logFile: this._extensionHostLogFile,
|
||||
logName: nls.localize('extension host Log', "Extension Host"),
|
||||
autoStart: initData.autoStart,
|
||||
uiKind: UIKind.Desktop
|
||||
};
|
||||
|
||||
@ -3,39 +3,32 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { LogService, ConsoleLogger, MultiplexLogService, ILogger, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { ConsoleLogger, ILogger, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService';
|
||||
import { LogLevelChannelClient, FollowerLogService, LoggerChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { LoggerChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { localize } from 'vs/nls';
|
||||
import { rendererLogId } from 'vs/workbench/common/logConstants';
|
||||
import { LogService } from 'vs/platform/log/common/logService';
|
||||
|
||||
export class NativeLogService extends LogService {
|
||||
|
||||
constructor(name: string, logLevel: LogLevel, loggerService: LoggerChannelClient, loggerClient: LogLevelChannelClient, environmentService: INativeWorkbenchEnvironmentService) {
|
||||
constructor(logLevel: LogLevel, loggerService: LoggerChannelClient, environmentService: INativeWorkbenchEnvironmentService) {
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
const loggers: ILogger[] = [];
|
||||
const fileLogger = disposables.add(loggerService.createLogger(environmentService.logFile, { id: rendererLogId, name: localize('rendererLog', "Window") }));
|
||||
|
||||
// Always log to file
|
||||
loggers.push(disposables.add(loggerService.createLogger(environmentService.logFile, { id: rendererLogId, name: localize('rendererLog', "Window") })));
|
||||
|
||||
// Extension development test CLI: forward everything to main side
|
||||
let consoleLogger: ILogger;
|
||||
if (environmentService.isExtensionDevelopment && !!environmentService.extensionTestsLocationURI) {
|
||||
loggers.push(loggerService.createConsoleMainLogger());
|
||||
// Extension development test CLI: forward everything to main side
|
||||
consoleLogger = loggerService.createConsoleMainLogger();
|
||||
} else {
|
||||
// Normal mode: Log to console
|
||||
consoleLogger = new ConsoleLogger(logLevel);
|
||||
}
|
||||
|
||||
// Normal mode: Log to console
|
||||
else {
|
||||
loggers.push(
|
||||
disposables.add(new ConsoleLogger(logLevel)),
|
||||
);
|
||||
}
|
||||
|
||||
const multiplexLogger = disposables.add(new MultiplexLogService(loggers));
|
||||
const followerLogger = disposables.add(new FollowerLogService(loggerClient, multiplexLogger));
|
||||
super(followerLogger);
|
||||
super(fileLogger, [consoleLogger]);
|
||||
|
||||
this._register(disposables);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user