mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Initial work to update telemetry to use Common Schema (#6203)
* Update admin-tool-ext-win to use new ads-extension-telemetry package * Add AdsTelemetryService for sending telemetry events using the ADS Common Schema * Clean up unused import and add engineType * Address PR comments * Update private var names
This commit is contained in:
@@ -7,7 +7,7 @@ import * as nls from 'vscode-nls';
|
||||
import * as path from 'path';
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { Telemetry } from './telemetry';
|
||||
import { TelemetryReporter, TelemetryViews } from './telemetry';
|
||||
import { doubleEscapeSingleQuotes, backEscapeDoubleQuotes, getTelemetryErrorType } from './utils';
|
||||
import { ChildProcess, exec } from 'child_process';
|
||||
const localize = nls.loadMessageBundle();
|
||||
@@ -95,7 +95,7 @@ function registerCommands(context: vscode.ExtensionContext): void {
|
||||
*/
|
||||
async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
|
||||
if (!connectionContext) {
|
||||
Telemetry.sendTelemetryEventForError('NoConnectionContext', { action: 'Properties' });
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinProperties, 'NoConnectionContext');
|
||||
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForProp', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand'));
|
||||
return;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: az
|
||||
else if (connectionContext.nodeInfo) {
|
||||
nodeType = connectionContext.nodeInfo.nodeType;
|
||||
} else {
|
||||
Telemetry.sendTelemetryEventForError('NoOENode', { action: 'Properties' });
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinProperties, 'NoOENode');
|
||||
vscode.window.showErrorMessage(localize('adminToolExtWin.noOENode', 'Could not determine Object Explorer node from connectionContext : {0}', JSON.stringify(connectionContext)));
|
||||
return;
|
||||
}
|
||||
@@ -124,7 +124,7 @@ async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: az
|
||||
async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
|
||||
const action = 'GenerateScripts';
|
||||
if (!connectionContext) {
|
||||
Telemetry.sendTelemetryEventForError('NoConnectionContext', { action: action });
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinGsw, 'NoConnectionContext');
|
||||
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForGsw', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand'));
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.Ob
|
||||
*/
|
||||
async function launchSsmsDialog(action: string, connectionContext: azdata.ObjectExplorerContext): Promise<void> {
|
||||
if (!connectionContext.connectionProfile) {
|
||||
Telemetry.sendTelemetryEventForError('NoConnectionProfile', { action: action });
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinDialog, 'NoConnectionProfile');
|
||||
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionProfile', 'No connectionProfile provided from connectionContext : {0}', JSON.stringify(connectionContext)));
|
||||
return;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
|
||||
oeNode = await azdata.objectexplorer.getNode(connectionContext.connectionProfile.id, connectionContext.nodeInfo.nodePath);
|
||||
}
|
||||
else {
|
||||
Telemetry.sendTelemetryEventForError('NoOENode', { action: action });
|
||||
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinDialog, 'NoOENode');
|
||||
vscode.window.showErrorMessage(localize('adminToolExtWin.noOENode', 'Could not determine Object Explorer node from connectionContext : {0}', JSON.stringify(connectionContext)));
|
||||
return;
|
||||
}
|
||||
@@ -178,13 +178,15 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
|
||||
};
|
||||
|
||||
const args = buildSsmsMinCommandArgs(params);
|
||||
|
||||
Telemetry.sendTelemetryEvent('LaunchSsmsDialog',
|
||||
{
|
||||
action: action,
|
||||
nodeType: oeNode ? oeNode.nodeType : 'Server',
|
||||
authType: connectionContext.connectionProfile.authenticationType
|
||||
});
|
||||
TelemetryReporter.createActionEvent(
|
||||
TelemetryViews.SsmsMinDialog,
|
||||
'LaunchSsmsDialog',
|
||||
'',
|
||||
action).withAdditionalProperties(
|
||||
{
|
||||
nodeType: oeNode ? oeNode.nodeType : 'Server'
|
||||
}).withConnectionInfo(connectionContext.connectionProfile)
|
||||
.send();
|
||||
|
||||
vscode.window.setStatusBarMessage(localize('adminToolExtWin.launchingDialogStatus', 'Launching dialog...'), 3000);
|
||||
|
||||
@@ -196,11 +198,14 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
|
||||
// Process has exited so remove from map of running processes
|
||||
runningProcesses.delete(proc.pid);
|
||||
const err = stderr.toString();
|
||||
Telemetry.sendTelemetryEvent('LaunchSsmsDialogResult', {
|
||||
action: params.action,
|
||||
returnCode: execException && execException.code ? execException.code.toString() : '0',
|
||||
errorType: getTelemetryErrorType(err)
|
||||
});
|
||||
if ((execException && execException.code !== 0) || err !== '') {
|
||||
TelemetryReporter.sendErrorEvent(
|
||||
TelemetryViews.SsmsMinDialog,
|
||||
'LaunchSsmsDialogError',
|
||||
execException ? execException.code.toString() : '',
|
||||
getTelemetryErrorType(err));
|
||||
}
|
||||
|
||||
if (err !== '') {
|
||||
vscode.window.showErrorMessage(localize(
|
||||
'adminToolExtWin.ssmsMinError',
|
||||
|
||||
@@ -4,99 +4,23 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import * as vscode from 'vscode';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
import AdsTelemetryReporter from 'ads-extension-telemetry';
|
||||
|
||||
import * as Utils from './utils';
|
||||
|
||||
const packageJson = require('../package.json');
|
||||
|
||||
export interface ITelemetryEventProperties {
|
||||
[key: string]: string;
|
||||
let packageInfo = Utils.getPackageInfo(packageJson);
|
||||
|
||||
export const TelemetryReporter = new AdsTelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||
|
||||
export enum TelemetryViews {
|
||||
SsmsMinProperties = 'SsmsMinProperties',
|
||||
SsmsMinGsw = 'SsmsMinGsw',
|
||||
SsmsMinDialog = 'SsmsMinDialog'
|
||||
}
|
||||
|
||||
export interface ITelemetryEventMeasures {
|
||||
[key: string]: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters error paths to only include source files. Exported to support testing
|
||||
*/
|
||||
export function filterErrorPath(line: string): string {
|
||||
if (line) {
|
||||
let values: string[] = line.split('/out/');
|
||||
if (values.length <= 1) {
|
||||
// Didn't match expected format
|
||||
return line;
|
||||
} else {
|
||||
return values[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Telemetry {
|
||||
private static reporter: TelemetryReporter;
|
||||
private static disabled: boolean;
|
||||
|
||||
/**
|
||||
* Disable telemetry reporting
|
||||
*/
|
||||
public static disable(): void {
|
||||
this.disabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the telemetry reporter for use.
|
||||
*/
|
||||
public static initialize(): void {
|
||||
if (typeof this.reporter === 'undefined') {
|
||||
// Check if the user has opted out of telemetry
|
||||
if (!vscode.workspace.getConfiguration('telemetry').get<boolean>('enableTelemetry', true)) {
|
||||
this.disable();
|
||||
return;
|
||||
}
|
||||
|
||||
let packageInfo = Utils.getPackageInfo(packageJson);
|
||||
this.reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a telemetry event for a general error
|
||||
* @param err The error to log
|
||||
*/
|
||||
public static sendTelemetryEventForError(err: string, properties?: ITelemetryEventProperties): void {
|
||||
this.sendTelemetryEvent('Error', { error: err, ...properties });
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a telemetry event using application insights
|
||||
*/
|
||||
public static sendTelemetryEvent(
|
||||
eventName: string,
|
||||
properties?: ITelemetryEventProperties,
|
||||
measures?: ITelemetryEventMeasures): void {
|
||||
|
||||
if (typeof this.disabled === 'undefined') {
|
||||
this.disabled = false;
|
||||
}
|
||||
|
||||
if (this.disabled || typeof (this.reporter) === 'undefined') {
|
||||
// Don't do anything if telemetry is disabled
|
||||
return;
|
||||
}
|
||||
|
||||
if (!properties || typeof properties === 'undefined') {
|
||||
properties = {};
|
||||
}
|
||||
|
||||
try {
|
||||
this.reporter.sendTelemetryEvent(eventName, properties, measures);
|
||||
} catch (telemetryErr) {
|
||||
// If sending telemetry event fails ignore it so it won't break the extension
|
||||
console.error('Failed to send telemetry event. error: ' + telemetryErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Telemetry.initialize();
|
||||
|
||||
Reference in New Issue
Block a user