Merge pull request #40142 from Microsoft/roblou/extHostLogger2

Expose log level and log path to extensions
This commit is contained in:
Rob Lourens
2017-12-14 16:12:22 -08:00
committed by GitHub
9 changed files with 152 additions and 5 deletions

View File

@@ -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,

View File

@@ -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),

View File

@@ -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;
}
/**

View File

@@ -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); }
});
});
}

View File

@@ -0,0 +1,89 @@
/*---------------------------------------------------------------------------------------------
* 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);
}
}

View File

@@ -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
}