* Add trace level debugging

* Fixes

* Simpler

* Remove dead code

* Delete unwanted method

* Remove dead code
This commit is contained in:
Don Jayamanne 2024-05-03 13:08:24 +10:00 коммит произвёл GitHub
Родитель a823a873ec
Коммит fb39f04ce6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
23 изменённых файлов: 221 добавлений и 262 удалений

Просмотреть файл

@ -1461,7 +1461,16 @@
"error",
"warn",
"info",
"debug"
"debug",
"trace"
],
"enumDescriptions": [
"%jupyter.configuration.jupyter.logging.level.off%",
"%jupyter.configuration.jupyter.logging.level.error%",
"%jupyter.configuration.jupyter.logging.level.warn%",
"%jupyter.configuration.jupyter.logging.level.info%",
"%jupyter.configuration.jupyter.logging.level.debug%",
"%jupyter.configuration.jupyter.logging.level.trace%"
],
"description": "%jupyter.configuration.jupyter.logging.level.description%"
},

Просмотреть файл

@ -134,6 +134,12 @@
"jupyter.debuggers.interactive": "Python Interactive Window",
"jupyter.configuration.jupyter.experiments.enabled.description": "Enables/disables A/B tests.",
"jupyter.configuration.jupyter.showVariableViewWhenDebugging.description": "Bring up the Variable View when starting a Run by Line session.",
"jupyter.configuration.jupyter.logging.level.off": "No messages are logged with this level.",
"jupyter.configuration.jupyter.logging.level.trace": "All messages are logged with this level.",
"jupyter.configuration.jupyter.logging.level.debug": " ",
"jupyter.configuration.jupyter.logging.level.info": "Information, warning and error messages are logged with this level.",
"jupyter.configuration.jupyter.logging.level.warn": "Warning and error messages are logged with this level.",
"jupyter.configuration.jupyter.logging.level.error": "Only error messages are logged with this level.",
"jupyter.configuration.jupyter.logging.level.description": "The logging level the extension logs at.",
"jupyter.configuration.jupyter.experiments.optInto.markdownDescription": "List of experiment to opt into. If empty, user is assigned the default experiment groups. [Learn more](https://github.com/microsoft/vscode-jupyter/wiki/Experiments).",
"jupyter.configuration.jupyter.experiments.optOutFrom.markdownDescription": "List of experiment to opt out of. If empty, user is assigned the default experiment groups. [Learn more](https://github.com/microsoft/vscode-jupyter/wiki/Experiments).",

Просмотреть файл

@ -27,7 +27,6 @@ import {
import { getDisplayPath } from './platform/common/platform/fs-paths';
import {
GLOBAL_MEMENTO,
IConfigurationService,
IDisposableRegistry,
IExperimentService,
IExtensionContext,
@ -36,10 +35,9 @@ import {
IOutputChannel,
WORKSPACE_MEMENTO
} from './platform/common/types';
import { Common, OutputChannelNames } from './platform/common/utils/localize';
import { Common } from './platform/common/utils/localize';
import { IServiceContainer, IServiceManager } from './platform/ioc/types';
import { registerLogger, setLoggingLevel, traceError } from './platform/logging';
import { OutputChannelLogger } from './platform/logging/outputChannelLogger';
import { initializeLoggers as init, traceError } from './platform/logging';
import { getJupyterOutputChannel } from './standalone/devTools/jupyterOutputChannel';
import { isUsingPylance } from './standalone/intellisense/notebookPythonPathService';
import { noop } from './platform/common/utils/misc';
@ -50,20 +48,18 @@ import { sendTelemetryEvent } from './telemetry';
import { IExtensionActivationManager } from './platform/activation/types';
import { getVSCodeChannel } from './platform/common/application/applicationEnvironment';
export function addOutputChannel(
export function initializeLoggers(
context: IExtensionContext,
serviceManager: IServiceManager,
options?: { userNameRegEx?: RegExp; homePathRegEx?: RegExp; platform: string; arch: string; homePath: string }
options: {
addConsoleLogger: boolean;
userNameRegEx?: RegExp;
homePathRegEx?: RegExp;
platform?: string;
arch?: string;
homePath?: string;
}
) {
const standardOutputChannel = window.createOutputChannel(OutputChannelNames.jupyter, 'log');
registerLogger(new OutputChannelLogger(standardOutputChannel, options?.userNameRegEx, options?.homePathRegEx));
serviceManager.addSingletonInstance<OutputChannel>(IOutputChannel, standardOutputChannel, STANDARD_OUTPUT_CHANNEL);
serviceManager.addSingletonInstance<OutputChannel>(
IOutputChannel,
getJupyterOutputChannel(context.subscriptions),
JUPYTER_OUTPUT_CHANNEL
);
const standardOutputChannel = init(options);
// Log env info.
standardOutputChannel.appendLine(`${env.appName} (${version}, ${env.remoteName}, ${env.appHost})`);
standardOutputChannel.appendLine(`Jupyter Extension Version: ${context.extension.packageJSON['version']}.`);
@ -99,9 +95,14 @@ export function addOutputChannel(
.join(', ')}`
);
}
return standardOutputChannel;
}
export function initializeGlobals(context: IExtensionContext): [IServiceManager, IServiceContainer] {
export function initializeGlobals(
context: IExtensionContext,
standardOutputChannel: OutputChannel
): [IServiceManager, IServiceContainer] {
const cont = new Container({ skipBaseClassChecks: true });
const serviceManager = new ServiceManager(cont);
const serviceContainer = new ServiceContainer(cont);
@ -113,6 +114,12 @@ export function initializeGlobals(context: IExtensionContext): [IServiceManager,
serviceManager.addSingletonInstance<Memento>(IMemento, context.globalState, GLOBAL_MEMENTO);
serviceManager.addSingletonInstance<Memento>(IMemento, context.workspaceState, WORKSPACE_MEMENTO);
serviceManager.addSingletonInstance<IExtensionContext>(IExtensionContext, context);
serviceManager.addSingletonInstance<OutputChannel>(IOutputChannel, standardOutputChannel, STANDARD_OUTPUT_CHANNEL);
serviceManager.addSingletonInstance<OutputChannel>(
IOutputChannel,
getJupyterOutputChannel(context.subscriptions),
JUPYTER_OUTPUT_CHANNEL
);
return [serviceManager, serviceContainer];
}
@ -153,11 +160,7 @@ function notifyUser(msg: string) {
}
}
export async function postActivateLegacy(
context: IExtensionContext,
serviceManager: IServiceManager,
serviceContainer: IServiceContainer
) {
export async function postActivateLegacy(context: IExtensionContext, serviceContainer: IServiceContainer) {
// Load the two data science experiments that we need to register types
// Await here to keep the register method sync
const experimentService = serviceContainer.get<IExperimentService>(IExperimentService);
@ -167,17 +170,6 @@ export async function postActivateLegacy(
const duration = stopWatch.elapsedTime;
sendTelemetryEvent(Telemetry.ExperimentLoad, { duration });
const configuration = serviceManager.get<IConfigurationService>(IConfigurationService);
// We should start logging using the log level as soon as possible, so set it as soon as we can access the level.
// `IConfigurationService` may depend any of the registered types, so doing it after all registrations are finished.
// XXX Move this *after* abExperiments is activated?
const settings = configuration.getSettings();
setLoggingLevel(settings.logging.level, settings.logging.widgets);
context.subscriptions.push(
settings.onDidChange(() => setLoggingLevel(settings.logging.level, settings.logging.widgets))
);
// "initialize" "services"
commands.executeCommand('setContext', 'jupyter.vscode.channel', getVSCodeChannel()).then(noop, noop);

Просмотреть файл

@ -35,7 +35,7 @@ import './platform/logging';
//===============================================
// loading starts here
import { commands, env, ExtensionMode, UIKind, workspace } from 'vscode';
import { commands, env, ExtensionMode, UIKind, workspace, type OutputChannel } from 'vscode';
import { buildApi, IExtensionApi } from './standalone/api';
import { setHomeDirectory, traceError } from './platform/logging';
import { IAsyncDisposableRegistry, IExtensionContext, IsDevMode } from './platform/common/types';
@ -48,9 +48,7 @@ import { registerTypes as registerNotebookTypes } from './notebooks/serviceRegis
import { registerTypes as registerInteractiveTypes } from './interactive-window/serviceRegistry.node';
import { registerTypes as registerStandaloneTypes } from './standalone/serviceRegistry.node';
import { registerTypes as registerWebviewTypes } from './webviews/extension-side/serviceRegistry.node';
import { Exiting, isCI, isTestExecution, setIsCodeSpace, setIsWebExtension } from './platform/common/constants';
import { registerLogger } from './platform/logging';
import { ConsoleLogger } from './platform/logging/consoleLogger';
import { Exiting, isTestExecution, setIsCodeSpace, setIsWebExtension } from './platform/common/constants';
import { initializeGlobals as initializeTelemetryGlobals } from './platform/telemetry/telemetry';
import { IInterpreterPackages } from './platform/interpreter/types';
import { homedir, platform, arch, userInfo } from 'os';
@ -63,7 +61,7 @@ import {
import { activate as activateChat, deactivate as deactivateChat } from './standalone/chat/extesnion';
import { setDisposableTracker } from './platform/common/utils/lifecycle';
import {
addOutputChannel,
initializeLoggers,
displayProgress,
handleError,
initializeGlobals,
@ -84,13 +82,22 @@ let activatedServiceContainer: IServiceContainer | undefined;
export async function activate(context: IExtensionContext): Promise<IExtensionApi> {
durations.startActivateTime = stopWatch.elapsedTime;
const standardOutputChannel = initializeLoggers(context, {
addConsoleLogger: !!process.env.VSC_JUPYTER_FORCE_LOGGING,
userNameRegEx: tryGetUsername(),
homePathRegEx: tryGetHomePath(),
arch: arch(),
platform: platform(),
homePath: homePath.fsPath
});
activateNotebookTelemetry(stopWatch);
setDisposableTracker(context.subscriptions);
setIsCodeSpace(env.uiKind == UIKind.Web);
setIsWebExtension(false);
context.subscriptions.push({ dispose: () => (Exiting.isExiting = true) });
try {
const [api, ready] = activateUnsafe(context);
const [api, ready] = activateUnsafe(context, standardOutputChannel);
await ready;
// Send the "success" telemetry only if activation did not fail.
// Otherwise Telemetry is send via the error handler.
@ -140,18 +147,21 @@ export function deactivate(): Thenable<void> {
// activation helpers
// eslint-disable-next-line
function activateUnsafe(context: IExtensionContext): [IExtensionApi, Promise<void>, IServiceContainer] {
function activateUnsafe(
context: IExtensionContext,
standardOutputChannel: OutputChannel
): [IExtensionApi, Promise<void>, IServiceContainer] {
const progress = displayProgress();
try {
//===============================================
// activation starts here
const [serviceManager, serviceContainer] = initializeGlobals(context);
const [serviceManager, serviceContainer] = initializeGlobals(context, standardOutputChannel);
activatedServiceContainer = serviceContainer;
initializeTelemetryGlobals((interpreter) =>
serviceContainer.get<IInterpreterPackages>(IInterpreterPackages).getPackageVersions(interpreter)
);
const activationPromise = activateComponents(context, serviceManager, serviceContainer);
const activationPromise = activateLegacy(context, serviceManager, serviceContainer);
//===============================================
// activation ends here
@ -168,30 +178,6 @@ function activateUnsafe(context: IExtensionContext): [IExtensionApi, Promise<voi
}
}
/////////////////////////////
// error handling
async function activateComponents(
context: IExtensionContext,
serviceManager: IServiceManager,
serviceContainer: IServiceContainer
) {
// We will be pulling code over from activateLegacy().
return activateLegacy(context, serviceManager, serviceContainer);
}
function addConsoleLogger() {
if (process.env.VSC_JUPYTER_FORCE_LOGGING) {
let label = undefined;
// In CI there's no need for the label.
if (!isCI) {
label = 'Jupyter Extension:';
}
registerLogger(new ConsoleLogger(label));
}
}
function escapeRegExp(text: string) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
@ -247,16 +233,6 @@ async function activateLegacy(
// Set the logger home dir (we can compute this in a node app)
setHomeDirectory(homedir());
// Setup the console logger if asked to
addOutputChannel(context, serviceManager, {
userNameRegEx: tryGetUsername(),
homePathRegEx: tryGetHomePath(),
arch: arch(),
platform: platform(),
homePath: homePath.fsPath
});
addConsoleLogger();
// Register the rest of the types (platform is first because it's needed by others)
registerPlatformTypes(serviceManager);
registerKernelTypes(serviceManager, isDevMode);
@ -265,5 +241,5 @@ async function activateLegacy(
registerStandaloneTypes(context, serviceManager, isDevMode);
registerWebviewTypes(serviceManager);
await postActivateLegacy(context, serviceManager, serviceContainer);
await postActivateLegacy(context, serviceContainer);
}

Просмотреть файл

@ -46,7 +46,7 @@ import './platform/logging';
//===============================================
// loading starts here
import { commands, env, ExtensionMode, UIKind, workspace } from 'vscode';
import { commands, env, ExtensionMode, UIKind, workspace, type OutputChannel } from 'vscode';
import { buildApi, IExtensionApi } from './standalone/api';
import { traceError } from './platform/logging';
import { IAsyncDisposableRegistry, IExtensionContext, IsDevMode } from './platform/common/types';
@ -60,13 +60,11 @@ import { registerTypes as registerInteractiveTypes } from './interactive-window/
import { registerTypes as registerTerminalTypes } from './platform/terminals/serviceRegistry.web';
import { registerTypes as registerStandaloneTypes } from './standalone/serviceRegistry.web';
import { registerTypes as registerWebviewTypes } from './webviews/extension-side/serviceRegistry.web';
import { Exiting, isCI, isTestExecution, setIsCodeSpace, setIsWebExtension } from './platform/common/constants';
import { registerLogger } from './platform/logging';
import { ConsoleLogger } from './platform/logging/consoleLogger';
import { Exiting, isTestExecution, setIsCodeSpace, setIsWebExtension } from './platform/common/constants';
import { initializeGlobals as initializeTelemetryGlobals } from './platform/telemetry/telemetry';
import { setDisposableTracker } from './platform/common/utils/lifecycle';
import {
addOutputChannel,
initializeLoggers,
displayProgress,
handleError,
initializeGlobals,
@ -87,13 +85,15 @@ let activatedServiceContainer: IServiceContainer | undefined;
export async function activate(context: IExtensionContext): Promise<IExtensionApi> {
durations.startActivateTime = stopWatch.elapsedTime;
const standardOutputChannel = initializeLoggers(context, { addConsoleLogger: isTestExecution() });
activateNotebookTelemetry(stopWatch);
setDisposableTracker(context.subscriptions);
setIsCodeSpace(env.uiKind == UIKind.Web);
setIsWebExtension(true);
context.subscriptions.push({ dispose: () => (Exiting.isExiting = true) });
try {
const [api, ready] = activateUnsafe(context);
const [api, ready] = activateUnsafe(context, standardOutputChannel);
await ready;
// Send the "success" telemetry only if activation did not fail.
// Otherwise Telemetry is send via the error handler.
@ -139,16 +139,20 @@ export function deactivate(): Thenable<void> {
// activation helpers
// eslint-disable-next-line
function activateUnsafe(context: IExtensionContext): [IExtensionApi, Promise<void>, IServiceContainer] {
function activateUnsafe(
context: IExtensionContext,
standardOutputChannel: OutputChannel
): [IExtensionApi, Promise<void>, IServiceContainer] {
const progress = displayProgress();
try {
//===============================================
// activation starts here
const [serviceManager, serviceContainer] = initializeGlobals(context);
const [serviceManager, serviceContainer] = initializeGlobals(context, standardOutputChannel);
activatedServiceContainer = serviceContainer;
initializeTelemetryGlobals(() => Promise.resolve(new Map()));
const activationPromise = activateComponents(context, serviceManager, serviceContainer);
const activationPromise = activateLegacy(context, serviceManager, serviceContainer);
//===============================================
// activation ends here
@ -160,30 +164,6 @@ function activateUnsafe(context: IExtensionContext): [IExtensionApi, Promise<voi
}
}
/////////////////////////////
// error handling
async function activateComponents(
context: IExtensionContext,
serviceManager: IServiceManager,
serviceContainer: IServiceContainer
) {
// We will be pulling code over from activateLegacy().
return activateLegacy(context, serviceManager, serviceContainer);
}
function addConsoleLogger() {
if (isTestExecution()) {
let label = undefined;
// In CI there's no need for the label.
if (!isCI) {
label = 'Jupyter Extension:';
}
registerLogger(new ConsoleLogger(label));
}
}
/////////////////////////////
// old activation code
@ -210,10 +190,6 @@ async function activateLegacy(
}
commands.executeCommand('setContext', 'jupyter.webExtension', true).then(noop, noop);
// Output channel is special. We need it before everything else
addOutputChannel(context, serviceManager);
addConsoleLogger();
// Register the rest of the types (platform is first because it's needed by others)
registerPlatformTypes(serviceManager);
registerNotebookTypes(serviceManager, isDevMode);
@ -223,5 +199,5 @@ async function activateLegacy(
registerStandaloneTypes(context, serviceManager, isDevMode);
registerWebviewTypes(serviceManager);
await postActivateLegacy(context, serviceManager, serviceContainer);
await postActivateLegacy(context, serviceContainer);
}

Просмотреть файл

@ -25,14 +25,7 @@ import {
} from '../platform/common/constants';
import { WrappedError } from '../platform/errors/types';
import { splitLines } from '../platform/common/helpers';
import {
traceInfo,
traceInfoIfCI,
traceError,
traceVerbose,
traceWarning,
traceVerboseWidgets
} from '../platform/logging';
import { traceInfo, traceInfoIfCI, traceError, traceVerbose, traceWarning, traceTrace } from '../platform/logging';
import { getDisplayPath, getFilePath } from '../platform/common/platform/fs-paths';
import { Resource, IDisposable, IDisplayOptions } from '../platform/common/types';
import { createDeferred, raceTimeout, raceTimeoutError } from '../platform/common/utils/async';
@ -859,7 +852,7 @@ abstract class BaseKernel implements IBaseKernel {
);
const newVersion = (this._ipywidgetsVersion = isVersion7 ? 7 : isVersion8 ? 8 : undefined);
traceVerboseWidgets(`Determined IPyWidgets Version as ${newVersion}`);
traceTrace(`Determined IPyWidgets Version as ${newVersion}`);
// If user does not have ipywidgets installed, then this event will never get fired.
this._ipywidgetsVersion == newVersion;
this._onIPyWidgetVersionResolved.fire(newVersion);

Просмотреть файл

@ -4,7 +4,7 @@
import type { KernelMessage } from '@jupyterlab/services';
import { Event, EventEmitter, NotebookDocument, Uri, commands, env, window } from 'vscode';
import { STANDARD_OUTPUT_CHANNEL, WIDGET_VERSION_NON_PYTHON_KERNELS } from '../../../../platform/common/constants';
import { traceVerboseWidgets, traceError, traceInfoWidgets, traceInfoIfCI } from '../../../../platform/logging';
import { traceTrace, traceError, traceInfoIfCI } from '../../../../platform/logging';
import {
IDisposableRegistry,
IOutputChannel,
@ -167,7 +167,7 @@ export class CommonMessageCoordinator {
}
// IPyWidgets scripts will not be loaded if we're unable to determine the version of IPyWidgets.
const version = await deferred.promise;
traceVerboseWidgets(`Version of IPyWidgets ${version} determined after ${stopWatch.elapsedTime / 1000}s`);
traceTrace(`Version of IPyWidgets ${version} determined after ${stopWatch.elapsedTime / 1000}s`);
webview
.postMessage({
type: IPyWidgetMessages.IPyWidgets_Reply_Widget_Version,
@ -189,7 +189,7 @@ export class CommonMessageCoordinator {
void env.openExternal(Uri.parse(m.url));
}
if (m.type === IPyWidgetMessages.IPyWidgets_Ready) {
traceVerboseWidgets('Web view is ready to receive widget messages');
traceTrace('Web view is ready to receive widget messages');
this.readyMessageReceived = true;
this.sendPendingWebViewMessages(webview);
}
@ -327,7 +327,7 @@ export class CommonMessageCoordinator {
const errorMsg = msg as KernelMessage.IErrorMsg;
errorMsg.content.traceback = errorMsg.content.traceback.map(stripAnsi);
}
traceInfoWidgets(`Unhandled widget kernel message: ${msg.header.msg_type} ${msg.content}`);
traceTrace(`Unhandled widget kernel message: ${msg.header.msg_type} ${msg.content}`);
this.jupyterOutput.appendLine(
DataScience.unhandledMessage(msg.header.msg_type, JSON.stringify(msg.content))
);

Просмотреть файл

@ -5,7 +5,7 @@ import type { Kernel, KernelMessage } from '@jupyterlab/services';
import uuid from 'uuid/v4';
import { Event, EventEmitter, NotebookDocument } from 'vscode';
import type { Data as WebSocketData } from 'ws';
import { traceVerboseWidgets, traceError } from '../../../../platform/logging';
import { traceTrace, traceError } from '../../../../platform/logging';
import { Identifiers, WIDGET_MIMETYPE } from '../../../../platform/common/constants';
import { IDisposable } from '../../../../platform/common/types';
import { Deferred, createDeferred } from '../../../../platform/common/utils/async';
@ -121,7 +121,7 @@ export class IPyWidgetMessageDispatcher implements IIPyWidgetMessageDispatcher {
if (payload.category === 'error') {
traceError(`Widget Error: ${payload.message}`);
} else {
traceVerboseWidgets(`Widget Message: ${payload.message}`);
traceTrace(`Widget Message: ${payload.message}`);
}
break;
}
@ -437,7 +437,7 @@ export class IPyWidgetMessageDispatcher implements IIPyWidgetMessageDispatcher {
return;
}
traceVerboseWidgets(`Registering commtarget ${targetName}`);
traceTrace(`Registering commtarget ${targetName}`);
this.commTargetsRegistered.add(targetName);
this.pendingTargetNames.delete(targetName);

Просмотреть файл

@ -8,7 +8,7 @@ import { GLOBAL_MEMENTO, IConfigurationService, IMemento, WidgetCDNs } from '../
import { createDeferred, createDeferredFromPromise, Deferred } from '../../../../platform/common/utils/async';
import { Common, DataScience } from '../../../../platform/common/utils/localize';
import { noop } from '../../../../platform/common/utils/misc';
import { traceError, traceInfoWidgets, traceInfoIfCI, traceVerboseWidgets } from '../../../../platform/logging';
import { traceError, traceTrace, traceInfoIfCI } from '../../../../platform/logging';
import { ConsoleForegroundColors } from '../../../../platform/logging/types';
import { sendTelemetryEvent } from '../../../../telemetry';
import { IWidgetScriptSourceProvider, WidgetScriptSource } from '../types';
@ -165,7 +165,7 @@ export class CDNWidgetScriptSourceProvider implements IWidgetScriptSourceProvide
moduleName: string,
moduleVersion: string
): Promise<WidgetScriptSource> {
traceInfoWidgets(
traceTrace(
`${
ConsoleForegroundColors.Green
}Searching for Widget Script ${moduleName}#${moduleVersion} using cdns ${this.cdnProviders.join(' ')}`
@ -180,7 +180,7 @@ export class CDNWidgetScriptSourceProvider implements IWidgetScriptSourceProvide
);
const scriptUri = uris.find((u) => u);
if (scriptUri) {
traceInfoWidgets(
traceTrace(
`${ConsoleForegroundColors.Green}Widget Script ${moduleName}#${moduleVersion} found at URI: ${scriptUri}`
);
return { moduleName, scriptUri, source: 'cdn' };
@ -200,7 +200,7 @@ export class CDNWidgetScriptSourceProvider implements IWidgetScriptSourceProvide
return downloadUrl;
}
} catch (ex) {
traceVerboseWidgets(`Failed downloading ${moduleName}:${moduleVersion} from ${cdn}`);
traceTrace(`Failed downloading ${moduleName}:${moduleVersion} from ${cdn}`);
return undefined;
}
}

Просмотреть файл

@ -3,7 +3,7 @@
import type * as jupyterlabService from '@jupyterlab/services';
import { Event, EventEmitter, NotebookDocument, Uri } from 'vscode';
import { traceError, traceInfoWidgets, traceVerboseWidgets, traceWarning } from '../../../../platform/logging';
import { traceError, traceTrace, traceWarning } from '../../../../platform/logging';
import { IDisposableRegistry, IConfigurationService, IDisposable } from '../../../../platform/common/types';
import { InteractiveWindowMessages, IPyWidgetMessages } from '../../../../messageTypes';
import { sendTelemetryEvent, Telemetry } from '../../../../telemetry';
@ -132,7 +132,7 @@ export class IPyWidgetScriptSource {
this.kernel.onDisposed(() => this.dispose());
this.handlePendingRequests();
this.sendBaseUrl();
traceVerboseWidgets('IPyWidgetScriptSource.initialize');
traceTrace('IPyWidgetScriptSource.initialize');
}
/**
* Sends the base url of the remote Jupyter server to the webview.
@ -189,7 +189,7 @@ export class IPyWidgetScriptSource {
private async onRequestWidgetScript(payload: { moduleName: string; moduleVersion: string; requestId: string }) {
const { moduleName, moduleVersion, requestId } = payload;
traceInfoWidgets(`${ConsoleForegroundColors.Green}Fetch Script for ${JSON.stringify(payload)}`);
traceTrace(`${ConsoleForegroundColors.Green}Fetch Script for ${JSON.stringify(payload)}`);
await this.sendWidgetSource(moduleName, moduleVersion, requestId).catch((ex) =>
traceError('Failed to send widget sources upon ready', ex)
);
@ -221,7 +221,7 @@ export class IPyWidgetScriptSource {
let widgetSource: WidgetScriptSource = { moduleName, requestId };
try {
traceInfoWidgets(`${ConsoleForegroundColors.Green}Fetch Script for ${moduleName}`);
traceTrace(`${ConsoleForegroundColors.Green}Fetch Script for ${moduleName}`);
widgetSource = await this.scriptProvider.getWidgetScriptSource(moduleName, moduleVersion);
// If we have a widget source from CDN, never overwrite that.
if (this.widgetSources.get(widgetSource.moduleName)?.source !== 'cdn') {
@ -231,7 +231,7 @@ export class IPyWidgetScriptSource {
traceError('Failed to get widget source due to an error', ex);
sendTelemetryEvent(Telemetry.HashedIPyWidgetScriptDiscoveryError);
} finally {
traceInfoWidgets(
traceTrace(
`${ConsoleForegroundColors.Green}Script for ${moduleName}, is ${widgetSource.scriptUri} from ${widgetSource.source}`
);
// Send to UI (even if there's an error) continues instead of hanging while waiting for a response.

Просмотреть файл

@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { traceError, traceVerboseWidgets, traceWarning } from '../../../../platform/logging';
import { traceError, traceTrace, traceWarning } from '../../../../platform/logging';
import { WidgetCDNs, IConfigurationService } from '../../../../platform/common/types';
import { sendTelemetryEvent, Telemetry } from '../../../../telemetry';
import { getTelemetrySafeHashedString } from '../../../../platform/telemetry/helpers';
@ -102,7 +102,7 @@ export class IPyWidgetScriptSourceProvider extends DisposableBase implements IWi
.join(', ')}`
);
} else {
traceVerboseWidgets(
traceTrace(
`Script source for Widget ${moduleName}@${moduleVersion} was found from source ${found.source} and ${found.scriptUri}`
);
}

Просмотреть файл

@ -5,7 +5,7 @@ import type * as nbformat from '@jupyterlab/nbformat';
import * as path from '../../../../platform/vscode-path/path';
import { ExtensionMode, Uri } from 'vscode';
import { IExtensionContext } from '../../../../platform/common/types';
import { traceError, traceInfoIfCI, traceVerboseWidgets } from '../../../../platform/logging';
import { traceError, traceInfoIfCI, traceTrace } from '../../../../platform/logging';
import { executeSilently, isPythonKernelConnection } from '../../../../kernels/helpers';
import { IKernel, RemoteKernelConnectionMetadata } from '../../../../kernels/types';
import { IIPyWidgetScriptManager } from '../types';
@ -111,7 +111,7 @@ export class RemoteIPyWidgetScriptManager extends BaseIPyWidgetScriptManager imp
return [];
}
try {
traceVerboseWidgets(`Widget Outputs include, ${output.text}`);
traceTrace(`Widget Outputs include, ${output.text}`);
// Value will be an array of the form `['xyz', 'abc']`
const items = (output.text as string)
.trim()

Просмотреть файл

@ -4,7 +4,7 @@
import { inject, injectable } from 'inversify';
import { NotebookDocument, Disposable, NotebookEditor, Uri, EventEmitter, workspace, window } from 'vscode';
import { dispose } from '../../platform/common/utils/lifecycle';
import { traceVerboseWidgets } from '../../platform/logging';
import { traceTrace } from '../../platform/logging';
import { getDisplayPath } from '../../platform/common/platform/fs-paths';
import { IDisposableRegistry, IDisposable } from '../../platform/common/types';
import { IServiceContainer } from '../../platform/ioc/types';
@ -142,7 +142,7 @@ export class NotebookIPyWidgetCoordinator implements IExtensionSyncActivationSer
}
const notebook = editor.notebook;
if (!controller) {
traceVerboseWidgets(
traceTrace(
`No controller, hence notebook communications cannot be initialized for editor ${getDisplayPath(
editor.notebook.uri
)}`

Просмотреть файл

@ -7,7 +7,6 @@ import {
Disposable,
Event,
EventEmitter,
LogLevel,
Uri,
WorkspaceConfiguration,
workspace
@ -15,11 +14,9 @@ import {
import { isTestExecution } from './constants';
import {
IExperiments,
ILoggingSettings,
InteractiveWindowMode,
InteractiveWindowViewColumn,
IWatchableJupyterSettings,
LoggingLevelSettingType,
Resource,
WidgetCDNs
} from './types';
@ -41,7 +38,6 @@ export class JupyterSettings implements IWatchableJupyterSettings {
private static jupyterSettings: Map<string, JupyterSettings> = new Map<string, JupyterSettings>();
public experiments!: IExperiments;
public logging: ILoggingSettings = { level: LogLevel.Error };
public allowUnauthorizedRemoteConnection: boolean = false;
public jupyterInterruptTimeout: number = 10_000;
public jupyterLaunchTimeout: number = 60_000;
@ -176,17 +172,6 @@ export class JupyterSettings implements IWatchableJupyterSettings {
private update(jupyterConfig: WorkspaceConfiguration, pythonConfig: WorkspaceConfiguration | undefined) {
const systemVariables = this.createSystemVariables(undefined);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const loggingSettings = systemVariables.resolveAny(jupyterConfig.get<any>('logging'))!;
if (loggingSettings) {
loggingSettings.level = convertSettingTypeToLogLevel(loggingSettings.level);
if (this.logging) {
Object.assign<ILoggingSettings, ILoggingSettings>(this.logging, loggingSettings);
} else {
this.logging = loggingSettings;
}
}
const experiments = systemVariables.resolveAny(jupyterConfig.get<IExperiments>('experiments'))!;
if (this.experiments) {
Object.assign<IExperiments, IExperiments>(this.experiments, experiments);
@ -284,23 +269,3 @@ export class JupyterSettings implements IWatchableJupyterSettings {
return Object.getOwnPropertyNames(this).filter((f) => !f.startsWith('_'));
}
}
function convertSettingTypeToLogLevel(setting: LoggingLevelSettingType | undefined): LogLevel | 'off' {
switch (setting) {
case 'info': {
return LogLevel.Info;
}
case 'warn': {
return LogLevel.Warning;
}
case 'off': {
return 'off';
}
case 'error': {
return LogLevel.Error;
}
default: {
return LogLevel.Debug;
}
}
}

Просмотреть файл

@ -1,16 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import {
ConfigurationTarget,
Disposable,
Event,
ExtensionContext,
OutputChannel,
Uri,
Range,
type LogLevel
} from 'vscode';
import { ConfigurationTarget, Disposable, Event, ExtensionContext, OutputChannel, Uri, Range } from 'vscode';
import { PythonEnvironment } from '../pythonEnvironments/info';
import { CommandIds } from '../../commands';
import { ISystemVariables } from './variables/types';
@ -54,7 +45,6 @@ export interface IRandom {
export interface IJupyterSettings {
readonly experiments: IExperiments;
readonly logging: ILoggingSettings;
readonly allowUnauthorizedRemoteConnection: boolean;
readonly jupyterInterruptTimeout: number;
readonly jupyterLaunchTimeout: number;
@ -116,13 +106,6 @@ export interface IWatchableJupyterSettings extends IJupyterSettings {
createSystemVariables(resource: Resource): ISystemVariables;
}
export type LoggingLevelSettingType = 'off' | 'error' | 'warn' | 'info' | 'debug';
export interface ILoggingSettings {
readonly level: LogLevel;
readonly widgets?: LoggingLevelSettingType | 'off';
}
export interface IExperiments {
/**
* Return `true` if experiments are enabled, else `false`.

Просмотреть файл

@ -14,23 +14,22 @@ function formatMessage(level: string | undefined, message: string, ...data: Argu
export class ConsoleLogger implements ILogger {
constructor(private readonly prefix: string | undefined) {}
public traceLog(message: string, ...data: Arguments): void {
console.log(format(`${this.prefix || ''} ${message}`, ...data));
}
public traceError(message: string, ...data: Arguments): void {
public error(message: string, ...data: Arguments): void {
console.error(formatMessage('error', `${this.prefix || ''} ${message}`, ...data));
}
public traceWarn(message: string, ...data: Arguments): void {
public warn(message: string, ...data: Arguments): void {
console.warn(formatMessage('warn', `${this.prefix || ''} ${message}`, ...data));
}
public traceInfo(message: string, ...data: Arguments): void {
public info(message: string, ...data: Arguments): void {
console.info(formatMessage('info', `${this.prefix || ''} ${message}`, ...data));
}
public traceVerbose(message: string, ...data: Arguments): void {
console.log(formatMessage('verbose', `${this.prefix || ''} ${message}`, ...data));
public verbose(message: string, ...data: Arguments): void {
console.log(formatMessage('debug', `${this.prefix || ''} ${message}`, ...data));
}
public trace(message: string, ...data: Arguments): void {
console.trace(formatMessage('trace', `${this.prefix || ''} ${message}`, ...data));
}
}

Просмотреть файл

@ -4,14 +4,18 @@
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Disposable, Uri, LogLevel } from 'vscode';
import { Disposable, Uri, LogLevel, workspace, window } from 'vscode';
import { isCI } from '../common/constants';
import { Arguments, ILogger, TraceDecoratorType, TraceOptions } from './types';
import { CallInfo, trace as traceDecorator } from '../common/utils/decorators';
import { argsToLogString, returnValueToLogString } from './util';
import { LoggingLevelSettingType } from '../common/types';
import { splitLines } from '../common/helpers';
import { getDisplayPath } from '../common/platform/fs-paths';
import { trackDisposable } from '../common/utils/lifecycle';
import { OutputChannelNames } from '../common/utils/localize';
import { OutputChannelLogger } from './outputChannelLogger';
import { ConsoleLogger } from './consoleLogger';
let homeAsLowerCase = '';
const DEFAULT_OPTS: TraceOptions = TraceOptions.Arguments | TraceOptions.ReturnValue;
@ -27,6 +31,40 @@ export type TraceInfo =
| undefined;
let loggers: ILogger[] = [];
let globalLoggingLevel: LogLevel = LogLevel.Info;
export const logger: ILogger = {
error: (message: string, ...data: Arguments) => traceError(message, ...data),
warn: (message: string, ...data: Arguments) => traceWarning(message, ...data),
info: (message: string, ...data: Arguments) => traceInfo(message, ...data),
verbose: (message: string, ...data: Arguments) => traceVerbose(message, ...data),
trace: (message: string, ...data: Arguments) => traceTrace(message, ...data)
};
export function initializeLoggers(options: {
addConsoleLogger: boolean;
userNameRegEx?: RegExp;
homePathRegEx?: RegExp;
platform?: string;
arch?: string;
homePath?: string;
}) {
globalLoggingLevel = getLoggingLevelFromConfig();
trackDisposable(
workspace.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration('jupyter.logging')) {
globalLoggingLevel = getLoggingLevelFromConfig();
}
})
);
const standardOutputChannel = window.createOutputChannel(OutputChannelNames.jupyter, 'log');
registerLogger(new OutputChannelLogger(standardOutputChannel, options?.userNameRegEx, options?.homePathRegEx));
// In CI there's no need for the label.
registerLogger(new ConsoleLogger(isCI ? undefined : 'Jupyter Extension:'));
return standardOutputChannel;
}
export function registerLogger(logger: ILogger): Disposable {
loggers.push(logger);
return {
@ -36,13 +74,44 @@ export function registerLogger(logger: ILogger): Disposable {
};
}
let globalLoggingLevel: LogLevel = LogLevel.Debug;
let _enabledWidgetLogging: LoggingLevelSettingType = 'off';
export function setLoggingLevel(level: LogLevel, enabledWidgetLogging?: LoggingLevelSettingType): void {
_enabledWidgetLogging = enabledWidgetLogging || 'off';
globalLoggingLevel = level;
type LoggingLevelSettingType = keyof typeof LogLevel | Lowercase<keyof typeof LogLevel> | 'warn' | 'Warn';
function getLoggingLevelFromConfig() {
try {
const { level } = workspace
.getConfiguration('jupyter')
.get<{ level: LoggingLevelSettingType }>('logging', { level: 'Info' });
switch (level) {
case 'debug':
case 'Debug': {
return LogLevel.Debug;
}
case 'warn':
case 'Warn':
case 'warning':
case 'Warning': {
return LogLevel.Warning;
}
case 'Off':
case 'off': {
return LogLevel.Off;
}
case 'Error':
case 'error': {
return LogLevel.Error;
}
case 'Trace':
case 'trace': {
return LogLevel.Trace;
}
default: {
return LogLevel.Info;
}
}
} catch (ex) {
console.error('Failed to get logging level from configuration', ex);
return LogLevel.Info;
}
}
export function setHomeDirectory(homeDir: string) {
homeAsLowerCase = homeDir.toLowerCase();
}
@ -113,36 +182,30 @@ function formatErrors(...args: Arguments) {
export function traceError(message: string, ...args: Arguments): void {
if (globalLoggingLevel <= LogLevel.Error) {
args = formatErrors(...args);
loggers.forEach((l) => l.traceError(message, ...args));
loggers.forEach((l) => l.error(message, ...args));
}
}
export function traceWarning(message: string, ...args: Arguments): void {
if (globalLoggingLevel <= LogLevel.Warning) {
args = formatErrors(...args);
loggers.forEach((l) => l.traceWarn(message, ...args));
loggers.forEach((l) => l.warn(message, ...args));
}
}
export function traceInfo(message: string, ...args: Arguments): void {
if (globalLoggingLevel <= LogLevel.Info) {
loggers.forEach((l) => l.traceInfo(message, ...args));
loggers.forEach((l) => l.info(message, ...args));
}
}
export function traceInfoWidgets(message: string, ...args: Arguments): void {
if (_enabledWidgetLogging !== 'off' && globalLoggingLevel <= LogLevel.Info) {
loggers.forEach((l) => l.traceInfo(message, ...args));
}
}
export function traceVerbose(message: string, ...args: Arguments): void {
if (globalLoggingLevel <= LogLevel.Debug) {
loggers.forEach((l) => l.traceVerbose(message, ...args));
loggers.forEach((l) => l.verbose(message, ...args));
}
}
export function traceVerboseWidgets(message: string, ...args: Arguments): void {
if (_enabledWidgetLogging !== 'off' && globalLoggingLevel <= LogLevel.Debug) {
loggers.forEach((l) => l.traceVerbose(message, ...args));
export function traceTrace(message: string, ...args: Arguments): void {
if (globalLoggingLevel <= LogLevel.Trace) {
loggers.forEach((l) => l.trace(message, ...args));
}
}
export function traceInfoIfCI(msg: () => [message: string, ...args: string[]] | string): void;

Просмотреть файл

@ -31,23 +31,23 @@ export class OutputChannelLogger implements ILogger {
return logMessage;
}
public traceLog(message: string, ...data: Arguments): void {
this.channel.appendLine(this.format('', message, ...data));
}
public traceError(message: string, ...data: Arguments): void {
public error(message: string, ...data: Arguments): void {
this.channel.appendLine(this.format('error', message, ...data));
}
public traceWarn(message: string, ...data: Arguments): void {
public warn(message: string, ...data: Arguments): void {
this.channel.appendLine(this.format('warn', message, ...data));
}
public traceInfo(message: string, ...data: Arguments): void {
public info(message: string, ...data: Arguments): void {
this.channel.appendLine(this.format('info', message, ...data));
}
public traceVerbose(message: string, ...data: Arguments): void {
public verbose(message: string, ...data: Arguments): void {
this.channel.appendLine(this.format('debug', message, ...data));
}
public trace(message: string, ...data: Arguments): void {
this.channel.appendLine(this.format('trace', message, ...data));
}
}

Просмотреть файл

@ -7,11 +7,11 @@
export type Arguments = unknown[];
export interface ILogger {
traceLog(message: string, ...data: Arguments): void;
traceError(message: string, ...data: Arguments): void;
traceWarn(message: string, ...data: Arguments): void;
traceInfo(message: string, ...data: Arguments): void;
traceVerbose(message: string, ...data: Arguments): void;
error(message: string, ...data: Arguments): void;
warn(message: string, ...data: Arguments): void;
info(message: string, ...data: Arguments): void;
verbose(message: string, ...data: Arguments): void;
trace(message: string, ...data: Arguments): void;
}
export type TraceDecoratorType = (

Просмотреть файл

@ -17,7 +17,7 @@ import {
} from '../notebook/helper';
import { initialize } from '../../initialize';
import { JVSC_EXTENSION_ID, PYTHON_LANGUAGE } from '../../../platform/common/constants';
import { traceInfoWidgets } from '../../../platform/logging';
import { traceTrace } from '../../../platform/logging';
import { IKernel, IKernelProvider, isLocalConnection } from '../../../kernels/types';
import { getTelemetrySafeHashedString } from '../../../platform/telemetry/helpers';
import { IFileSystem } from '../../../platform/common/platform/types';
@ -45,7 +45,7 @@ suite('IPyWidget Script Manager @widgets', function () {
let fs: IFileSystem;
let context: IExtensionContext;
suiteSetup(async function () {
traceInfoWidgets('Suite Setup');
traceTrace('Suite Setup');
api = await initialize();
await closeNotebooks();
await startJupyterServer();
@ -97,18 +97,18 @@ suite('IPyWidget Script Manager @widgets', function () {
kernel = kernelProvider.get(notebook)!;
scriptManager = widgetScriptManagerFactory.getOrCreate(kernel);
traceInfoWidgets('Suite Setup (completed)');
traceTrace('Suite Setup (completed)');
});
setup(async function () {
traceInfoWidgets(`Starting Test ${this.currentTest?.title}`);
traceTrace(`Starting Test ${this.currentTest?.title}`);
});
teardown(async function () {
traceInfoWidgets(`Ended Test ${this.currentTest?.title}`);
traceTrace(`Ended Test ${this.currentTest?.title}`);
if (this.currentTest?.isFailed()) {
await captureScreenShot(this);
}
traceInfoWidgets(`Ended Test (completed) ${this.currentTest?.title}`);
traceTrace(`Ended Test (completed) ${this.currentTest?.title}`);
});
suiteTeardown(() => closeNotebooksAndCleanUpAfterTests(disposables));
test('Returns the right base Url', async function () {

Просмотреть файл

@ -171,22 +171,22 @@ class ConsoleHijacker implements ILogger {
this._outputs = [];
return capturedOutput;
}
traceLog(message: string, ...data: Arguments): void {
this.logMessage(undefined, message, data);
}
traceError(message: string, ...data: Arguments): void {
error(message: string, ...data: Arguments): void {
this.logMessage('error', message, data);
}
traceWarn(message: string, ...data: Arguments): void {
warn(message: string, ...data: Arguments): void {
this.logMessage('warn', message, data);
}
traceInfo(message: string, ...data: Arguments): void {
info(message: string, ...data: Arguments): void {
this.logMessage(undefined, message, data);
}
traceEverything(message: string, ...data: Arguments): void {
this.logMessage(undefined, message, data);
}
traceVerbose(message: string, ...data: Arguments): void {
verbose(message: string, ...data: Arguments): void {
this.logMessage(undefined, message, data);
}
trace(message: string, ...data: Arguments): void {
this.logMessage(undefined, message, data);
}
logMessage(category: 'error' | 'warn' | undefined, message: string, ...data: Arguments) {

Просмотреть файл

@ -13,7 +13,7 @@ import { WIDGET_MIMETYPE } from '../../../platform/common/constants';
import { dispose } from '../../../platform/common/utils/lifecycle';
import { IDisposable } from '../../../platform/common/types';
import { noop } from '../../../platform/common/utils/misc';
import { traceVerboseWidgets } from '../../../platform/logging';
import { traceTrace } from '../../../platform/logging';
type WidgetData = {
model_id: string;
@ -140,10 +140,10 @@ export class IPyWidgetRendererComms implements IExtensionSyncActivationService {
// }
const version = kernel?.ipywidgetsVersion; // || versionInWidgetState;
if (kernel?.ipywidgetsVersion) {
traceVerboseWidgets(`IPyWidget version in Kernel is ${kernel?.ipywidgetsVersion}.`);
traceTrace(`IPyWidget version in Kernel is ${kernel?.ipywidgetsVersion}.`);
}
// if (versionInWidgetState) {
// traceVerboseWidgets(`IPyWidget version in Kernel is ${versionInWidgetState}.`);
// traceTrace(`IPyWidget version in Kernel is ${versionInWidgetState}.`);
// }
// if (kernel?.ipywidgetsVersion && versionInWidgetState) {
// traceWarning(

Просмотреть файл

@ -8,9 +8,6 @@ export function getDefaultSettings(): IJupyterExtraSettings {
// eslint-disable-next-line
const result: Partial<IJupyterExtraSettings> = {
experiments: { enabled: true, optInto: [], optOutFrom: [] },
logging: {
level: 5 // Not used in react side, should be removed later.
},
jupyterLaunchTimeout: 10,
jupyterLaunchRetries: 3,
// eslint-disable-next-line no-template-curly-in-string