From 250faa52064de277a7adf6b9738f4ee720db8e9c Mon Sep 17 00:00:00 2001 From: Srinath Narayanan Date: Mon, 5 Apr 2021 14:08:57 -0700 Subject: [PATCH] SelfServe - Telemetry and Localization improvements (#617) * made selfServeTelemetry use existing functions * removed "data" from SelfServeTelemetryType * fixed localization bugs * added comment --- src/Localization/en/SqlX.json | 4 +- src/SelfServe/SelfServe.tsx | 10 +-- src/SelfServe/SelfServeTelemetryProcessor.ts | 67 ++++--------------- src/SelfServe/SelfServeTypes.ts | 6 +- src/SelfServe/SqlX/SqlX.tsx | 6 +- src/Shared/Telemetry/TelemetryProcessor.ts | 69 +++++++++++++++----- 6 files changed, 79 insertions(+), 83 deletions(-) diff --git a/src/Localization/en/SqlX.json b/src/Localization/en/SqlX.json index 465cba248..3c1d81dac 100644 --- a/src/Localization/en/SqlX.json +++ b/src/Localization/en/SqlX.json @@ -1,8 +1,8 @@ { "DedicatedGatewayDescription": "Provision a dedicated gateway cluster for your Azure Cosmos DB account. A dedicated gateway is compute that is a front-end to data in your Azure Cosmos DB account. Your dedicated gateway automatically includes the integrated cache, which can improve read performance.", "DedicatedGateway": "Dedicated Gateway", - "Enable": "Enable", - "Disable": "Disable", + "Provisioned": "Provisioned", + "Deprovisioned": "Deprovisioned", "LearnAboutDedicatedGateway": "Learn more about dedicated gateway.", "DeprovisioningDetailsText": "Learn more about deprovisioning the dedicated gateway.", "DedicatedGatewayPricing": "Learn more about dedicated gateway pricing.", diff --git a/src/SelfServe/SelfServe.tsx b/src/SelfServe/SelfServe.tsx index 062d07289..7fed9c7ab 100644 --- a/src/SelfServe/SelfServe.tsx +++ b/src/SelfServe/SelfServe.tsx @@ -23,9 +23,11 @@ const loadTranslationFile = async (className: string): Promise => { // eslint-disable-next-line @typescript-eslint/no-explicit-any let translations: any; try { - translations = await import(`../Localization/${language}/${fileName}`); + translations = await import( + /* webpackChunkName: "Localization-[request]" */ `../Localization/${language}/${fileName}` + ); } catch (e) { - translations = await import(`../Localization/en/${fileName}`); + translations = await import(/* webpackChunkName: "Localization-en-[request]" */ `../Localization/en/${fileName}`); } i18n.addResourceBundle(language, className, translations.default, true); }; @@ -39,12 +41,12 @@ const getDescriptor = async (selfServeType: SelfServeType): Promise { - sendSelfServeTelemetryMessage(ActionModifiers.Mark, data); - appInsights.trackEvent({ name: Action[action] }, decorateData(data, ActionModifiers.Mark)); +export const selfServeTrace = (data: SelfServeTelemetryMessage): void => { + trace(Action.SelfServe, ActionModifiers.Mark, data, SelfServeMessageTypes.TelemetryInfo); }; -export const traceStart = (data: SelfServeTelemetryMessage): number => { - const timestamp: number = Date.now(); - sendSelfServeTelemetryMessage(ActionModifiers.Start, data); - appInsights.startTrackEvent(Action[action]); - return timestamp; +export const selfServeTraceStart = (data: SelfServeTelemetryMessage): number => { + return traceStart(Action.SelfServe, data, SelfServeMessageTypes.TelemetryInfo); }; -export const traceSuccess = (data: SelfServeTelemetryMessage, timestamp?: number): void => { - sendSelfServeTelemetryMessage(ActionModifiers.Success, data, timestamp || Date.now()); - appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Success)); +export const selfServeTraceSuccess = (data: SelfServeTelemetryMessage, timestamp?: number): void => { + traceSuccess(Action.SelfServe, data, timestamp, SelfServeMessageTypes.TelemetryInfo); }; -export const traceFailure = (data: SelfServeTelemetryMessage, timestamp?: number): void => { - sendSelfServeTelemetryMessage(ActionModifiers.Failed, data, timestamp || Date.now()); - appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Failed)); +export const selfServeTraceFailure = (data: SelfServeTelemetryMessage, timestamp?: number): void => { + traceFailure(Action.SelfServe, data, timestamp, SelfServeMessageTypes.TelemetryInfo); }; -export const traceCancel = (data: SelfServeTelemetryMessage, timestamp?: number): void => { - sendSelfServeTelemetryMessage(ActionModifiers.Cancel, data, timestamp || Date.now()); - appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Cancel)); -}; - -const sendSelfServeTelemetryMessage = ( - actionModifier: string, - data: SelfServeTelemetryMessage, - timeStamp?: number -): void => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const dataToSend: any = { - type: SelfServeMessageTypes.TelemetryInfo, - data: { - action: Action[action], - actionModifier: actionModifier, - data: JSON.stringify(decorateData(data)), - }, - }; - if (timeStamp) { - dataToSend.data.timeStamp = timeStamp; - } - sendMessage(dataToSend); -}; - -const decorateData = (data: SelfServeTelemetryMessage, actionModifier?: string) => { - return { - databaseAccountName: userContext.databaseAccount?.name, - defaultExperience: userContext.defaultExperience, - authType: userContext.authType, - subscriptionId: userContext.subscriptionId, - platform: configContext.platform, - env: process.env.NODE_ENV, - actionModifier, - ...data, - } as { [key: string]: string }; +export const selfServeTraceCancel = (data: SelfServeTelemetryMessage, timestamp?: number): void => { + traceCancel(Action.SelfServe, data, timestamp, SelfServeMessageTypes.TelemetryInfo); }; diff --git a/src/SelfServe/SelfServeTypes.ts b/src/SelfServe/SelfServeTypes.ts index a86b74c04..d8393ba19 100644 --- a/src/SelfServe/SelfServeTypes.ts +++ b/src/SelfServe/SelfServeTypes.ts @@ -1,3 +1,5 @@ +import { TelemetryData } from "../Shared/Telemetry/TelemetryProcessor"; + interface BaseInput { dataFieldName: string; errorMessage?: string; @@ -158,8 +160,6 @@ export interface RefreshParams { retryIntervalInMs: number; } -export interface SelfServeTelemetryMessage { +export interface SelfServeTelemetryMessage extends TelemetryData { selfServeClassName: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - data?: any; } diff --git a/src/SelfServe/SqlX/SqlX.tsx b/src/SelfServe/SqlX/SqlX.tsx index 41d855fee..b27f69e69 100644 --- a/src/SelfServe/SqlX/SqlX.tsx +++ b/src/SelfServe/SqlX/SqlX.tsx @@ -1,5 +1,5 @@ import { IsDisplayable, OnChange, RefreshOptions, Values } from "../Decorators"; -import { trace } from "../SelfServeTelemetryProcessor"; +import { selfServeTrace } from "../SelfServeTelemetryProcessor"; import { ChoiceItem, Description, @@ -177,7 +177,7 @@ export default class SqlX extends SelfServeBaseClass { currentValues: Map, baselineValues: Map ): Promise => { - trace({ selfServeClassName: "SqlX" }); + selfServeTrace({ selfServeClassName: "SqlX" }); const dedicatedGatewayCurrentlyEnabled = currentValues.get("enableDedicatedGateway")?.value as boolean; const dedicatedGatewayOriginallyEnabled = baselineValues.get("enableDedicatedGateway")?.value as boolean; @@ -234,7 +234,7 @@ export default class SqlX extends SelfServeBaseClass { portalNotification: { initialize: { titleTKey: "CreateInitializeTitle", - messageTKey: "CreateInitializeTitle", + messageTKey: "CreateInitializeMessage", }, success: { titleTKey: "CreateSuccessTitle", diff --git a/src/Shared/Telemetry/TelemetryProcessor.ts b/src/Shared/Telemetry/TelemetryProcessor.ts index e261f3635..e7280f147 100644 --- a/src/Shared/Telemetry/TelemetryProcessor.ts +++ b/src/Shared/Telemetry/TelemetryProcessor.ts @@ -1,15 +1,25 @@ import { sendMessage } from "../../Common/MessageHandler"; import { configContext } from "../../ConfigContext"; import { MessageTypes } from "../../Contracts/ExplorerContracts"; +import { SelfServeMessageTypes } from "../../Contracts/SelfServeContracts"; import { userContext } from "../../UserContext"; import { appInsights } from "../appInsights"; import { Action, ActionModifiers } from "./TelemetryConstants"; -type TelemetryData = { [key: string]: unknown }; +// Right now, the ExplorerContracts has MessageTypes as a numeric enum (TelemetryInfo = 0) while the SelfServeContracts +// has MessageTypes as a string enum (TelemetryInfo = "TelemetryInfo"). We should move to string enums for all use cases. +type TelemetryType = MessageTypes.TelemetryInfo | SelfServeMessageTypes.TelemetryInfo; -export function trace(action: Action, actionModifier: string = ActionModifiers.Mark, data: TelemetryData = {}): void { +export type TelemetryData = { [key: string]: unknown }; + +export function trace( + action: Action, + actionModifier: string = ActionModifiers.Mark, + data: TelemetryData = {}, + type: TelemetryType = MessageTypes.TelemetryInfo +): void { sendMessage({ - type: MessageTypes.TelemetryInfo, + type: type, data: { action: Action[action], actionModifier: actionModifier, @@ -20,10 +30,14 @@ export function trace(action: Action, actionModifier: string = ActionModifiers.M appInsights.trackEvent({ name: Action[action] }, decorateData(data, actionModifier)); } -export function traceStart(action: Action, data?: TelemetryData): number { +export function traceStart( + action: Action, + data?: TelemetryData, + type: TelemetryType = MessageTypes.TelemetryInfo +): number { const timestamp: number = Date.now(); sendMessage({ - type: MessageTypes.TelemetryInfo, + type: type, data: { action: Action[action], actionModifier: ActionModifiers.Start, @@ -36,9 +50,14 @@ export function traceStart(action: Action, data?: TelemetryData): number { return timestamp; } -export function traceSuccess(action: Action, data?: TelemetryData, timestamp?: number): void { +export function traceSuccess( + action: Action, + data?: TelemetryData, + timestamp?: number, + type: TelemetryType = MessageTypes.TelemetryInfo +): void { sendMessage({ - type: MessageTypes.TelemetryInfo, + type: type, data: { action: Action[action], actionModifier: ActionModifiers.Success, @@ -50,9 +69,14 @@ export function traceSuccess(action: Action, data?: TelemetryData, timestamp?: n appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Success)); } -export function traceFailure(action: Action, data?: TelemetryData, timestamp?: number): void { +export function traceFailure( + action: Action, + data?: TelemetryData, + timestamp?: number, + type: TelemetryType = MessageTypes.TelemetryInfo +): void { sendMessage({ - type: MessageTypes.TelemetryInfo, + type: type, data: { action: Action[action], actionModifier: ActionModifiers.Failed, @@ -64,9 +88,14 @@ export function traceFailure(action: Action, data?: TelemetryData, timestamp?: n appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Failed)); } -export function traceCancel(action: Action, data?: TelemetryData, timestamp?: number): void { +export function traceCancel( + action: Action, + data?: TelemetryData, + timestamp?: number, + type: TelemetryType = MessageTypes.TelemetryInfo +): void { sendMessage({ - type: MessageTypes.TelemetryInfo, + type: type, data: { action: Action[action], actionModifier: ActionModifiers.Cancel, @@ -78,10 +107,15 @@ export function traceCancel(action: Action, data?: TelemetryData, timestamp?: nu appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Cancel)); } -export function traceOpen(action: Action, data?: TelemetryData, timestamp?: number): number { +export function traceOpen( + action: Action, + data?: TelemetryData, + timestamp?: number, + type: TelemetryType = MessageTypes.TelemetryInfo +): number { const validTimestamp = timestamp || Date.now(); sendMessage({ - type: MessageTypes.TelemetryInfo, + type: type, data: { action: Action[action], actionModifier: ActionModifiers.Open, @@ -94,10 +128,15 @@ export function traceOpen(action: Action, data?: TelemetryData, timestamp?: numb return validTimestamp; } -export function traceMark(action: Action, data?: TelemetryData, timestamp?: number): number { +export function traceMark( + action: Action, + data?: TelemetryData, + timestamp?: number, + type: TelemetryType = MessageTypes.TelemetryInfo +): number { const validTimestamp = timestamp || Date.now(); sendMessage({ - type: MessageTypes.TelemetryInfo, + type: type, data: { action: Action[action], actionModifier: ActionModifiers.Mark,