mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-16 01:25:36 -05:00
Added data points for Table Designer (#18182)
* added server infor and metrics for table designer * update generate script * pr comments * format more files * pr comments * make changes to core * remove unused imports * add server info * revert enum change and add publish event * format doc * nitpicks * remove os version * remove modifier from telemetry info * remove error message
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import { DesignerViewModel, DesignerEdit, DesignerComponentInput, DesignerView, DesignerTab, DesignerDataPropertyInfo, DropDownProperties, DesignerTableProperties, DesignerEditProcessedEventArgs, DesignerAction, DesignerStateChangedEventArgs } from 'sql/workbench/browser/designer/interfaces';
|
||||
import { DesignerViewModel, DesignerEdit, DesignerComponentInput, DesignerView, DesignerTab, DesignerDataPropertyInfo, DropDownProperties, DesignerTableProperties, DesignerEditProcessedEventArgs, DesignerAction, DesignerStateChangedEventArgs, DesignerEditPath } from 'sql/workbench/browser/designer/interfaces';
|
||||
import { TableDesignerProvider } from 'sql/workbench/services/tableDesigner/common/interface';
|
||||
import { localize } from 'vs/nls';
|
||||
import { designers } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
@@ -14,6 +14,8 @@ import { deepClone, equals } from 'vs/base/common/objects';
|
||||
import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TableDesignerPublishDialogResult, TableDesignerPublishDialog } from 'sql/workbench/services/tableDesigner/browser/tableDesignerPublishDialog';
|
||||
import { IAdsTelemetryService, ITelemetryEventProperties } from 'sql/platform/telemetry/common/telemetry';
|
||||
import { TelemetryAction, TelemetryView } from 'sql/platform/telemetry/common/telemetryKeys';
|
||||
|
||||
export class TableDesignerComponentInput implements DesignerComponentInput {
|
||||
|
||||
@@ -31,9 +33,15 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
|
||||
public readonly onEditProcessed: Event<DesignerEditProcessedEventArgs> = this._onEditProcessed.event;
|
||||
public readonly onStateChange: Event<DesignerStateChangedEventArgs> = this._onStateChange.event;
|
||||
|
||||
private readonly designerEditTypeDisplayValue: { [key: number]: string } = {
|
||||
0: 'Add', 1: 'Remove', 2: 'Update'
|
||||
};
|
||||
|
||||
constructor(private readonly _provider: TableDesignerProvider,
|
||||
private _tableInfo: azdata.designers.TableInfo,
|
||||
private _telemetryInfo: ITelemetryEventProperties,
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
@IAdsTelemetryService readonly _adsTelemetryService: IAdsTelemetryService,
|
||||
@IQueryEditorService private readonly _queryEditorService: IQueryEditorService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService) {
|
||||
}
|
||||
@@ -63,6 +71,11 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
|
||||
}
|
||||
|
||||
processEdit(edit: DesignerEdit): void {
|
||||
const telemetryInfo = this.createTelemetryInfo();
|
||||
telemetryInfo.tableObjectType = this.getObjectTypeFromPath(edit.path);
|
||||
const editAction = this._adsTelemetryService.createActionEvent(TelemetryView.TableDesigner,
|
||||
this.designerEditTypeDisplayValue[edit.type]).withAdditionalProperties(telemetryInfo);
|
||||
const startTime = new Date().getTime();
|
||||
this.updateState(this.valid, this.dirty, 'processEdit');
|
||||
this._provider.processTableEdit(this._tableInfo, edit).then(
|
||||
result => {
|
||||
@@ -76,10 +89,15 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
|
||||
errors: result.errors
|
||||
}
|
||||
});
|
||||
editAction.withAdditionalMeasurements({
|
||||
'elapsedTimeMs': new Date().getTime() - startTime
|
||||
}).send();
|
||||
},
|
||||
error => {
|
||||
this._notificationService.error(localize('tableDesigner.errorProcessingEdit', "An error occured while processing the change: {0}", error?.message ?? error));
|
||||
this.updateState(this.valid, this.dirty);
|
||||
this._adsTelemetryService.createErrorEvent(TelemetryView.TableDesigner,
|
||||
this.designerEditTypeDisplayValue[edit.type]).withAdditionalProperties(telemetryInfo).send();
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -90,35 +108,49 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
|
||||
message: localize('tableDesigner.generatingScript', "Generating script..."),
|
||||
sticky: true
|
||||
});
|
||||
const telemetryInfo = this.createTelemetryInfo();
|
||||
const generateScriptEvent = this._adsTelemetryService.createActionEvent(TelemetryView.TableDesigner, TelemetryAction.GenerateScript).withAdditionalProperties(telemetryInfo);
|
||||
const startTime = new Date().getTime();
|
||||
try {
|
||||
this.updateState(this.valid, this.dirty, 'generateScript');
|
||||
const script = await this._provider.generateScript(this._tableInfo);
|
||||
this._queryEditorService.newSqlEditor({ initalContent: script });
|
||||
this.updateState(this.valid, this.dirty);
|
||||
notificationHandle.updateMessage(localize('tableDesigner.generatingScriptCompleted', "Script generated."));
|
||||
generateScriptEvent.withAdditionalMeasurements({
|
||||
'elapsedTimeMs': new Date().getTime() - startTime
|
||||
}).send();
|
||||
} catch (error) {
|
||||
notificationHandle.updateSeverity(Severity.Error);
|
||||
notificationHandle.updateMessage(localize('tableDesigner.generateScriptError', "An error occured while generating the script: {0}", error?.message ?? error));
|
||||
this.updateState(this.valid, this.dirty);
|
||||
this._adsTelemetryService.createErrorEvent(TelemetryView.TableDesigner, TelemetryAction.GenerateScript).withAdditionalProperties(telemetryInfo).send();
|
||||
}
|
||||
}
|
||||
|
||||
async publishChanges(): Promise<void> {
|
||||
const telemetryInfo = this.createTelemetryInfo();
|
||||
const publishEvent = this._adsTelemetryService.createActionEvent(TelemetryView.TableDesigner, TelemetryAction.PublishChanges).withAdditionalProperties(telemetryInfo);
|
||||
const saveNotificationHandle = this._notificationService.notify({
|
||||
severity: Severity.Info,
|
||||
message: localize('tableDesigner.savingChanges', "Saving table designer changes..."),
|
||||
sticky: true
|
||||
});
|
||||
const startTime = new Date().getTime();
|
||||
try {
|
||||
this.updateState(this.valid, this.dirty, 'save');
|
||||
await this._provider.publishChanges(this._tableInfo);
|
||||
this._originalViewModel = this._viewModel;
|
||||
this.updateState(true, false);
|
||||
saveNotificationHandle.updateMessage(localize('tableDesigner.publishChangeSuccess', "The changes have been successfully published."));
|
||||
publishEvent.withAdditionalMeasurements({
|
||||
'elapsedTimeMs': new Date().getTime() - startTime
|
||||
}).send();
|
||||
} catch (error) {
|
||||
saveNotificationHandle.updateSeverity(Severity.Error);
|
||||
saveNotificationHandle.updateMessage(localize('tableDesigner.publishChangeError', "An error occured while publishing changes: {0}", error?.message ?? error));
|
||||
this.updateState(this.valid, this.dirty);
|
||||
this._adsTelemetryService.createErrorEvent(TelemetryView.TableDesigner, TelemetryAction.PublishChanges).withAdditionalProperties(telemetryInfo).send();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,4 +612,36 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
|
||||
this._viewModel[property] = {};
|
||||
}
|
||||
}
|
||||
|
||||
private createTelemetryInfo(): ITelemetryEventProperties {
|
||||
let telemetryInfo = {
|
||||
provider: this._provider.providerId,
|
||||
isNewTable: this._tableInfo.isNewTable,
|
||||
};
|
||||
Object.assign(telemetryInfo, this._telemetryInfo);
|
||||
return telemetryInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 'Add' scenario
|
||||
a. ['propertyName1']. Example: add a column to the columns property: ['columns'].
|
||||
b. ['propertyName1',index-1,'propertyName2']. Example: add a column mapping to the first foreign key: ['foreignKeys',0,'mappings'].
|
||||
2. 'Update' scenario
|
||||
a. ['propertyName1']. Example: update the name of the table: ['name'].
|
||||
b. ['propertyName1',index-1,'propertyName2']. Example: update the name of a column: ['columns',0,'name'].
|
||||
c. ['propertyName1',index-1,'propertyName2',index-2,'propertyName3']. Example: update the source column of an entry in a foreign key's column mapping table: ['foreignKeys',0,'mappings',0,'source'].
|
||||
3. 'Remove' scenario
|
||||
a. ['propertyName1',index-1]. Example: remove a column from the columns property: ['columns',0'].
|
||||
b. ['propertyName1',index-1,'proper
|
||||
The return values would be the propertyNames followed by slashes in level order. Eg.: propertyName1/propertyName2/...
|
||||
*/
|
||||
private getObjectTypeFromPath(path: DesignerEditPath): string {
|
||||
let typeArray = [];
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
if (i % 2 === 0) {
|
||||
typeArray.push(path[i]);
|
||||
}
|
||||
}
|
||||
return typeArray.join('/');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user