SelfServe - Telemetry and Localization improvements (#617)

* made selfServeTelemetry use existing functions

* removed "data" from SelfServeTelemetryType

* fixed localization bugs

* added comment
This commit is contained in:
Srinath Narayanan 2021-04-05 14:08:57 -07:00 committed by GitHub
parent b150e53814
commit 250faa5206
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 83 deletions

View File

@ -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.", "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", "DedicatedGateway": "Dedicated Gateway",
"Enable": "Enable", "Provisioned": "Provisioned",
"Disable": "Disable", "Deprovisioned": "Deprovisioned",
"LearnAboutDedicatedGateway": "Learn more about dedicated gateway.", "LearnAboutDedicatedGateway": "Learn more about dedicated gateway.",
"DeprovisioningDetailsText": "Learn more about deprovisioning the dedicated gateway.", "DeprovisioningDetailsText": "Learn more about deprovisioning the dedicated gateway.",
"DedicatedGatewayPricing": "Learn more about dedicated gateway pricing.", "DedicatedGatewayPricing": "Learn more about dedicated gateway pricing.",

View File

@ -23,9 +23,11 @@ const loadTranslationFile = async (className: string): Promise<void> => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
let translations: any; let translations: any;
try { try {
translations = await import(`../Localization/${language}/${fileName}`); translations = await import(
/* webpackChunkName: "Localization-[request]" */ `../Localization/${language}/${fileName}`
);
} catch (e) { } 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); i18n.addResourceBundle(language, className, translations.default, true);
}; };
@ -39,12 +41,12 @@ const getDescriptor = async (selfServeType: SelfServeType): Promise<SelfServeDes
switch (selfServeType) { switch (selfServeType) {
case SelfServeType.example: { case SelfServeType.example: {
const SelfServeExample = await import(/* webpackChunkName: "SelfServeExample" */ "./Example/SelfServeExample"); const SelfServeExample = await import(/* webpackChunkName: "SelfServeExample" */ "./Example/SelfServeExample");
await loadTranslations(SelfServeExample.default.name); await loadTranslations("SelfServeExample");
return new SelfServeExample.default().toSelfServeDescriptor(); return new SelfServeExample.default().toSelfServeDescriptor();
} }
case SelfServeType.sqlx: { case SelfServeType.sqlx: {
const SqlX = await import(/* webpackChunkName: "SqlX" */ "./SqlX/SqlX"); const SqlX = await import(/* webpackChunkName: "SqlX" */ "./SqlX/SqlX");
await loadTranslations(SqlX.default.name); await loadTranslations("SqlX");
return new SqlX.default().toSelfServeDescriptor(); return new SqlX.default().toSelfServeDescriptor();
} }
default: default:

View File

@ -1,69 +1,24 @@
import { sendMessage } from "../Common/MessageHandler";
import { configContext } from "../ConfigContext";
import { SelfServeMessageTypes } from "../Contracts/SelfServeContracts"; import { SelfServeMessageTypes } from "../Contracts/SelfServeContracts";
import { appInsights } from "../Shared/appInsights";
import { Action, ActionModifiers } from "../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../Shared/Telemetry/TelemetryConstants";
import { userContext } from "../UserContext"; import { trace, traceCancel, traceFailure, traceStart, traceSuccess } from "../Shared/Telemetry/TelemetryProcessor";
import { SelfServeTelemetryMessage } from "./SelfServeTypes"; import { SelfServeTelemetryMessage } from "./SelfServeTypes";
const action = Action.SelfServe; export const selfServeTrace = (data: SelfServeTelemetryMessage): void => {
trace(Action.SelfServe, ActionModifiers.Mark, data, SelfServeMessageTypes.TelemetryInfo);
export const trace = (data: SelfServeTelemetryMessage): void => {
sendSelfServeTelemetryMessage(ActionModifiers.Mark, data);
appInsights.trackEvent({ name: Action[action] }, decorateData(data, ActionModifiers.Mark));
}; };
export const traceStart = (data: SelfServeTelemetryMessage): number => { export const selfServeTraceStart = (data: SelfServeTelemetryMessage): number => {
const timestamp: number = Date.now(); return traceStart(Action.SelfServe, data, SelfServeMessageTypes.TelemetryInfo);
sendSelfServeTelemetryMessage(ActionModifiers.Start, data);
appInsights.startTrackEvent(Action[action]);
return timestamp;
}; };
export const traceSuccess = (data: SelfServeTelemetryMessage, timestamp?: number): void => { export const selfServeTraceSuccess = (data: SelfServeTelemetryMessage, timestamp?: number): void => {
sendSelfServeTelemetryMessage(ActionModifiers.Success, data, timestamp || Date.now()); traceSuccess(Action.SelfServe, data, timestamp, SelfServeMessageTypes.TelemetryInfo);
appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Success));
}; };
export const traceFailure = (data: SelfServeTelemetryMessage, timestamp?: number): void => { export const selfServeTraceFailure = (data: SelfServeTelemetryMessage, timestamp?: number): void => {
sendSelfServeTelemetryMessage(ActionModifiers.Failed, data, timestamp || Date.now()); traceFailure(Action.SelfServe, data, timestamp, SelfServeMessageTypes.TelemetryInfo);
appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Failed));
}; };
export const traceCancel = (data: SelfServeTelemetryMessage, timestamp?: number): void => { export const selfServeTraceCancel = (data: SelfServeTelemetryMessage, timestamp?: number): void => {
sendSelfServeTelemetryMessage(ActionModifiers.Cancel, data, timestamp || Date.now()); traceCancel(Action.SelfServe, data, timestamp, SelfServeMessageTypes.TelemetryInfo);
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 };
}; };

View File

@ -1,3 +1,5 @@
import { TelemetryData } from "../Shared/Telemetry/TelemetryProcessor";
interface BaseInput { interface BaseInput {
dataFieldName: string; dataFieldName: string;
errorMessage?: string; errorMessage?: string;
@ -158,8 +160,6 @@ export interface RefreshParams {
retryIntervalInMs: number; retryIntervalInMs: number;
} }
export interface SelfServeTelemetryMessage { export interface SelfServeTelemetryMessage extends TelemetryData {
selfServeClassName: string; selfServeClassName: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data?: any;
} }

View File

@ -1,5 +1,5 @@
import { IsDisplayable, OnChange, RefreshOptions, Values } from "../Decorators"; import { IsDisplayable, OnChange, RefreshOptions, Values } from "../Decorators";
import { trace } from "../SelfServeTelemetryProcessor"; import { selfServeTrace } from "../SelfServeTelemetryProcessor";
import { import {
ChoiceItem, ChoiceItem,
Description, Description,
@ -177,7 +177,7 @@ export default class SqlX extends SelfServeBaseClass {
currentValues: Map<string, SmartUiInput>, currentValues: Map<string, SmartUiInput>,
baselineValues: Map<string, SmartUiInput> baselineValues: Map<string, SmartUiInput>
): Promise<OnSaveResult> => { ): Promise<OnSaveResult> => {
trace({ selfServeClassName: "SqlX" }); selfServeTrace({ selfServeClassName: "SqlX" });
const dedicatedGatewayCurrentlyEnabled = currentValues.get("enableDedicatedGateway")?.value as boolean; const dedicatedGatewayCurrentlyEnabled = currentValues.get("enableDedicatedGateway")?.value as boolean;
const dedicatedGatewayOriginallyEnabled = baselineValues.get("enableDedicatedGateway")?.value as boolean; const dedicatedGatewayOriginallyEnabled = baselineValues.get("enableDedicatedGateway")?.value as boolean;
@ -234,7 +234,7 @@ export default class SqlX extends SelfServeBaseClass {
portalNotification: { portalNotification: {
initialize: { initialize: {
titleTKey: "CreateInitializeTitle", titleTKey: "CreateInitializeTitle",
messageTKey: "CreateInitializeTitle", messageTKey: "CreateInitializeMessage",
}, },
success: { success: {
titleTKey: "CreateSuccessTitle", titleTKey: "CreateSuccessTitle",

View File

@ -1,15 +1,25 @@
import { sendMessage } from "../../Common/MessageHandler"; import { sendMessage } from "../../Common/MessageHandler";
import { configContext } from "../../ConfigContext"; import { configContext } from "../../ConfigContext";
import { MessageTypes } from "../../Contracts/ExplorerContracts"; import { MessageTypes } from "../../Contracts/ExplorerContracts";
import { SelfServeMessageTypes } from "../../Contracts/SelfServeContracts";
import { userContext } from "../../UserContext"; import { userContext } from "../../UserContext";
import { appInsights } from "../appInsights"; import { appInsights } from "../appInsights";
import { Action, ActionModifiers } from "./TelemetryConstants"; 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({ sendMessage({
type: MessageTypes.TelemetryInfo, type: type,
data: { data: {
action: Action[action], action: Action[action],
actionModifier: actionModifier, actionModifier: actionModifier,
@ -20,10 +30,14 @@ export function trace(action: Action, actionModifier: string = ActionModifiers.M
appInsights.trackEvent({ name: Action[action] }, decorateData(data, actionModifier)); 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(); const timestamp: number = Date.now();
sendMessage({ sendMessage({
type: MessageTypes.TelemetryInfo, type: type,
data: { data: {
action: Action[action], action: Action[action],
actionModifier: ActionModifiers.Start, actionModifier: ActionModifiers.Start,
@ -36,9 +50,14 @@ export function traceStart(action: Action, data?: TelemetryData): number {
return timestamp; 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({ sendMessage({
type: MessageTypes.TelemetryInfo, type: type,
data: { data: {
action: Action[action], action: Action[action],
actionModifier: ActionModifiers.Success, actionModifier: ActionModifiers.Success,
@ -50,9 +69,14 @@ export function traceSuccess(action: Action, data?: TelemetryData, timestamp?: n
appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Success)); 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({ sendMessage({
type: MessageTypes.TelemetryInfo, type: type,
data: { data: {
action: Action[action], action: Action[action],
actionModifier: ActionModifiers.Failed, actionModifier: ActionModifiers.Failed,
@ -64,9 +88,14 @@ export function traceFailure(action: Action, data?: TelemetryData, timestamp?: n
appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Failed)); 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({ sendMessage({
type: MessageTypes.TelemetryInfo, type: type,
data: { data: {
action: Action[action], action: Action[action],
actionModifier: ActionModifiers.Cancel, actionModifier: ActionModifiers.Cancel,
@ -78,10 +107,15 @@ export function traceCancel(action: Action, data?: TelemetryData, timestamp?: nu
appInsights.stopTrackEvent(Action[action], decorateData(data, ActionModifiers.Cancel)); 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(); const validTimestamp = timestamp || Date.now();
sendMessage({ sendMessage({
type: MessageTypes.TelemetryInfo, type: type,
data: { data: {
action: Action[action], action: Action[action],
actionModifier: ActionModifiers.Open, actionModifier: ActionModifiers.Open,
@ -94,10 +128,15 @@ export function traceOpen(action: Action, data?: TelemetryData, timestamp?: numb
return validTimestamp; 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(); const validTimestamp = timestamp || Date.now();
sendMessage({ sendMessage({
type: MessageTypes.TelemetryInfo, type: type,
data: { data: {
action: Action[action], action: Action[action],
actionModifier: ActionModifiers.Mark, actionModifier: ActionModifiers.Mark,