diff --git a/src/sql/platform/telemetry/common/adsTelemetryService.ts b/src/sql/platform/telemetry/common/adsTelemetryService.ts index 9742590a7b..edcda1cb0a 100644 --- a/src/sql/platform/telemetry/common/adsTelemetryService.ts +++ b/src/sql/platform/telemetry/common/adsTelemetryService.ts @@ -8,6 +8,7 @@ import { IAdsTelemetryService, ITelemetryInfo, ITelemetryEvent, ITelemetryEventM import { ILogService } from 'vs/platform/log/common/log'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { assign } from 'vs/base/common/objects'; +import { EventName } from 'sql/platform/telemetry/common/telemetryKeys'; class TelemetryEventImpl implements ITelemetryEvent { @@ -106,7 +107,7 @@ export class AdsTelemetryService implements IAdsTelemetryService { * @param view The name of the page or item that was viewed */ public createViewEvent(view: string): ITelemetryEvent { - return new TelemetryEventImpl(this.telemetryService, this.logService, 'view', { + return new TelemetryEventImpl(this.telemetryService, this.logService, EventName.View, { view: view }); } @@ -128,7 +129,7 @@ export class AdsTelemetryService implements IAdsTelemetryService { */ public createActionEvent(view: string, action: string, target: string = '', source: string = '', durationInMs?: number): ITelemetryEvent { const measures: ITelemetryEventMeasures = durationInMs ? { durationInMs: durationInMs } : {}; - return new TelemetryEventImpl(this.telemetryService, this.logService, 'action', { + return new TelemetryEventImpl(this.telemetryService, this.logService, EventName.Action, { view: view, action: action, target: target, @@ -152,7 +153,7 @@ export class AdsTelemetryService implements IAdsTelemetryService { * @param metrics The metrics to send */ public createMetricsEvent(metrics: ITelemetryEventMeasures, groupName: string = ''): ITelemetryEvent { - return new TelemetryEventImpl(this.telemetryService, this.logService, 'metrics', { groupName: groupName }, metrics); + return new TelemetryEventImpl(this.telemetryService, this.logService, EventName.Metrics, { groupName: groupName }, metrics); } /** @@ -172,7 +173,7 @@ export class AdsTelemetryService implements IAdsTelemetryService { * @param properties Optional additional properties */ public createErrorEvent(view: string, name: string, errorCode: string = '', errorType: string = ''): ITelemetryEvent { - return new TelemetryEventImpl(this.telemetryService, this.logService, 'error', { + return new TelemetryEventImpl(this.telemetryService, this.logService, EventName.Error, { view: view, name: name, errorCode: errorCode, diff --git a/src/sql/platform/telemetry/common/telemetryKeys.ts b/src/sql/platform/telemetry/common/telemetryKeys.ts index bf9f49044b..a009d97362 100644 --- a/src/sql/platform/telemetry/common/telemetryKeys.ts +++ b/src/sql/platform/telemetry/common/telemetryKeys.ts @@ -3,7 +3,14 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export enum ModalDialogName { +export const enum EventName { + Action = 'action', + Error = 'error', + Metrics = 'metrics', + View = 'view' +} + +export const enum ModalDialogName { ErrorMessage = 'ErrorMessage', WebView = 'WebView', ConnectionAdvancedProperties = 'ConnectionAdvancedProperties', @@ -22,7 +29,7 @@ export enum ModalDialogName { CalloutDialog = 'CalloutDialog' } -export enum TelemetryView { +export const enum TelemetryView { Agent = 'Agent', AgentJobs = 'AgentJobs', AgentJobHistory = 'AgentJobHistory', @@ -30,18 +37,19 @@ export enum TelemetryView { AgentNotebookHistory = 'AgentNotebookHistory', AgentNotebooks = 'AgentNotebooks', ConnectionDialog = 'ConnectionDialog', - Shell = 'Shell', + ExtensionHost = 'ExtensionHost', ExtensionRecommendationDialog = 'ExtensionRecommendationDialog', - ResultsPanel = 'ResultsPanel', Notebook = 'Notebook', + ResultsPanel = 'ResultsPanel', + Shell = 'Shell', SqlAssessment = 'SqlAssessment' } -export enum TelemetryError { +export const enum TelemetryError { DatabaseConnectionError = 'DatabaseConnectionError' } -export enum TelemetryAction { +export const enum TelemetryAction { AddServerGroup = 'AddServerGroup', adsCommandExecuted = 'adsCommandExecuted', ConnectToServer = 'ConnectToServer', @@ -82,7 +90,7 @@ export enum TelemetryAction { SearchCompleted = 'SearchCompleted' } -export enum NbTelemetryAction { +export const enum NbTelemetryAction { RunCell = 'RunCell', RunAll = 'RunNotebook', AddCell = 'AddCell', @@ -90,7 +98,7 @@ export enum NbTelemetryAction { NewNotebookFromConnections = 'NewNotebookWithConnectionProfile' } -export enum TelemetryPropertyName { +export const enum TelemetryPropertyName { ChartMaxRowCountExceeded = 'chartMaxRowCountExceeded', ConnectionSource = 'connectionSource' } diff --git a/src/sql/workbench/contrib/telemetry/common/telemetry.contribution.ts b/src/sql/workbench/contrib/telemetry/common/telemetry.contribution.ts index f65649f129..8dd46b17b8 100644 --- a/src/sql/workbench/contrib/telemetry/common/telemetry.contribution.ts +++ b/src/sql/workbench/contrib/telemetry/common/telemetry.contribution.ts @@ -35,6 +35,7 @@ export class SqlTelemetryContribution extends Disposable implements IWorkbenchCo // Events from src\vs\editor\contrib\wordOperations\wordOperations.ts !e.commandId.startsWith('cursor') && !e.commandId.startsWith('_vscode_delegate')) { + // Note - this event is duplicated in extHostCommands to also ensure logging of all commands contributed by extensions telemetryService.sendActionEvent(TelemetryView.Shell, TelemetryAction.adsCommandExecuted, e.commandId); } })); diff --git a/src/vs/workbench/api/common/extHostCommands.ts b/src/vs/workbench/api/common/extHostCommands.ts index 12c75e0476..00c624c889 100644 --- a/src/vs/workbench/api/common/extHostCommands.ts +++ b/src/vs/workbench/api/common/extHostCommands.ts @@ -8,7 +8,7 @@ import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; import * as extHostTypeConverter from 'vs/workbench/api/common/extHostTypeConverters'; import { cloneAndChange } from 'vs/base/common/objects'; -import { MainContext, MainThreadCommandsShape, ExtHostCommandsShape, ObjectIdentifier, ICommandDto } from './extHost.protocol'; +import { MainContext, MainThreadCommandsShape, ExtHostCommandsShape, ObjectIdentifier, ICommandDto, MainThreadTelemetryShape } from './extHost.protocol'; // {{SQL CARBON EDIT}} Log extension contributed actions import { isNonEmptyArray } from 'vs/base/common/arrays'; import * as modes from 'vs/editor/common/modes'; import type * as vscode from 'vscode'; @@ -21,6 +21,7 @@ import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { ISelection } from 'vs/editor/common/core/selection'; +import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys'; // {{SQL CARBON EDIT}} Log extension contributed actions interface CommandHandler { callback: Function; @@ -40,6 +41,7 @@ export class ExtHostCommands implements ExtHostCommandsShape { private readonly _apiCommands = new Map(); private readonly _proxy: MainThreadCommandsShape; + protected readonly _mainThreadTelemetryProxy: MainThreadTelemetryShape; // {{SQL CARBON EDIT}} Log extension contributed actions private readonly _logService: ILogService; private readonly _argumentProcessors: ArgumentProcessor[]; @@ -50,6 +52,7 @@ export class ExtHostCommands implements ExtHostCommandsShape { @ILogService logService: ILogService ) { this._proxy = extHostRpc.getProxy(MainContext.MainThreadCommands); + this._mainThreadTelemetryProxy = extHostRpc.getProxy(MainContext.MainThreadTelemetry); // {{SQL CARBON EDIT}} Log extension contributed actions this._logService = logService; this.converter = new CommandsConverter( this, @@ -157,6 +160,7 @@ export class ExtHostCommands implements ExtHostCommandsShape { private async _doExecuteCommand(id: string, args: any[], retry: boolean): Promise { if (this._commands.has(id)) { + this._mainThreadTelemetryProxy.$publicLog(TelemetryKeys.EventName.Action, { properties: { action: TelemetryKeys.TelemetryAction.adsCommandExecuted, view: TelemetryKeys.TelemetryView.ExtensionHost, target: id } }); // {{SQL CARBON EDIT}} Log ext-contributed commands. Only logging here to avoid double-logging for command executions coming from core (which are already logged) // we stay inside the extension host and support // to pass any kind of parameters around return this._executeContributedCommand(id, args);