未验证 提交 91c8e61e 编写于 作者: R Rob Lourens 提交者: GitHub

Merge pull request #40142 from Microsoft/roblou/extHostLogger2

Expose log level and log path to extensions
......@@ -10,10 +10,11 @@ import { ILogService, LogLevel, NullLogService } from 'vs/platform/log/common/lo
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { RotatingLogger, setAsyncMode } from 'spdlog';
export function createLogService(processName: string, environmentService: IEnvironmentService): ILogService {
export function createLogService(processName: string, environmentService: IEnvironmentService, logsSubfolder?: string): ILogService {
try {
setAsyncMode(8192, 2000);
const logfilePath = path.join(environmentService.logsPath, `${processName}.log`);
const logsDirPath = logsSubfolder ? path.join(environmentService.logsPath, logsSubfolder) : environmentService.logsPath;
const logfilePath = path.join(logsDirPath, `${processName}.log`);
const logger = new RotatingLogger(processName, logfilePath, 1024 * 1024 * 5, 6);
logger.setLevel(0);
......
......@@ -335,4 +335,40 @@ declare module 'vscode' {
private constructor(enabled: boolean, condition: string, hitCondition: string, functionName: string);
}
/**
* The severity level of a log message
*/
export enum LogLevel {
Trace = 1,
Debug = 2,
Info = 3,
Warning = 4,
Error = 5,
Critical = 6,
Off = 7
}
/**
* A logger for writing to an extension's log file, and accessing its dedicated log directory.
*/
export interface Logger {
readonly onDidChangeLogLevel: Event<LogLevel>;
readonly currentLevel: LogLevel;
readonly logDirectory: Thenable<string>;
trace(message: string, ...args: any[]): void;
debug(message: string, ...args: any[]): void;
info(message: string, ...args: any[]): void;
warn(message: string, ...args: any[]): void;
error(message: string | Error, ...args: any[]): void;
critical(message: string | Error, ...args: any[]): void;
}
export interface ExtensionContext {
/**
* This extension's logger
*/
logger: Logger;
}
}
......@@ -569,6 +569,7 @@ export function createApiFactory(
Hover: extHostTypes.Hover,
IndentAction: languageConfiguration.IndentAction,
Location: extHostTypes.Location,
LogLevel: extHostTypes.LogLevel,
MarkdownString: extHostTypes.MarkdownString,
OverviewRulerLane: EditorCommon.OverviewRulerLane,
ParameterInformation: extHostTypes.ParameterInformation,
......
......@@ -779,6 +779,7 @@ export const ExtHostContext = {
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
ExtHostQuickOpen: createExtId<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
ExtHostExtensionService: createExtId<ExtHostExtensionServiceShape>('ExtHostExtensionService'),
// ExtHostLogService: createExtId<ExtHostLogServiceShape>('ExtHostLogService'),
ExtHostTerminalService: createExtId<ExtHostTerminalServiceShape>('ExtHostTerminalService'),
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM', ProxyType.CustomMarshaller),
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask', ProxyType.CustomMarshaller),
......
......@@ -10,6 +10,7 @@ import Severity from 'vs/base/common/severity';
import { TPromise } from 'vs/base/common/winjs.base';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtHostLogger } from 'vs/workbench/api/node/extHostLogService';
const hasOwnProperty = Object.hasOwnProperty;
const NO_OP_VOID_PROMISE = TPromise.wrap<void>(void 0);
......@@ -26,6 +27,7 @@ export interface IExtensionContext {
extensionPath: string;
storagePath: string;
asAbsolutePath(relativePath: string): string;
logger: ExtHostLogger;
}
/**
......
......@@ -20,6 +20,8 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { TernarySearchTree } from 'vs/base/common/map';
import { Barrier } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
class ExtensionMemento implements IExtensionMemento {
......@@ -117,6 +119,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private readonly _storagePath: ExtensionStoragePath;
private readonly _proxy: MainThreadExtensionServiceShape;
private readonly _logService: ILogService;
private readonly _extHostLogService: ExtHostLogService;
private _activator: ExtensionsActivator;
private _extensionPathIndex: TPromise<TernarySearchTree<IExtensionDescription>>;
/**
......@@ -126,7 +129,8 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
threadService: IExtHostContext,
extHostWorkspace: ExtHostWorkspace,
extHostConfiguration: ExtHostConfiguration,
logService: ILogService
logService: ILogService,
environmentService: IEnvironmentService
) {
this._barrier = new Barrier();
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
......@@ -137,6 +141,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment);
this._proxy = this._threadService.getProxy(MainContext.MainThreadExtensionService);
this._activator = null;
this._extHostLogService = new ExtHostLogService(environmentService);
// initialize API first (i.e. do not release barrier until the API is initialized)
const apiFactory = createApiFactory(initData, threadService, extHostWorkspace, extHostConfiguration, this, logService);
......@@ -331,13 +336,15 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
workspaceState.whenReady,
this._storagePath.whenReady
]).then(() => {
const that = this;
return Object.freeze(<IExtensionContext>{
globalState,
workspaceState,
subscriptions: [],
get extensionPath() { return extensionDescription.extensionFolderPath; },
storagePath: this._storagePath.value(extensionDescription),
asAbsolutePath: (relativePath: string) => { return join(extensionDescription.extensionFolderPath, relativePath); }
asAbsolutePath: (relativePath: string) => { return join(extensionDescription.extensionFolderPath, relativePath); },
get logger() { return that._extHostLogService.getExtLogger(extensionDescription.id); }
});
});
}
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as path from 'path';
import * as vscode from 'vscode';
import { TPromise } from 'vs/base/common/winjs.base';
import { mkdirp, dirExists } from 'vs/base/node/pfs';
import Event, { Emitter } from 'vs/base/common/event';
import { LogLevel } from 'vs/workbench/api/node/extHostTypes';
import { ILogService } from 'vs/platform/log/common/log';
import { createLogService } from 'vs/platform/log/node/spdlogService';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { memoize } from 'vs/base/common/decorators';
export class ExtHostLogService {
private _loggers: Map<string, ExtHostLogger> = new Map();
constructor(private _environmentService: IEnvironmentService) {
}
getExtLogger(extensionID: string): ExtHostLogger {
if (!this._loggers.has(extensionID)) {
const logService = createLogService(extensionID, this._environmentService, extensionID);
const logsDirPath = path.join(this._environmentService.logsPath, extensionID);
this._loggers.set(extensionID, new ExtHostLogger(logService, logsDirPath));
}
return this._loggers.get(extensionID);
}
}
export class ExtHostLogger implements vscode.Logger {
private _currentLevel: LogLevel;
private _onDidChangeLogLevel: Emitter<LogLevel>;
constructor(
private readonly _logService: ILogService,
private readonly _logDirectory: string
) {
this._currentLevel = this._logService.getLevel();
this._onDidChangeLogLevel = new Emitter<LogLevel>();
this.onDidChangeLogLevel = this._onDidChangeLogLevel.event;
}
// TODO
readonly onDidChangeLogLevel: Event<LogLevel>;
get currentLevel(): LogLevel { return this._currentLevel; }
@memoize
get logDirectory(): TPromise<string> {
return dirExists(this._logDirectory).then(exists => {
if (exists) {
return TPromise.wrap(null);
} else {
return mkdirp(this._logDirectory);
}
}).then(() => {
return this._logDirectory;
});
}
trace(message: string, ...args: any[]): void {
return this._logService.trace(message, ...args);
}
debug(message: string, ...args: any[]): void {
return this._logService.debug(message, ...args);
}
info(message: string, ...args: any[]): void {
return this._logService.info(message, ...args);
}
warn(message: string, ...args: any[]): void {
return this._logService.warn(message, ...args);
}
error(message: string | Error, ...args: any[]): void {
return this._logService.error(message, ...args);
}
critical(message: string | Error, ...args: any[]): void {
return this._logService.critical(message, ...args);
}
}
......@@ -1531,3 +1531,13 @@ export class FunctionBreakpoint extends Breakpoint {
this.functionName = functionName;
}
}
export enum LogLevel {
Trace = 1,
Debug = 2,
Info = 3,
Warning = 4,
Error = 5,
Critical = 6,
Off = 7
}
......@@ -99,7 +99,7 @@ export class ExtensionHostMain {
this._logService.trace('initData', initData);
this._extHostConfiguration = new ExtHostConfiguration(rpcProtocol.getProxy(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration);
this._extensionService = new ExtHostExtensionService(initData, rpcProtocol, extHostWorkspace, this._extHostConfiguration, this._logService);
this._extensionService = new ExtHostExtensionService(initData, rpcProtocol, extHostWorkspace, this._extHostConfiguration, this._logService, environmentService);
// error forwarding and stack trace scanning
const extensionErrors = new WeakMap<Error, IExtensionDescription>();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册