diff --git a/extensions/arc/src/ui/components/dashboard.ts b/extensions/arc/src/ui/components/dashboard.ts index 4cacfeb6dd..4284b5dbf3 100644 --- a/extensions/arc/src/ui/components/dashboard.ts +++ b/extensions/arc/src/ui/components/dashboard.ts @@ -9,7 +9,7 @@ export abstract class Dashboard { private dashboard!: azdata.window.ModelViewDashboard; - constructor(protected title: string) { } + constructor(protected title: string, protected readonly name: string) { } public async showDashboard(): Promise { this.dashboard = this.createDashboard(); @@ -17,7 +17,7 @@ export abstract class Dashboard { } protected createDashboard(): azdata.window.ModelViewDashboard { - const dashboard = azdata.window.createModelViewDashboard(this.title); + const dashboard = azdata.window.createModelViewDashboard(this.title, this.name); dashboard.registerTabs(async modelView => { return await this.registerTabs(modelView); }); diff --git a/extensions/arc/src/ui/dashboards/controller/controllerDashboard.ts b/extensions/arc/src/ui/dashboards/controller/controllerDashboard.ts index 5945b6df98..cf2722bed2 100644 --- a/extensions/arc/src/ui/dashboards/controller/controllerDashboard.ts +++ b/extensions/arc/src/ui/dashboards/controller/controllerDashboard.ts @@ -12,7 +12,7 @@ import * as loc from '../../../localizedConstants'; export class ControllerDashboard extends Dashboard { constructor(private _controllerModel: ControllerModel) { - super(loc.arcControllerDashboard(_controllerModel.info.name)); + super(loc.arcControllerDashboard(_controllerModel.info.name), 'ArcDataControllerDashboard'); } public async showDashboard(): Promise { diff --git a/extensions/arc/src/ui/dashboards/miaa/miaaDashboard.ts b/extensions/arc/src/ui/dashboards/miaa/miaaDashboard.ts index 3a7a24b044..8f52b2c15d 100644 --- a/extensions/arc/src/ui/dashboards/miaa/miaaDashboard.ts +++ b/extensions/arc/src/ui/dashboards/miaa/miaaDashboard.ts @@ -14,7 +14,7 @@ import { MiaaModel } from '../../../models/miaaModel'; export class MiaaDashboard extends Dashboard { constructor(private _controllerModel: ControllerModel, private _miaaModel: MiaaModel) { - super(loc.miaaDashboard(_miaaModel.info.name)); + super(loc.miaaDashboard(_miaaModel.info.name), 'ArcMiaaDashboard'); } public async showDashboard(): Promise { diff --git a/extensions/arc/src/ui/dashboards/postgres/postgresDashboard.ts b/extensions/arc/src/ui/dashboards/postgres/postgresDashboard.ts index 9951e99a8c..3c256e3d15 100644 --- a/extensions/arc/src/ui/dashboards/postgres/postgresDashboard.ts +++ b/extensions/arc/src/ui/dashboards/postgres/postgresDashboard.ts @@ -18,7 +18,7 @@ import { PostgresResourceHealthPage } from './postgresResourceHealthPage'; export class PostgresDashboard extends Dashboard { constructor(private _context: vscode.ExtensionContext, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) { - super(loc.postgresDashboard(_postgresModel.name)); + super(loc.postgresDashboard(_postgresModel.name), 'ArcPgDashboard'); } public async showDashboard(): Promise { diff --git a/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboard.ts b/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboard.ts index b33d361bfc..2efc98e1c7 100644 --- a/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboard.ts +++ b/extensions/big-data-cluster/src/bigDataCluster/dialog/bdcDashboard.ts @@ -34,7 +34,7 @@ export class BdcDashboard extends InitializingComponent { } private async createDashboard(): Promise { - this.dashboard = azdata.window.createModelViewDashboard(this.title, { alwaysShowTabs: true }); + this.dashboard = azdata.window.createModelViewDashboard(this.title, 'BdcDashboard', { alwaysShowTabs: true }); this.dashboard.registerTabs(async (modelView: azdata.ModelView) => { this.modelView = modelView; diff --git a/extensions/schema-compare/src/schemaCompareMainWindow.ts b/extensions/schema-compare/src/schemaCompareMainWindow.ts index d842965f3e..2ce221acee 100644 --- a/extensions/schema-compare/src/schemaCompareMainWindow.ts +++ b/extensions/schema-compare/src/schemaCompareMainWindow.ts @@ -75,7 +75,7 @@ export class SchemaCompareMainWindow { this.SchemaCompareActionMap[mssql.SchemaUpdateAction.Change] = loc.changeAction; this.SchemaCompareActionMap[mssql.SchemaUpdateAction.Add] = loc.addAction; - this.editor = azdata.workspace.createModelViewEditor(loc.SchemaCompareLabel, { retainContextWhenHidden: true, supportsSave: true, resourceName: schemaCompareResourceName }); + this.editor = azdata.workspace.createModelViewEditor(loc.SchemaCompareLabel, { retainContextWhenHidden: true, supportsSave: true, resourceName: schemaCompareResourceName }, 'SchemaCompareEditor'); } // schema compare can get started with three contexts for the source: diff --git a/src/sql/azdata.d.ts b/src/sql/azdata.d.ts index 2c6d704bd3..0aa84c9c74 100644 --- a/src/sql/azdata.d.ts +++ b/src/sql/azdata.d.ts @@ -2485,7 +2485,9 @@ declare module 'azdata' { export const onDidChangeToDashboard: vscode.Event; /** - * Create a new model view editor + * Create a new ModelView editor + * @param title The title shown in the editor tab + * @param options Options to configure the editor */ export function createModelViewEditor(title: string, options?: ModelViewEditorOptions): ModelViewEditor; diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index 3a9b5483ac..2a5b0f2a4e 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -513,7 +513,13 @@ declare module 'azdata' { selectTab(id: string): void; } - export function createModelViewDashboard(title: string, options?: ModelViewDashboardOptions): ModelViewDashboard; + /** + * + * @param title The title displayed in the editor tab for the dashboard + * @param name The name used to identify this dashboard in telemetry + * @param options Options to configure the dashboard + */ + export function createModelViewDashboard(title: string, name?: string, options?: ModelViewDashboardOptions): ModelViewDashboard; export interface Dialog { /** @@ -547,6 +553,16 @@ declare module 'azdata' { export function createWizard(title: string, width?: DialogWidth): Wizard; } + export namespace workspace { + /** + * Create a new ModelView editor + * @param title The title shown in the editor tab + * @param options Options to configure the editor + * @param name The name used to identify the editor in telemetry + */ + export function createModelViewEditor(title: string, options?: ModelViewEditorOptions, name?: string,): ModelViewEditor; + } + export interface DashboardTab extends Tab { /** * Toolbar of the tab, optional. diff --git a/src/sql/platform/telemetry/common/telemetryKeys.ts b/src/sql/platform/telemetry/common/telemetryKeys.ts index 3c93dcf45f..3ac83c6529 100644 --- a/src/sql/platform/telemetry/common/telemetryKeys.ts +++ b/src/sql/platform/telemetry/common/telemetryKeys.ts @@ -72,6 +72,7 @@ export enum TelemetryView { export enum TelemetryAction { Click = 'Click', - Open = 'Open' + Open = 'Open', + ModelViewDashboardOpened = 'ModelViewDashboardOpened' } diff --git a/src/sql/workbench/api/browser/mainThreadModelViewDialog.ts b/src/sql/workbench/api/browser/mainThreadModelViewDialog.ts index 3372f78435..6c2c1ecd1d 100644 --- a/src/sql/workbench/api/browser/mainThreadModelViewDialog.ts +++ b/src/sql/workbench/api/browser/mainThreadModelViewDialog.ts @@ -17,6 +17,8 @@ import { ModelViewInput, ModelViewInputModel, ModeViewSaveHandler } from 'sql/wo import * as vscode from 'vscode'; import * as azdata from 'azdata'; import { assign } from 'vs/base/common/objects'; +import { TelemetryView, TelemetryAction } from 'sql/platform/telemetry/common/telemetryKeys'; +import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; @extHostNamedCustomer(SqlMainContext.MainThreadModelViewDialog) export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape { @@ -33,7 +35,8 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape constructor( context: IExtHostContext, @IInstantiationService private _instatiationService: IInstantiationService, - @IEditorService private _editorService: IEditorService + @IEditorService private _editorService: IEditorService, + @IAdsTelemetryService private _telemetryService: IAdsTelemetryService ) { this._proxy = context.getProxy(SqlExtHostContext.ExtHostModelViewDialog); this._dialogService = new CustomDialogService(_instatiationService); @@ -43,7 +46,7 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape throw new Error('Method not implemented.'); } - public $openEditor(handle: number, modelViewId: string, title: string, options?: azdata.ModelViewEditorOptions, position?: vscode.ViewColumn): Thenable { + public $openEditor(handle: number, modelViewId: string, title: string, name?: string, options?: azdata.ModelViewEditorOptions, position?: vscode.ViewColumn): Thenable { return new Promise((resolve, reject) => { let saveHandler: ModeViewSaveHandler = options && options.supportsSave ? (h) => this.handleSave(h) : undefined; let model = new ModelViewInputModel(modelViewId, handle, saveHandler); @@ -52,7 +55,9 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape preserveFocus: true, pinned: true }; - + this._telemetryService.createActionEvent(TelemetryView.Shell, TelemetryAction.ModelViewDashboardOpened) + .withAdditionalProperties({ name: name }) + .send(); this._editorService.openEditor(input, editorOptions, position as any).then((editor) => { this._editorInputModels.set(handle, model); resolve(); diff --git a/src/sql/workbench/api/common/extHostModelViewDialog.ts b/src/sql/workbench/api/common/extHostModelViewDialog.ts index 868d90384d..17bba8dcf3 100644 --- a/src/sql/workbench/api/common/extHostModelViewDialog.ts +++ b/src/sql/workbench/api/common/extHostModelViewDialog.ts @@ -82,6 +82,7 @@ class ModelViewEditorImpl extends ModelViewPanelImpl implements azdata.workspace extension: IExtensionDescription, private _proxy: MainThreadModelViewDialogShape, private _title: string, + private _name: string, private _options: azdata.ModelViewEditorOptions ) { super('modelViewEditor', extHostModelViewDialog, extHostModelView, extension); @@ -89,7 +90,7 @@ class ModelViewEditorImpl extends ModelViewPanelImpl implements azdata.workspace } public openEditor(position?: vscode.ViewColumn): Thenable { - return this._proxy.$openEditor(this.handle, this._modelViewId, this._title, this._options, position); + return this._proxy.$openEditor(this.handle, this._modelViewId, this._title, this._name, this._options, position); } public get isDirty(): boolean { @@ -648,14 +649,16 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape { this._proxy.$closeDialog(handle); } - public createModelViewEditor(title: string, extension: IExtensionDescription, options?: azdata.ModelViewEditorOptions): azdata.workspace.ModelViewEditor { - let editor = new ModelViewEditorImpl(this, this._extHostModelView, extension, this._proxy, title, options); + public createModelViewEditor(title: string, extension: IExtensionDescription, name?: string, options?: azdata.ModelViewEditorOptions): azdata.workspace.ModelViewEditor { + name = name ?? 'ModelViewEditor'; + let editor = new ModelViewEditorImpl(this, this._extHostModelView, extension, this._proxy, title, name, options); editor.handle = this.getHandle(editor); return editor; } - public createModelViewDashboard(title: string, options: azdata.ModelViewDashboardOptions | undefined, extension: IExtensionDescription): azdata.window.ModelViewDashboard { - const editor = this.createModelViewEditor(title, extension, { supportsSave: false }) as ModelViewEditorImpl; + public createModelViewDashboard(title: string, name: string | undefined, options: azdata.ModelViewDashboardOptions | undefined, extension: IExtensionDescription): azdata.window.ModelViewDashboard { + name = name ?? 'ModelViewDashboard'; + const editor = this.createModelViewEditor(title, extension, name, { supportsSave: false }) as ModelViewEditorImpl; return new ModelViewDashboardImpl(editor, options); } diff --git a/src/sql/workbench/api/common/sqlExtHost.api.impl.ts b/src/sql/workbench/api/common/sqlExtHost.api.impl.ts index f2e5f95b9b..dc0479be07 100644 --- a/src/sql/workbench/api/common/sqlExtHost.api.impl.ts +++ b/src/sql/workbench/api/common/sqlExtHost.api.impl.ts @@ -440,8 +440,8 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp createWizard(title: string, width?: azdata.window.DialogWidth): azdata.window.Wizard { return extHostModelViewDialog.createWizard(title, width); }, - createModelViewDashboard(title: string, options?: azdata.ModelViewDashboardOptions): azdata.window.ModelViewDashboard { - return extHostModelViewDialog.createModelViewDashboard(title, options, extension); + createModelViewDashboard(title: string, name?: string, options?: azdata.ModelViewDashboardOptions): azdata.window.ModelViewDashboard { + return extHostModelViewDialog.createModelViewDashboard(title, name, options, extension); }, MessageLevel: sqlExtHostTypes.MessageLevel }; @@ -458,8 +458,8 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp const workspace: typeof azdata.workspace = { onDidOpenDashboard: extHostDashboard.onDidOpenDashboard, onDidChangeToDashboard: extHostDashboard.onDidChangeToDashboard, - createModelViewEditor(title: string, options?: azdata.ModelViewEditorOptions): azdata.workspace.ModelViewEditor { - return extHostModelViewDialog.createModelViewEditor(title, extension, options); + createModelViewEditor(title: string, options?: azdata.ModelViewEditorOptions, name?: string): azdata.workspace.ModelViewEditor { + return extHostModelViewDialog.createModelViewEditor(title, extension, name, options); } }; diff --git a/src/sql/workbench/api/common/sqlExtHost.protocol.ts b/src/sql/workbench/api/common/sqlExtHost.protocol.ts index b185e3e486..63ae3f1d66 100644 --- a/src/sql/workbench/api/common/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/common/sqlExtHost.protocol.ts @@ -804,7 +804,7 @@ export interface ExtHostModelViewDialogShape { } export interface MainThreadModelViewDialogShape extends IDisposable { - $openEditor(handle: number, modelViewId: string, title: string, options?: azdata.ModelViewEditorOptions, position?: vscode.ViewColumn): Thenable; + $openEditor(handle: number, modelViewId: string, title: string, name?: string, options?: azdata.ModelViewEditorOptions, position?: vscode.ViewColumn): Thenable; $openDialog(handle: number, dialogName?: string): Thenable; $closeDialog(handle: number): Thenable; $setDialogDetails(handle: number, details: IModelViewDialogDetails): Thenable; diff --git a/src/sql/workbench/test/electron-browser/api/mainThreadModelViewDialog.test.ts b/src/sql/workbench/test/electron-browser/api/mainThreadModelViewDialog.test.ts index 7a25ed54f7..01b3a6736b 100644 --- a/src/sql/workbench/test/electron-browser/api/mainThreadModelViewDialog.test.ts +++ b/src/sql/workbench/test/electron-browser/api/mainThreadModelViewDialog.test.ts @@ -65,7 +65,7 @@ suite('MainThreadModelViewDialog Tests', () => { let extHostContext = { getProxy: proxyType => mockExtHostModelViewDialog.object }; - mainThreadModelViewDialog = new MainThreadModelViewDialog(extHostContext, undefined, undefined); + mainThreadModelViewDialog = new MainThreadModelViewDialog(extHostContext, undefined, undefined, undefined); // Set up the mock dialog service mockDialogService = Mock.ofType(CustomDialogService, undefined);