Skip to content

Commit

Permalink
Adding logging infra to webview framework (#18613)
Browse files Browse the repository at this point in the history
* Refactoring context props to centralize shared props

* compiling checkpoint

* deduping vscode channels

* swapping from reducer to RPC

* added prefix and reusing shared MSSQL output channel

* swapping console.logs in react views for new logger API

* Adding timestamp to logger; fixing issue where first message of logger wouldn't include prefixed tags

* fixing up tests

* removing test print
  • Loading branch information
Benjin authored Feb 1, 2025
1 parent 9f685c3 commit e73af46
Show file tree
Hide file tree
Showing 34 changed files with 410 additions and 202 deletions.
51 changes: 24 additions & 27 deletions src/connectionconfig/connectionDialogWebviewController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import { ApiStatus } from "../sharedInterfaces/webview";
import { AzureController } from "../azure/azureController";
import { AzureSubscription } from "@microsoft/vscode-azext-azureauth";
import { IConnectionInfo } from "vscode-mssql";
import { Logger } from "../models/logger";
import MainController from "../controllers/mainController";
import { ObjectExplorerProvider } from "../objectExplorer/objectExplorerProvider";
import { ReactWebviewPanelController } from "../controllers/reactWebviewPanelController";
Expand Down Expand Up @@ -94,43 +93,41 @@ export class ConnectionDialogWebviewController extends ReactWebviewPanelControll
"encrypt",
];

private static _logger: Logger;

private _connectionToEditCopy: IConnectionDialogProfile | undefined;
private _azureSubscriptions: Map<string, AzureSubscription>;

//#endregion

constructor(
context: vscode.ExtensionContext,
vscodeWrapper: VscodeWrapper,
private _mainController: MainController,
private _objectExplorerProvider: ObjectExplorerProvider,
private _connectionToEdit?: IConnectionInfo,
) {
super(context, "connectionDialog", new ConnectionDialogWebviewState(), {
title: Loc.connectionDialog,
viewColumn: vscode.ViewColumn.Active,
iconPath: {
dark: vscode.Uri.joinPath(
context.extensionUri,
"media",
"connectionDialogEditor_dark.svg",
),
light: vscode.Uri.joinPath(
context.extensionUri,
"media",
"connectionDialogEditor_light.svg",
),
super(
context,
vscodeWrapper,
"connectionDialog",
"connectionDialog",
new ConnectionDialogWebviewState(),
{
title: Loc.connectionDialog,
viewColumn: vscode.ViewColumn.Active,
iconPath: {
dark: vscode.Uri.joinPath(
context.extensionUri,
"media",
"connectionDialogEditor_dark.svg",
),
light: vscode.Uri.joinPath(
context.extensionUri,
"media",
"connectionDialogEditor_light.svg",
),
},
},
});

if (!ConnectionDialogWebviewController._logger) {
const vscodeWrapper = new VscodeWrapper();
const channel = vscodeWrapper.createOutputChannel(
Loc.connectionDialog,
);
ConnectionDialogWebviewController._logger = Logger.create(channel);
}
);

this.registerRpcHandlers();
this.initializeDialog().catch((err) => {
Expand Down Expand Up @@ -1027,7 +1024,7 @@ export class ConnectionDialogWebviewController extends ReactWebviewPanelControll
account,
undefined,
);
ConnectionDialogWebviewController._logger.log(
this.logger.log(
"Token refreshed",
session.expiresOn,
);
Expand Down
4 changes: 4 additions & 0 deletions src/controllers/executionPlanWebviewController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ import {
updateTotalCost,
} from "./sharedExecutionPlanUtils";
import { ExecutionPlanService } from "../services/executionPlanService";
import VscodeWrapper from "./vscodeWrapper";

export class ExecutionPlanWebviewController extends ReactWebviewPanelController<
ep.ExecutionPlanWebviewState,
ep.ExecutionPlanReducers
> {
constructor(
context: vscode.ExtensionContext,
vscodeWrapper: VscodeWrapper,
public executionPlanService: ExecutionPlanService, // public for testing purposes
public untitledSqlDocumentService: UntitledSqlDocumentService,
public executionPlanContents: string,
Expand All @@ -32,6 +34,8 @@ export class ExecutionPlanWebviewController extends ReactWebviewPanelController<
) {
super(
context,
vscodeWrapper,
"executionPlan",
"executionPlan",
{
executionPlanState: {
Expand Down
24 changes: 15 additions & 9 deletions src/controllers/mainController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ export default class MainController implements vscode.Disposable {
if (connectionManager) {
this._connectionMgr = connectionManager;
}
this._vscodeWrapper = vscodeWrapper || new VscodeWrapper();
this._vscodeWrapper = vscodeWrapper ?? new VscodeWrapper();
this._untitledSqlDocumentService = new UntitledSqlDocumentService(
this._vscodeWrapper,
);
this.configuration = vscode.workspace.getConfiguration();
UserSurvey.createInstance(this._context);
UserSurvey.createInstance(this._context, this._vscodeWrapper);
}

/**
Expand Down Expand Up @@ -372,6 +372,7 @@ export default class MainController implements vscode.Disposable {

const providerInstance = new this.ExecutionPlanCustomEditorProvider(
this._context,
this._vscodeWrapper,
this.executionPlanService,
this._untitledSqlDocumentService,
);
Expand Down Expand Up @@ -546,9 +547,9 @@ export default class MainController implements vscode.Disposable {
// Init Query Results Webview Controller
this._queryResultWebviewController = new QueryResultWebviewController(
this._context,
this._vscodeWrapper,
this.executionPlanService,
this.untitledSqlDocumentService,
this._vscodeWrapper,
);

// Init content provider for results pane
Expand Down Expand Up @@ -762,6 +763,7 @@ export default class MainController implements vscode.Disposable {

const connDialog = new ConnectionDialogWebviewController(
this._context,
this._vscodeWrapper,
this,
this._objectExplorerProvider,
connectionInfo,
Expand Down Expand Up @@ -900,6 +902,7 @@ export default class MainController implements vscode.Disposable {
const connDialog =
new ConnectionDialogWebviewController(
this._context,
this._vscodeWrapper,
this,
this._objectExplorerProvider,
node.connectionInfo,
Expand Down Expand Up @@ -927,6 +930,7 @@ export default class MainController implements vscode.Disposable {
const schemaDesignerWebvie =
new SchemaDesignerWebviewController(
this._context,
this._vscodeWrapper,
this.schemaDesignerService,
node.metadata.name,
schema,
Expand All @@ -943,6 +947,7 @@ export default class MainController implements vscode.Disposable {
async (node: TreeNodeInfo) => {
const reactPanel = new TableDesignerWebviewController(
this._context,
this._vscodeWrapper,
this.tableDesignerService,
this._connectionMgr,
this._untitledSqlDocumentService,
Expand All @@ -961,6 +966,7 @@ export default class MainController implements vscode.Disposable {
async (node: TreeNodeInfo) => {
const reactPanel = new TableDesignerWebviewController(
this._context,
this._vscodeWrapper,
this.tableDesignerService,
this._connectionMgr,
this._untitledSqlDocumentService,
Expand All @@ -976,6 +982,7 @@ export default class MainController implements vscode.Disposable {
const filterNode = async (node: TreeNodeInfo) => {
const filters = await ObjectExplorerFilter.getFilters(
this._context,
this._vscodeWrapper,
node,
);
if (filters) {
Expand Down Expand Up @@ -2324,13 +2331,11 @@ export default class MainController implements vscode.Disposable {
private ExecutionPlanCustomEditorProvider = class
implements vscode.CustomTextEditorProvider
{
context: vscode.ExtensionContext;
executionPlanService: ExecutionPlanService;
untitledSqlService: UntitledSqlDocumentService;
constructor(
context: vscode.ExtensionContext,
executionPlanService: ExecutionPlanService,
untitledSqlService: UntitledSqlDocumentService,
public context: vscode.ExtensionContext,
public vscodeWrapper: VscodeWrapper,
public executionPlanService: ExecutionPlanService,
public untitledSqlService: UntitledSqlDocumentService,
) {
this.context = context;
this.executionPlanService = executionPlanService;
Expand All @@ -2354,6 +2359,7 @@ export default class MainController implements vscode.Disposable {

const executionPlanController = new ExecutionPlanWebviewController(
this.context,
this.vscodeWrapper,
this.executionPlanService,
this.untitledSqlService,
planContents,
Expand Down
20 changes: 19 additions & 1 deletion src/controllers/reactWebviewBaseController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
TelemetryViews,
} from "../sharedInterfaces/telemetry";
import {
LogEvent,
WebviewTelemetryActionEvent,
WebviewTelemetryErrorEvent,
} from "../sharedInterfaces/webview";
Expand All @@ -21,6 +22,8 @@ import {
} from "../telemetry/telemetry";

import { getNonce } from "../utils/utils";
import { Logger } from "../models/logger";
import VscodeWrapper from "./vscodeWrapper";

/**
* ReactWebviewBaseController is a class that manages a vscode.Webview and provides
Expand Down Expand Up @@ -118,6 +121,8 @@ export abstract class ReactWebviewBaseController<State, Reducers>
}
};

protected logger: Logger;

/**
* Creates a new ReactWebviewPanelController
* @param _context The context of the extension
Expand All @@ -126,9 +131,17 @@ export abstract class ReactWebviewBaseController<State, Reducers>
*/
constructor(
protected _context: vscode.ExtensionContext,
protected vscodeWrapper: VscodeWrapper,
private _sourceFile: string,
private _initialData: State,
) {}
viewId?: string,
) {
if (!vscodeWrapper) {
vscodeWrapper = new VscodeWrapper();
}

this.logger = Logger.create(vscodeWrapper.outputChannel, viewId);
}

protected initializeBase() {
this.state = this._initialData;
Expand Down Expand Up @@ -282,9 +295,14 @@ export abstract class ReactWebviewBaseController<State, Reducers>
...args,
);
};

this._webviewRequestHandlers["getPlatform"] = async () => {
return process.platform;
};

this._webviewRequestHandlers["log"] = async (message: LogEvent) => {
this.logger[message.level ?? "log"](message.message);
};
}

/**
Expand Down
5 changes: 4 additions & 1 deletion src/controllers/reactWebviewPanelController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { MssqlWebviewPanelOptions } from "../sharedInterfaces/webview";
import { ReactWebviewBaseController } from "./reactWebviewBaseController";
import { sendActionEvent } from "../telemetry/telemetry";
import VscodeWrapper from "./vscodeWrapper";

/**
* ReactWebviewPanelController is a class that manages a vscode.WebviewPanel and provides
Expand All @@ -39,11 +40,13 @@ export class ReactWebviewPanelController<
*/
constructor(
_context: vscode.ExtensionContext,
vscodeWrapper: VscodeWrapper,
sourceFile: string,
_viewId: string,
initialData: State,
private _options: MssqlWebviewPanelOptions,
) {
super(_context, sourceFile, initialData);
super(_context, vscodeWrapper, sourceFile, initialData, _viewId);
this.createWebviewPanel();
// This call sends messages to the Webview so it's called after the Webview creation.
this.initializeBase();
Expand Down
4 changes: 3 additions & 1 deletion src/controllers/reactWebviewViewController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import * as vscode from "vscode";
import { ReactWebviewBaseController } from "./reactWebviewBaseController";
import VscodeWrapper from "./vscodeWrapper";

/**
* ReactWebviewViewController is a class that manages a vscode.WebviewView and provides
Expand All @@ -28,11 +29,12 @@ export class ReactWebviewViewController<State, Reducers>
*/
constructor(
_context: vscode.ExtensionContext,
_vscodeWrapper: VscodeWrapper,
_sourceFile: string,
private _viewId: string,
initialData: State,
) {
super(_context, _sourceFile, initialData);
super(_context, _vscodeWrapper, _sourceFile, initialData, _viewId);
}

protected _getWebview(): vscode.Webview {
Expand Down
Loading

0 comments on commit e73af46

Please sign in to comment.