mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Extension telemetry feature cleanup (#21779)
* Extension telemetry feature cleanup * one more
This commit is contained in:
@@ -7,6 +7,7 @@ export const serviceName = 'SQL Tools Service';
|
||||
export const providerId = 'MSSQL';
|
||||
export const serviceCrashLink = 'https://github.com/Microsoft/vscode-mssql/wiki/SqlToolsService-Known-Issues';
|
||||
export const extensionConfigSectionName = 'mssql';
|
||||
export const packageName = 'Microsoft.mssql';
|
||||
|
||||
// DATA PROTOCOL VALUES ///////////////////////////////////////////////////////////
|
||||
export const sqlProviderName = 'MSSQL';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { NotificationType, RequestType } from 'vscode-languageclient';
|
||||
import { ITelemetryEventProperties, ITelemetryEventMeasures } from './telemetry';
|
||||
import * as telemetry from '@microsoft/ads-extension-telemetry';
|
||||
import * as azdata from 'azdata';
|
||||
import { ConnectParams } from 'dataprotocol-client/lib/protocol';
|
||||
import * as mssql from 'mssql';
|
||||
@@ -24,8 +24,8 @@ export namespace TelemetryNotification {
|
||||
export class TelemetryParams {
|
||||
public params: {
|
||||
eventName: string;
|
||||
properties: ITelemetryEventProperties;
|
||||
measures: ITelemetryEventMeasures;
|
||||
properties: telemetry.TelemetryEventProperties;
|
||||
measures: telemetry.TelemetryEventMeasures;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as nls from 'vscode-nls';
|
||||
import { SqlOpsDataClient, SqlOpsFeature } from 'dataprotocol-client';
|
||||
import { ClientCapabilities, StaticFeature, RPCMessageType, ServerCapabilities } from 'vscode-languageclient';
|
||||
import { Disposable, window, QuickPickItem, QuickPickOptions } from 'vscode';
|
||||
import { Telemetry } from './telemetry';
|
||||
import { TelemetryReporter } from './telemetry';
|
||||
import * as contracts from './contracts';
|
||||
import * as azdata from 'azdata';
|
||||
import * as Utils from './utils';
|
||||
@@ -27,7 +27,7 @@ export class TelemetryFeature implements StaticFeature {
|
||||
|
||||
initialize(): void {
|
||||
this._client.onNotification(contracts.TelemetryNotification.type, e => {
|
||||
Telemetry.sendTelemetryEvent(e.params.eventName, e.params.properties, e.params.measures);
|
||||
TelemetryReporter.sendTelemetryEvent(e.params.eventName, e.params.properties, e.params.measures);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import { IconPathHelper } from './iconHelper';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { INotebookConvertService } from './notebookConvert/notebookConvertService';
|
||||
import { registerTableDesignerCommands } from './tableDesigner/tableDesigner';
|
||||
import { TelemetryReporter } from './telemetry';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -88,6 +89,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<IExten
|
||||
|
||||
registerTableDesignerCommands(appContext);
|
||||
|
||||
context.subscriptions.push(TelemetryReporter);
|
||||
return createMssqlApi(appContext, server);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as Constants from './constants';
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { getCommonLaunchArgsAndCleanupOldLogFiles, getConfigTracingLevel, getOrDownloadServer, getParallelMessageProcessingConfig, TracingLevel } from './utils';
|
||||
import { Telemetry, LanguageClientErrorHandler } from './telemetry';
|
||||
import { TelemetryReporter, LanguageClientErrorHandler } from './telemetry';
|
||||
import { SqlOpsDataClient, ClientOptions } from 'dataprotocol-client';
|
||||
import { TelemetryFeature, AgentServicesFeature, SerializationFeature, AccountFeature, SqlAssessmentServicesFeature, ProfilerFeature, TableDesignerFeature, ExecutionPlanServiceFeature } from './features';
|
||||
import { CredentialStore } from './credentialstore/credentialstore';
|
||||
@@ -69,7 +69,7 @@ export class SqlToolsServer {
|
||||
vscode.commands.registerCommand('mssql.loadCompletionExtension', (params: CompletionExtensionParams) => {
|
||||
return this.client.sendRequest(CompletionExtLoadRequest.type, params);
|
||||
});
|
||||
Telemetry.sendTelemetryEvent('startup/LanguageClientStarted', {
|
||||
TelemetryReporter.sendTelemetryEvent('startup/LanguageClientStarted', {
|
||||
installationTime: String(installationComplete - installationStart),
|
||||
processStartupTime: String(processEnd - processStart),
|
||||
totalTime: String(processEnd - installationStart),
|
||||
@@ -82,7 +82,7 @@ export class SqlToolsServer {
|
||||
await Promise.all([this.activateFeatures(context), clientReadyPromise]);
|
||||
return this.client;
|
||||
} catch (e) {
|
||||
Telemetry.sendTelemetryEvent('ServiceInitializingFailed');
|
||||
TelemetryReporter.sendTelemetryEvent('ServiceInitializingFailed');
|
||||
void vscode.window.showErrorMessage(localize('failedToStartServiceErrorMsg', "Failed to start {0}", Constants.serviceName));
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { sqlProviderName } from '../constants';
|
||||
import { generateUuid } from 'vscode-languageclient/lib/utils/uuid';
|
||||
import { ITelemetryEventProperties, Telemetry } from '../telemetry';
|
||||
import { fillServerInfo } from '../telemetry';
|
||||
import * as telemetry from '@microsoft/ads-extension-telemetry';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { getConfigPreloadDatabaseModel, setConfigPreloadDatabaseModel } from '../utils';
|
||||
const localize = nls.loadMessageBundle();
|
||||
@@ -60,11 +61,12 @@ export function registerTableDesignerCommands(appContext: AppContext) {
|
||||
}));
|
||||
}
|
||||
|
||||
async function getTelemetryInfo(context: azdata.ObjectExplorerContext, tableType: string): Promise<ITelemetryEventProperties> {
|
||||
async function getTelemetryInfo(context: azdata.ObjectExplorerContext, tableType: string): Promise<telemetry.TelemetryEventProperties> {
|
||||
const serverInfo = await azdata.connection.getServerInfo(context.connectionProfile.id);
|
||||
const telemetryInfo: ITelemetryEventProperties = {};
|
||||
Telemetry.fillServerInfo(telemetryInfo, serverInfo);
|
||||
telemetryInfo['tableType'] = tableType;
|
||||
const telemetryInfo: telemetry.TelemetryEventProperties = {
|
||||
tableType
|
||||
};
|
||||
fillServerInfo(telemetryInfo, serverInfo);
|
||||
return telemetryInfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,129 +4,30 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import TelemetryReporter from '@microsoft/ads-extension-telemetry';
|
||||
import AdsTelemetryReporter from '@microsoft/ads-extension-telemetry';
|
||||
import { ErrorAction, ErrorHandler, Message, CloseAction } from 'vscode-languageclient';
|
||||
|
||||
import * as Utils from './utils';
|
||||
import * as Constants from './constants';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { ServerInfo } from 'azdata';
|
||||
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
const packageJson = require('../package.json');
|
||||
const viewKnownIssuesAction = localize('viewKnownIssuesText', "View Known Issues");
|
||||
|
||||
export interface ITelemetryEventProperties {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface ITelemetryEventMeasures {
|
||||
[key: string]: number;
|
||||
}
|
||||
const packageInfo = vscode.extensions.getExtension(Constants.packageName)?.packageJSON;
|
||||
export const TelemetryReporter = new AdsTelemetryReporter<string, string>(packageInfo?.name, packageInfo?.version, packageInfo?.aiKey);
|
||||
|
||||
/**
|
||||
* Filters error paths to only include source files. Exported to support testing
|
||||
* Collects server information from ServerInfo to put into a
|
||||
* property bag
|
||||
*/
|
||||
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];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
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 an exception
|
||||
*/
|
||||
public static sendTelemetryEventForException(
|
||||
err: any, methodName: string, extensionConfigName: string): void {
|
||||
let stackArray: string[];
|
||||
let firstLine: string = '';
|
||||
if (err !== undefined && err.stack !== undefined) {
|
||||
stackArray = err.stack.split('\n');
|
||||
if (stackArray !== undefined && stackArray.length >= 2) {
|
||||
firstLine = stackArray[1]; // The fist line is the error message and we don't want to send that telemetry event
|
||||
firstLine = FilterErrorPath(firstLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Only adding the method name and the fist line of the stack trace. We don't add the error message because it might have PII
|
||||
this.sendTelemetryEvent('Exception', { methodName: methodName, errorLine: firstLine });
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects server information from ServerInfo to put into a
|
||||
* property bag
|
||||
*/
|
||||
public static fillServerInfo(telemetryInfo: { [key: string]: string }, serverInfo: ServerInfo): void {
|
||||
telemetryInfo['serverEdition'] = serverInfo?.serverEdition;
|
||||
telemetryInfo['serverLevel'] = serverInfo?.serverLevel;
|
||||
telemetryInfo['serverMajorVersion'] = serverInfo?.serverMajorVersion.toString();
|
||||
telemetryInfo['serverMinorVersion'] = serverInfo?.serverMinorVersion.toString();
|
||||
telemetryInfo['isCloud'] = serverInfo?.isCloud.toString();
|
||||
}
|
||||
export function fillServerInfo(telemetryInfo: { [key: string]: string }, serverInfo: ServerInfo): void {
|
||||
telemetryInfo['serverEdition'] = serverInfo?.serverEdition;
|
||||
telemetryInfo['serverLevel'] = serverInfo?.serverLevel;
|
||||
telemetryInfo['serverMajorVersion'] = serverInfo?.serverMajorVersion.toString();
|
||||
telemetryInfo['serverMinorVersion'] = serverInfo?.serverMinorVersion.toString();
|
||||
telemetryInfo['isCloud'] = serverInfo?.isCloud.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +40,7 @@ export class LanguageClientErrorHandler implements ErrorHandler {
|
||||
* @memberOf LanguageClientErrorHandler
|
||||
*/
|
||||
showOnErrorPrompt(): void {
|
||||
Telemetry.sendTelemetryEvent(Constants.serviceName + 'Crash');
|
||||
TelemetryReporter.sendTelemetryEvent(Constants.serviceName + 'Crash');
|
||||
void vscode.window.showErrorMessage(
|
||||
localize('serviceCrashMessage', "{0} component exited unexpectedly. Please restart Azure Data Studio.", Constants.serviceName),
|
||||
viewKnownIssuesAction).then(action => {
|
||||
@@ -175,5 +76,3 @@ export class LanguageClientErrorHandler implements ErrorHandler {
|
||||
return CloseAction.DoNotRestart;
|
||||
}
|
||||
}
|
||||
|
||||
Telemetry.initialize();
|
||||
|
||||
Reference in New Issue
Block a user