Skip to content

Commit a7a2364

Browse files
committed
Implement 1ds SDK
1 parent eaf6aac commit a7a2364

6 files changed

+78
-89
lines changed

src/browser/1dsTelemetryReporter.ts

-24
This file was deleted.

src/browser/telemetryReporter.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import type { ApplicationInsights } from "@microsoft/applicationinsights-web";
66
import * as vscode from "vscode";
7+
import { oneDataSystemClientFactory } from "../common/1dsClientFactory";
78
import { BaseTelemetryAppender, BaseTelemetryClient } from "../common/baseTelemetryAppender";
89
import { AppenderData, BaseTelemetryReporter, ReplacementOption } from "../common/baseTelemetryReporter";
910
import { TelemetryUtil } from "../common/util";
@@ -71,8 +72,15 @@ const webAppInsightsClientFactory = async (key: string, replacementOptions?: Rep
7172

7273
export default class TelemetryReporter extends BaseTelemetryReporter {
7374
constructor(extensionId: string, extensionVersion: string, key: string, firstParty?: boolean, replacementOptions?: ReplacementOption[]) {
74-
const appender = new BaseTelemetryAppender(key, key => webAppInsightsClientFactory(key, replacementOptions));
75-
if (key && key.indexOf("AIF-") === 0) {
75+
let clientFactory = (key: string) => webAppInsightsClientFactory(key, replacementOptions);
76+
// If key is usable by 1DS use the 1DS SDk
77+
if (TelemetryUtil.shouldUseOneDataSystemSDK(key)) {
78+
clientFactory = (key: string) => oneDataSystemClientFactory(key);
79+
}
80+
81+
const appender = new BaseTelemetryAppender(key, clientFactory);
82+
// If it's a specialized AIF app insights key or a 1DS key then it is first party
83+
if (key && (key.indexOf("AIF-") === 0 || TelemetryUtil.shouldUseOneDataSystemSDK(key))) {
7684
firstParty = true;
7785
}
7886
super(extensionId, extensionVersion, appender, {

src/common/baseTelemetryReporter.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ export class BaseTelemetryReporter {
149149
// __GDPR__COMMON__ "common.isnewappinstall" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
150150
// __GDPR__COMMON__ "common.product" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
151151
private getCommonProperties(): TelemetryEventProperties {
152-
const commonProperties = Object.create(null);
152+
const commonProperties: Record<string, any> = {};
153153
commonProperties["common.os"] = this.osShim.platform;
154154
commonProperties["common.nodeArch"] = this.osShim.architecture;
155155
commonProperties["common.platformversion"] = (this.osShim.release || "").replace(/^(\d+)(\.\d+)?(\.\d+)?(.*)/, "$1$2$3");
@@ -242,7 +242,7 @@ export class BaseTelemetryReporter {
242242
if (typeof properties !== "object") {
243243
return;
244244
}
245-
const cleanedObject = Object.create(null);
245+
const cleanedObject: Record<string, any> = {};
246246
// Loop through key and values of the properties object
247247
for (const key of Object.keys(properties)) {
248248
const value = properties[key];

src/common/util.ts

+17
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,23 @@ export class TelemetryUtil {
5656
}
5757
}
5858

59+
/**
60+
* Given a key checks if it is a valid 1DS key
61+
* @param key The key to check if it's a valid 1DS key
62+
*/
63+
public static shouldUseOneDataSystemSDK(key: string): boolean {
64+
// Simple to check to ensure the key is the right length and the dashes are in the right spot
65+
return (
66+
key.length === 74 &&
67+
key[32] === "-" &&
68+
key[41] === "-" &&
69+
key[46] === "-" &&
70+
key[51] === "-" &&
71+
key[56] === "-" &&
72+
key[69] === "-"
73+
);
74+
}
75+
5976
// Get singleton instance of TelemetryUtil
6077
public static getInstance(vscodeAPI: typeof vscode): TelemetryUtil {
6178
if (!TelemetryUtil._instance) {

src/node/1dsTelemetryReporter.ts

-59
This file was deleted.

src/node/telemetryReporter.ts

+49-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
import * as os from "os";
66
import * as vscode from "vscode";
7+
import * as https from "https";
78
import type { TelemetryClient } from "applicationinsights";
89
import { AppenderData, BaseTelemetryReporter, ReplacementOption } from "../common/baseTelemetryReporter";
910
import { BaseTelemetryAppender, BaseTelemetryClient } from "../common/baseTelemetryAppender";
1011
import { TelemetryUtil } from "../common/util";
12+
import type { IXHROverride, IPayloadData } from "@microsoft/1ds-post-js";
13+
import { oneDataSystemClientFactory } from "../common/1dsClientFactory";
1114
/**
1215
* A factory function which creates a telemetry client to be used by an appender to send telemetry in a node application.
1316
*
@@ -118,10 +121,54 @@ function addReplacementOptions(appInsightsClient: TelemetryClient, replacementOp
118121
});
119122
}
120123

124+
/**
125+
* Create a replacement for the XHTMLRequest object utilizing nodes HTTP module.
126+
* @returns A XHR override object used to override the XHTMLRequest object in the 1DS SDK
127+
*/
128+
function getXHROverride() {
129+
// Override the way events get sent since node doesn't have XHTMLRequest
130+
const customHttpXHROverride: IXHROverride = {
131+
sendPOST: (payload: IPayloadData, oncomplete) => {
132+
const options = {
133+
method: "POST",
134+
headers: {
135+
...payload.headers,
136+
"Content-Type": "application/json",
137+
"Content-Length": Buffer.byteLength(payload.data)
138+
}
139+
};
140+
try {
141+
const req = https.request(payload.urlString, options, res => {
142+
res.on("data", function (responseData) {
143+
oncomplete(res.statusCode ?? 200, res.headers as Record<string, any>, responseData.toString());
144+
});
145+
// On response with error send status of 0 and a blank response to oncomplete so we can retry events
146+
res.on("error", function () {
147+
oncomplete(0, {});
148+
});
149+
});
150+
req.write(payload.data);
151+
req.end();
152+
} catch {
153+
// If it errors out, send status of 0 and a blank response to oncomplete so we can retry events
154+
oncomplete(0, {});
155+
}
156+
}
157+
};
158+
return customHttpXHROverride;
159+
}
160+
121161
export default class TelemetryReporter extends BaseTelemetryReporter {
122162
constructor(extensionId: string, extensionVersion: string, key: string, firstParty?: boolean, replacementOptions?: ReplacementOption[]) {
123-
const appender = new BaseTelemetryAppender(key, (key) => appInsightsClientFactory(key, replacementOptions));
124-
if (key && key.indexOf("AIF-") === 0) {
163+
let clientFactory = (key: string) => appInsightsClientFactory(key, replacementOptions);
164+
// If key is usable by 1DS use the 1DS SDk
165+
if (TelemetryUtil.shouldUseOneDataSystemSDK(key)) {
166+
clientFactory = (key: string) => oneDataSystemClientFactory(key, getXHROverride());
167+
}
168+
169+
const appender = new BaseTelemetryAppender(key, clientFactory);
170+
// If it's a specialized AIF app insights key or a 1DS key then it is first party
171+
if (key && (key.indexOf("AIF-") === 0 || TelemetryUtil.shouldUseOneDataSystemSDK(key))) {
125172
firstParty = true;
126173
}
127174
super(extensionId, extensionVersion, appender, {

0 commit comments

Comments
 (0)