Skip to content

Commit dc5329f

Browse files
authored
feat: usage analytics in code-snippet (#285)
1 parent fcb8b4b commit dc5329f

File tree

10 files changed

+498
-238
lines changed

10 files changed

+498
-238
lines changed

packages/backend/.nycrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"exclude": [
55
"src/logger/*.ts",
66
"src/panels/*.ts",
7-
"src/swa-tracker/*.ts",
7+
"src/usage-report/*.ts",
88
"src/webSocketServer/*.ts",
99
"src/output-channel-log.ts",
1010
"src/youi-adapter.ts"

packages/backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
},
115115
"dependencies": {
116116
"@sap-devx/webview-rpc": "0.3.1",
117-
"@sap/swa-for-sapbas-vsx": "1.2.15",
117+
"@sap/swa-for-sapbas-vsx": "2.0.4",
118118
"@vscode-logging/logger": "1.2.3",
119119
"code-snippet-frontend": "^1.3.2",
120120
"fs-extra": "9.1.0",

packages/backend/src/code-snippet.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { IRpc } from "@sap-devx/webview-rpc/out.ext/rpc-common";
66
import Generator = require("yeoman-generator");
77
import { IChildLogger } from "@vscode-logging/logger";
88
import TerminalAdapter = require("yeoman-environment/lib/adapter");
9-
import { SWA } from "./swa-tracker/swa-tracker-wrapper";
9+
import { AnalyticsWrapper } from "./usage-report/usage-analytics-wrapper";
1010
import messages from "./messages";
1111
import { State } from "./utils";
1212

@@ -206,7 +206,10 @@ export class CodeSnippet {
206206
const questions: any[] = await this.createCodeSnippetQuestions();
207207
this.currentQuestions = questions;
208208
const normalizedQuestions = this.normalizeFunctions(questions);
209-
SWA.updateSnippetStarted(this.uiOptions.messages.title, this.logger);
209+
AnalyticsWrapper.updateSnippetStarted(
210+
this.uiOptions.messages.title,
211+
this.logger
212+
);
210213
const response: any = await this.rpc.invoke("showPrompt", [
211214
normalizedQuestions,
212215
]);
@@ -253,7 +256,7 @@ export class CodeSnippet {
253256
private onSuccess(showDoneMessage: boolean, snippetName: string) {
254257
const message = `'${snippetName}' snippet has been created.`;
255258
this.logger.debug("done running code-snippet! " + message);
256-
SWA.updateSnippetEnded(snippetName, true, this.logger);
259+
AnalyticsWrapper.updateSnippetEnded(snippetName, true, this.logger);
257260
if (showDoneMessage) {
258261
this.appEvents.doSnippeDone(true, message);
259262
}
@@ -267,7 +270,12 @@ export class CodeSnippet {
267270
) {
268271
const messagePrefix = `${snippetrName} snippet failed.`;
269272
const errorMessage: string = this.logError(error, messagePrefix);
270-
SWA.updateSnippetEnded(snippetrName, false, this.logger, errorMessage);
273+
AnalyticsWrapper.updateSnippetEnded(
274+
snippetrName,
275+
false,
276+
this.logger,
277+
errorMessage
278+
);
271279
if (showDoneMessage) {
272280
this.appEvents.doSnippeDone(false, errorMessage);
273281
}

packages/backend/src/extension.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
} from "./logger/logger-wrapper";
66
import { CodeSnippetPanel } from "./panels/CodeSnippetPanel";
77
import { AbstractWebviewPanel } from "./panels/AbstractWebviewPanel";
8-
import { SWA } from "./swa-tracker/swa-tracker-wrapper";
8+
import { AnalyticsWrapper } from "./usage-report/usage-analytics-wrapper";
99

1010
let extContext: vscode.ExtensionContext;
1111
let codeSnippetPanel: CodeSnippetPanel;
@@ -15,7 +15,7 @@ export function activate(context: vscode.ExtensionContext): void {
1515

1616
try {
1717
createExtensionLoggerAndSubscribeToLogSettingsChanges(context);
18-
SWA.createSWATracker(getLogger());
18+
AnalyticsWrapper.createTracker(getLogger());
1919
} catch (error: any) {
2020
console.error(
2121
"Extension activation failed due to Logger configuration failure:",

packages/backend/src/swa-tracker/swa-tracker-wrapper.ts

Lines changed: 0 additions & 151 deletions
This file was deleted.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import {
2+
initTelemetrySettings,
3+
BASClientFactory,
4+
BASTelemetryClient,
5+
} from "@sap/swa-for-sapbas-vsx";
6+
import { IChildLogger } from "@vscode-logging/logger";
7+
import { join } from "path";
8+
import { readFileSync } from "fs";
9+
10+
/**
11+
* A Simple Wrapper for reporting usage analytics
12+
*/
13+
export class AnalyticsWrapper {
14+
// Event types used by Application Wizard
15+
private static readonly EVENT_TYPES = {
16+
SNIPPET_CREATION_STARTED: "Snippet creation started",
17+
SNIPPET_CREATION_SUCCESSFULLY: "Snippet creation successfully",
18+
SNIPPET_CREATION_FAILED: "Snippet creation failed",
19+
};
20+
21+
private static startTime: number = Date.now();
22+
23+
/**
24+
* Note the use of a getter function so the value would be lazy resolved on each use.
25+
* This enables concise and simple consumption of the tracker throughout our Extension.
26+
*
27+
* @returns { Tracker }
28+
*/
29+
public static getTracker(): BASTelemetryClient {
30+
return BASClientFactory.getBASTelemetryClient();
31+
}
32+
33+
public static createTracker(logger?: IChildLogger): void {
34+
try {
35+
const packageJsonPath = join(__dirname, "..", "package.json");
36+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
37+
const vscodeExtentionFullName = `${packageJson.publisher}.${packageJson.name}`;
38+
initTelemetrySettings(vscodeExtentionFullName, packageJson.version);
39+
logger?.info(
40+
`SAP Web Analytics tracker was created for ${vscodeExtentionFullName}`
41+
);
42+
} catch (error: any) {
43+
logger?.error(error);
44+
}
45+
}
46+
47+
private static report(opt: {
48+
eventName: string;
49+
properties?: any;
50+
logger?: IChildLogger;
51+
}): void {
52+
// We want to report only if we are not in Local VSCode environment
53+
const eventName = opt.eventName;
54+
if (process.env.LANDSCAPE_ENVIRONMENT) {
55+
void AnalyticsWrapper.getTracker().report(opt.eventName, opt.properties);
56+
opt.logger?.trace("SAP Web Analytics tracker was called", {
57+
eventName,
58+
});
59+
} else {
60+
opt.logger?.trace(
61+
"SAP Web Analytics tracker was not called because LANDSCAPE_ENVIRONMENT is not set",
62+
{
63+
eventName,
64+
}
65+
);
66+
}
67+
}
68+
69+
public static updateSnippetStarted(
70+
snippetName: string,
71+
logger?: IChildLogger
72+
): void {
73+
try {
74+
const eventName = AnalyticsWrapper.EVENT_TYPES.SNIPPET_CREATION_STARTED;
75+
AnalyticsWrapper.startTime = Date.now();
76+
const properties = { snippetName };
77+
AnalyticsWrapper.report({ eventName, properties, logger });
78+
} catch (error: any) {
79+
logger?.error(error);
80+
}
81+
}
82+
83+
public static updateSnippetEnded(
84+
snippetName: string,
85+
isSucceeded: boolean,
86+
logger?: IChildLogger,
87+
errorMessage?: string
88+
): void {
89+
try {
90+
const eventName = isSucceeded
91+
? AnalyticsWrapper.EVENT_TYPES.SNIPPET_CREATION_SUCCESSFULLY
92+
: AnalyticsWrapper.EVENT_TYPES.SNIPPET_CREATION_FAILED;
93+
const endTime = Date.now();
94+
const snippetTimeMilliSec = endTime - AnalyticsWrapper.startTime;
95+
const snippetTimeSec = Math.round(snippetTimeMilliSec / 1000);
96+
const properties: any = {
97+
snippetName,
98+
snippetTime: snippetTimeSec.toString(),
99+
};
100+
if (errorMessage) {
101+
properties.push(errorMessage);
102+
}
103+
AnalyticsWrapper.report({ eventName, properties, logger });
104+
} catch (error: any) {
105+
logger?.error(error);
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)