Skip to content

Commit

Permalink
feat(vscode): Improve export telemetry (#4421)
Browse files Browse the repository at this point in the history
* Add command to log telemtry

* Add log telemetry for run api service
  • Loading branch information
ccastrotrejo committed Mar 28, 2024
1 parent 8a5753a commit 0bfa095
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 37 deletions.
43 changes: 28 additions & 15 deletions apps/vs-code-designer/src/app/commands/workflows/exportLogicApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { getAccountCredentials } from '../../utils/credentials';
import { getRandomHexString } from '../../utils/fs';
import { delay } from '@azure/ms-rest-js';
import type { ServiceClientCredentials } from '@azure/ms-rest-js';
import { type IActionContext } from '@microsoft/vscode-azext-utils';
import { ExtensionCommand, ProjectName, getBaseGraphApi } from '@microsoft/vscode-extension';
import axios from 'axios';
import { writeFileSync } from 'fs';
Expand Down Expand Up @@ -75,13 +76,15 @@ class ExportEngine {
private location: string,
private addStatus: (status: string) => void,
private setFinalStatus: (status: string) => void,
private baseGraphUri: string
private baseGraphUri: string,
private context: IActionContext
) {}

public async export(): Promise<void> {
try {
this.setFinalStatus(this.finalStatus.InProgress);
this.addStatus(this.intlText.DOWNLOADING_PACKAGE);
ext.logTelemetry(this.context, 'exportLastStep', 'downloadPackage');
const flatFile = await axios.get(this.packageUrl, {
responseType: 'arraybuffer',
responseEncoding: 'binary',
Expand All @@ -90,6 +93,7 @@ class ExportEngine {
const buffer = Buffer.from(flatFile.data);
this.addStatus(this.intlText.DONE);
this.addStatus(this.intlText.UNZIP_PACKAGE);
ext.logTelemetry(this.context, 'exportLastStep', 'unzipPackage');
const zip = new AdmZip(buffer);
zip.extractAllTo(/*target path*/ this.targetDirectory, /*overwrite*/ true);
this.addStatus(this.intlText.DONE);
Expand All @@ -100,12 +104,14 @@ class ExportEngine {
if (!this.resourceGroupName || !templateExists) {
this.setFinalStatus(this.finalStatus.Succeeded);
this.addStatus(this.intlText.SUCESSFULL_EXPORTED_MESSAGE);
ext.logTelemetry(this.context, 'exportLastStep', 'workflowsExportedSuccessfully');
const uri: vscode.Uri = vscode.Uri.file(this.targetDirectory);
vscode.commands.executeCommand('vscode.openFolder', uri, { forceNewWindow: true });
return;
}

this.addStatus(this.intlText.DEPLOYING_CONNECTIONS);
ext.logTelemetry(this.context, 'exportLastStep', 'deployConnections');

const connectionsTemplate = await fse.readJSON(templatePath);
const parametersFile = await fse.readJSON(`${this.targetDirectory}/parameters.json`);
Expand All @@ -125,11 +131,13 @@ class ExportEngine {

this.setFinalStatus(this.finalStatus.Succeeded);
this.addStatus(this.intlText.SUCESSFULL_EXPORTED_MESSAGE);
ext.logTelemetry(this.context, 'exportLastStep', 'workflowsExportedSuccessfully');
const uri: vscode.Uri = vscode.Uri.file(this.targetDirectory);
vscode.commands.executeCommand('vscode.openFolder', uri, { forceNewWindow: true });
} catch (error) {
this.addStatus(localize('exportFailed', 'Export failed. {0}', error?.message ?? ''));
this.setFinalStatus(this.finalStatus.Failed);
ext.logTelemetry(this.context, 'exportError', error?.message ?? '');
}
}

Expand Down Expand Up @@ -224,6 +232,7 @@ class ExportEngine {

private async fetchConnectionKeys(output: ConnectionsDeploymentOutput): Promise<void> {
this.addStatus(this.intlText.FETCH_CONNECTION);
ext.logTelemetry(this.context, 'exportLastStep', 'retrieveConnectionKeys');
for (const connectionKey of Object.keys(output?.connections?.value || {})) {
const connectionItem = output.connections.value[connectionKey];
connectionItem.authKey = await this.getConnectionKey(connectionItem.connectionId);
Expand Down Expand Up @@ -279,6 +288,7 @@ class ExportEngine {
localSettingsFile: any
): Promise<void> {
this.addStatus(this.intlText.UPDATE_FILES);
ext.logTelemetry(this.context, 'exportLastStep', 'updatingParametersAndSettings');

const { value } = output.connections;
for (const key of Object.keys(value)) {
Expand All @@ -300,24 +310,22 @@ class ExportEngine {
}
}

export async function exportLogicApp(): Promise<void> {
const exportDialogOptions: vscode.OpenDialogOptions = {
canSelectMany: false,
openLabel: localize('selectFolder', 'Select folder'),
canSelectFiles: false,
canSelectFolders: true,
};

export async function exportLogicApp(context: IActionContext): Promise<void> {
const panelName: string = localize('export', 'Export');
const panelGroupKey = ext.webViewKey.export;
let accessToken: string;
const credentials: ServiceClientCredentials | undefined = await getAccountCredentials();
const apiVersion = '2021-03-01';

const dialogOptions: vscode.OpenDialogOptions = {
canSelectMany: false,
openLabel: 'Select folder',
canSelectFiles: false,
canSelectFolders: true,
};

const existingPanel: vscode.WebviewPanel | undefined = tryGetWebviewPanel(panelGroupKey, panelName);

accessToken = await getAuthorizationToken(credentials);
const cloudHost = await getCloudHost(credentials);
let accessToken: string;
accessToken = await getAuthorizationToken(credentials);

if (existingPanel) {
if (!existingPanel.active) {
Expand Down Expand Up @@ -369,7 +377,7 @@ export async function exportLogicApp(): Promise<void> {
break;
}
case ExtensionCommand.select_folder: {
vscode.window.showOpenDialog(dialogOptions).then((fileUri) => {
vscode.window.showOpenDialog(exportDialogOptions).then((fileUri) => {
if (fileUri && fileUri[0]) {
panel.webview.postMessage({
command: ExtensionCommand.update_export_path,
Expand Down Expand Up @@ -410,11 +418,16 @@ export async function exportLogicApp(): Promise<void> {
},
});
},
baseGraphUri
baseGraphUri,
context
);
engine.export();
break;
}
case ExtensionCommand.log_telemtry: {
ext.logTelemetry(context, message.key, message.value);
break;
}
default:
break;
}
Expand Down
6 changes: 5 additions & 1 deletion apps/vs-code-designer/src/extensionVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type DataMapperPanel from './app/commands/dataMapper/DataMapperPanel';
import type { AzureAccountTreeItemWithProjects } from './app/tree/AzureAccountTreeItemWithProjects';
import { dotnet, func, node, npm } from './constants';
import type { Site } from '@azure/arm-appservice';
import type { IAzExtOutputChannel } from '@microsoft/vscode-azext-utils';
import type { IActionContext, IAzExtOutputChannel } from '@microsoft/vscode-azext-utils';
import type { AzureHostExtensionApi } from '@microsoft/vscode-azext-utils/hostapi';
import type * as cp from 'child_process';
import { window, type ExtensionContext, type WebviewPanel } from 'vscode';
Expand Down Expand Up @@ -84,6 +84,10 @@ export namespace ext {
ext.log(errMsg);
window.showErrorMessage(errMsg);
};

export const logTelemetry = (context: IActionContext, key: string, value: string) => {
context.telemetry.properties[key] = value;
};
}

export const ExtensionCommand = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ import { type ISubscription, QueryKeys, type IIse, type IRegion } from '../../..
import { ApiService } from '../../../run-service/export';
import { updateSelectedLocation, updateSelectedSubscripton } from '../../../state/WorkflowSlice';
import type { AppDispatch, RootState } from '../../../state/store';
import { VSCodeContext } from '../../../webviewCommunication';
import { SearchableDropdown } from '../../components/searchableDropdown';
import { getDropdownPlaceholder, parseIseList, parseRegionList, parseSubscriptionsList } from './helper';
import { Text, DropdownMenuItemType } from '@fluentui/react';
import type { IDropdownOption } from '@fluentui/react';
import { isEmptyString } from '@microsoft/logic-apps-shared';
import { useEffect, useMemo } from 'react';
import { useContext, useEffect, useMemo } from 'react';
import { useIntl } from 'react-intl';
import { useQuery } from 'react-query';
import { useDispatch, useSelector } from 'react-redux';

export const InstanceSelection: React.FC = () => {
const vscode = useContext(VSCodeContext);
const workflowState = useSelector((state: RootState) => state.workflow);
const { baseUrl, accessToken, exportData, cloudHost } = workflowState;
const { selectedSubscription, selectedIse, location } = exportData;
Expand Down Expand Up @@ -88,8 +90,9 @@ export const InstanceSelection: React.FC = () => {
baseUrl,
accessToken,
cloudHost,
vscodeContext: vscode,
});
}, [accessToken, baseUrl, cloudHost]);
}, [accessToken, baseUrl, cloudHost, vscode]);

const loadSubscriptions = () => {
return apiService.getSubscriptions();
Expand Down
16 changes: 16 additions & 0 deletions apps/vs-code-react/src/app/export/navigation/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,39 @@ export const Navigation: React.FC = () => {
navigate(-1);
};

/**
* Logs the last step of the navigation.
* @param {string} pageName - The name of the page.
*/
const logLastStep = (pageName: string) => {
vscode.postMessage({
command: ExtensionCommand.log_telemtry,
key: 'lastStep',
value: pageName,
});
};

const onClickNext = () => {
const { pathname } = location;

switch (pathname) {
case `/${RouteName.export}/${RouteName.instance_selection}`: {
logLastStep(RouteName.workflows_selection);
navigate(`/${RouteName.export}/${RouteName.workflows_selection}`);
break;
}
case `/${RouteName.export}/${RouteName.workflows_selection}`: {
logLastStep(RouteName.validation);
navigate(`/${RouteName.export}/${RouteName.validation}`);
break;
}
case `/${RouteName.export}/${RouteName.validation}`: {
logLastStep(RouteName.summary);
navigate(`/${RouteName.export}/${RouteName.summary}`);
break;
}
case `/${RouteName.export}/${RouteName.summary}`: {
logLastStep(RouteName.status);
navigate(`/${RouteName.export}/${RouteName.status}`);
vscode.postMessage({
command: ExtensionCommand.export_package,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@ import { QueryKeys } from '../../../run-service';
import { ApiService } from '../../../run-service/export';
import { updateManagedConnections } from '../../../state/WorkflowSlice';
import type { AppDispatch, RootState } from '../../../state/store';
import { VSCodeContext } from '../../../webviewCommunication';
import { SearchableDropdown } from '../../components/searchableDropdown';
import { parseResourceGroupsData } from './helper';
import { NewResourceGroup } from './newResourceGroup';
import { Checkbox, Text } from '@fluentui/react';
import type { IDropdownOption } from '@fluentui/react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useContext, useCallback, useEffect, useMemo, useState } from 'react';
import { useIntl } from 'react-intl';
import { useQuery } from 'react-query';
import { useDispatch, useSelector } from 'react-redux';

export const ManagedConnections: React.FC = () => {
const intl = useIntl();
const vscode = useContext(VSCodeContext);
const dispatch: AppDispatch = useDispatch();
const [isConnectionsChecked, setConnectionsChecked] = useState(false);
const workflowState = useSelector((state: RootState) => state.workflow);
Expand Down Expand Up @@ -64,8 +66,9 @@ export const ManagedConnections: React.FC = () => {
baseUrl,
accessToken,
cloudHost,
vscodeContext: vscode,
});
}, [accessToken, baseUrl, cloudHost]);
}, [accessToken, baseUrl, cloudHost, vscode]);

const loadResourceGroups = () => {
return apiService.getResourceGroups(selectedSubscription);
Expand Down
3 changes: 2 additions & 1 deletion apps/vs-code-react/src/app/export/summary/summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ export const Summary: React.FC = () => {
baseUrl,
accessToken,
cloudHost,
vscodeContext: vscode,
});
}, [accessToken, baseUrl, cloudHost]);
}, [accessToken, baseUrl, cloudHost, vscode]);

const exportWorkflows = () => {
return apiService.exportWorkflows(selectedWorkflows, selectedSubscription, location, selectedAdvanceOptions);
Expand Down
7 changes: 5 additions & 2 deletions apps/vs-code-react/src/app/export/validation/validation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import type { IValidationData } from '../../../run-service';
import { ApiService } from '../../../run-service/export';
import { updateValidationState } from '../../../state/WorkflowSlice';
import type { AppDispatch, RootState } from '../../../state/store';
import { VSCodeContext } from '../../../webviewCommunication';
import { ReviewList } from '../../components/reviewList/reviewList';
import { getOverallValidationStatus, parseValidationData } from './helper';
import { MessageBar, MessageBarType, Text } from '@fluentui/react';
import { useMemo } from 'react';
import { useContext, useMemo } from 'react';
import { useIntl } from 'react-intl';
import { useQuery } from 'react-query';
import { useDispatch, useSelector } from 'react-redux';

export const Validation: React.FC = () => {
const vscode = useContext(VSCodeContext);
const workflowState = useSelector((state: RootState) => state.workflow);
const { baseUrl, accessToken, exportData, cloudHost } = workflowState;
const { selectedWorkflows, location, selectedSubscription, selectedAdvanceOptions } = exportData;
Expand Down Expand Up @@ -42,8 +44,9 @@ export const Validation: React.FC = () => {
baseUrl,
accessToken,
cloudHost,
vscodeContext: vscode,
});
}, [accessToken, baseUrl, cloudHost]);
}, [accessToken, baseUrl, cloudHost, vscode]);

const validateWorkflows = () => {
return apiService.validateWorkflows(selectedWorkflows, selectedSubscription, location, selectedAdvanceOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { WorkflowsList, SelectedWorkflowsList } from '../../../run-service'
import { ApiService } from '../../../run-service/export/index';
import { updateSelectedWorkFlows } from '../../../state/WorkflowSlice';
import type { AppDispatch, RootState } from '../../../state/store';
import { VSCodeContext } from '../../../webviewCommunication';
import { AdvancedOptions } from './advancedOptions';
import { Filters } from './filters';
import {
Expand All @@ -19,12 +20,13 @@ import { SelectedList } from './selectedList';
import { Separator, ShimmeredDetailsList, Text, SelectionMode, Selection, MessageBar, MessageBarType } from '@fluentui/react';
import type { IDropdownOption } from '@fluentui/react';
import { isNullOrUndefined } from '@microsoft/logic-apps-shared';
import { useMemo, useRef, useState, useEffect } from 'react';
import { useMemo, useRef, useState, useEffect, useContext } from 'react';
import { useIntl } from 'react-intl';
import { useQuery } from 'react-query';
import { useDispatch, useSelector } from 'react-redux';

export const WorkflowsSelection: React.FC = () => {
const vscode = useContext(VSCodeContext);
const workflowState = useSelector((state: RootState) => state.workflow);
const { baseUrl, accessToken, exportData, cloudHost } = workflowState;
const { selectedSubscription, selectedIse, selectedWorkflows, location } = exportData;
Expand Down Expand Up @@ -91,8 +93,9 @@ export const WorkflowsSelection: React.FC = () => {
baseUrl,
accessToken,
cloudHost,
vscodeContext: vscode,
});
}, [accessToken, baseUrl, cloudHost]);
}, [accessToken, baseUrl, cloudHost, vscode]);

const loadWorkflows = () => {
return apiService.getWorkflows(selectedSubscription, selectedIse, location);
Expand Down
Loading

0 comments on commit 0bfa095

Please sign in to comment.