Skip to content

Commit 62a515c

Browse files
committed
chore: enrich and improve telemetry events
1 parent 14698d5 commit 62a515c

File tree

8 files changed

+228
-63
lines changed

8 files changed

+228
-63
lines changed

src/extension.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import statusBar from "./plugins/status-bar.ts";
1010
import { PluginManager } from "./plugins.ts";
1111
import { createContainerStatusTracker } from "./utils/container-status.ts";
1212
import { createLocalStackStatusTracker } from "./utils/localstack-status.ts";
13-
import { getOrCreateExtensionSessionId } from "./utils/manage.ts";
13+
import {
14+
getOrCreateExtensionSessionId,
15+
getOrCreateMachineId,
16+
} from "./utils/manage.ts";
1417
import { createSetupStatusTracker } from "./utils/setup-status.ts";
1518
import { createTelemetry } from "./utils/telemetry.ts";
1619
import { createTimeTracker } from "./utils/time-tracker.ts";
@@ -78,7 +81,8 @@ export async function activate(context: ExtensionContext) {
7881
const startTelemetry = Date.now();
7982
outputChannel.trace(`[telemetry]: Starting...`);
8083
const sessionId = await getOrCreateExtensionSessionId(context);
81-
const telemetry = createTelemetry(outputChannel, sessionId);
84+
const machineId = await getOrCreateMachineId(context);
85+
const telemetry = createTelemetry(outputChannel, sessionId, machineId);
8286
const endTelemetry = Date.now();
8387
outputChannel.trace(
8488
`[telemetry]: Completed in ${ms(endTelemetry - startTelemetry, {

src/plugins/setup.ts

Lines changed: 83 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
checkIsAuthenticated,
66
requestAuthentication,
77
saveAuthToken,
8+
readAuthToken,
89
} from "../utils/authenticate.ts";
910
import { configureAwsProfiles } from "../utils/configure-aws.ts";
1011
import { runInstallProcess } from "../utils/install.ts";
@@ -31,26 +32,6 @@ export default createPlugin(
3132
payload: {
3233
namespace: "onboarding",
3334
origin: origin_trigger,
34-
expected_steps: [
35-
{
36-
name: "emulator_installed",
37-
is_first_step: true,
38-
is_last_step: false,
39-
position: 1,
40-
},
41-
{
42-
name: "auth_token_configured",
43-
is_first_step: false,
44-
is_last_step: false,
45-
position: 2,
46-
},
47-
{
48-
name: "aws_profile_configured",
49-
is_first_step: false,
50-
is_last_step: true,
51-
position: 3,
52-
},
53-
],
5435
},
5536
});
5637

@@ -77,7 +58,7 @@ export default createPlugin(
7758
payload: {
7859
namespace: "onboarding",
7960
origin: origin_trigger,
80-
position: 1,
61+
step_order: 1,
8162
started_at: installationStartedAt,
8263
ended_at: new Date().toISOString(),
8364
status: "CANCELLED",
@@ -98,8 +79,38 @@ export default createPlugin(
9879
name: "setup_ended",
9980
payload: {
10081
namespace: "onboarding",
101-
steps: [1, 2, 3],
82+
steps: [
83+
{
84+
name: "emulator_installed",
85+
is_first_step: true,
86+
is_last_step: false,
87+
step_order: 1,
88+
status: "COMPLETED",
89+
},
90+
{
91+
name: "auth_token_configured",
92+
is_first_step: false,
93+
is_last_step: false,
94+
step_order: 2,
95+
status: "CANCELLED",
96+
},
97+
{
98+
name: "license_setup_ended",
99+
is_first_step: false,
100+
is_last_step: false,
101+
step_order: 3,
102+
status: "SKIPPED",
103+
},
104+
{
105+
name: "aws_profile_configured",
106+
is_first_step: false,
107+
is_last_step: true,
108+
step_order: 4,
109+
status: "SKIPPED",
110+
},
111+
],
102112
status: "CANCELLED",
113+
auth_token: await readAuthToken(),
103114
},
104115
});
105116
return;
@@ -113,7 +124,7 @@ export default createPlugin(
113124
payload: {
114125
namespace: "onboarding",
115126
origin: origin_trigger,
116-
position: 2,
127+
step_order: 2,
117128
started_at: authStartedAuthAt,
118129
ended_at: new Date().toISOString(),
119130
status: "SKIPPED",
@@ -135,7 +146,7 @@ export default createPlugin(
135146
payload: {
136147
namespace: "onboarding",
137148
origin: origin_trigger,
138-
position: 2,
149+
step_order: 2,
139150
auth_token: authToken,
140151
started_at: authStartedAuthAt,
141152
ended_at: new Date().toISOString(),
@@ -156,7 +167,7 @@ export default createPlugin(
156167
payload: {
157168
namespace: "onboarding",
158169
origin: origin_trigger,
159-
position: 2,
170+
step_order: 2,
160171
auth_token: authToken,
161172
started_at: authStartedAuthAt,
162173
ended_at: new Date().toISOString(),
@@ -175,6 +186,7 @@ export default createPlugin(
175186
// then there will be no license info to be reported by `localstack license info`.
176187
// Also, an expired license could be cached.
177188
// Activating the license pre-emptively to know its state during the setup process.
189+
const licenseCheckStartedAt = new Date().toISOString();
178190
const licenseIsValid = await minDelay(
179191
activateLicense(outputChannel).then(() =>
180192
checkIsLicenseValid(outputChannel),
@@ -191,15 +203,28 @@ export default createPlugin(
191203
await activateLicenseUntilValid(
192204
outputChannel,
193205
cancellationToken,
206+
telemetry,
207+
origin_trigger,
208+
licenseCheckStartedAt,
194209
);
195210
}
196211

197212
if (cancellationToken.isCancellationRequested) {
213+
telemetry.track({
214+
name: "license_setup_ended",
215+
payload: {
216+
namespace: "onboarding",
217+
step_order: 3,
218+
origin: origin_trigger,
219+
auth_token: await readAuthToken(),
220+
started_at: licenseCheckStartedAt,
221+
ended_at: new Date().toISOString(),
222+
status: "COMPLETED",
223+
},
224+
});
198225
return;
199226
}
200227

201-
//TODO add telemetry
202-
203228
/////////////////////////////////////////////////////////////////////
204229
progress.report({
205230
message: "Configuring AWS profiles...",
@@ -234,8 +259,38 @@ export default createPlugin(
234259
name: "setup_ended",
235260
payload: {
236261
namespace: "onboarding",
237-
steps: [1, 2, 3],
262+
steps: [
263+
{
264+
name: "emulator_installed",
265+
is_first_step: true,
266+
is_last_step: false,
267+
step_order: 1,
268+
status: "COMPLETED",
269+
},
270+
{
271+
name: "auth_token_configured",
272+
is_first_step: false,
273+
is_last_step: false,
274+
step_order: 2,
275+
status: "COMPLETED",
276+
},
277+
{
278+
name: "license_setup_ended",
279+
is_first_step: false,
280+
is_last_step: false,
281+
step_order: 3,
282+
status: "COMPLETED",
283+
},
284+
{
285+
name: "aws_profile_configured",
286+
is_first_step: false,
287+
is_last_step: true,
288+
step_order: 4,
289+
status: "COMPLETED",
290+
},
291+
],
238292
status: "COMPLETED",
293+
auth_token: await readAuthToken(),
239294
},
240295
});
241296
},

src/utils/authenticate.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export async function checkIsAuthenticated() {
131131
return false;
132132
}
133133
return true;
134-
} catch (error) {
134+
} catch {
135135
return false;
136136
}
137137
}
@@ -143,3 +143,21 @@ function isAuthTokenPresent(authObject: unknown) {
143143
AUTH_TOKEN_KEY in authObject
144144
);
145145
}
146+
147+
// Reads the auth token from the auth.json file for logging in the user
148+
export async function readAuthToken(): Promise<string> {
149+
try {
150+
const authJson = await fs.readFile(LOCALSTACK_AUTH_FILENAME, "utf-8");
151+
const authObject = JSON.parse(authJson) as unknown;
152+
if (!isAuthTokenPresent(authObject)) {
153+
return "";
154+
}
155+
const authToken = authObject[AUTH_TOKEN_KEY];
156+
if (typeof authToken !== "string") {
157+
return "";
158+
}
159+
return authToken;
160+
} catch {
161+
return "";
162+
}
163+
}

src/utils/configure-aws.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as path from "node:path";
55

66
import { window } from "vscode";
77

8+
import { readAuthToken } from "./authenticate.ts";
89
import { parseIni, serializeIni, updateIniSection } from "./ini-parser.ts";
910
import type { IniFile, IniSection } from "./ini-parser.ts";
1011
import type { Telemetry } from "./telemetry.ts";
@@ -296,6 +297,8 @@ export async function configureAwsProfiles(options: {
296297
const credentialsNeedsOverride =
297298
checkIfCredentialsNeedsOverride(credentialsSection);
298299

300+
const authToken = await readAuthToken();
301+
299302
// means sections exist, but we need to check what's inside
300303
if (credentialsSection && configSection) {
301304
if (!configNeedsOverride && !credentialsNeedsOverride) {
@@ -310,10 +313,11 @@ export async function configureAwsProfiles(options: {
310313
payload: {
311314
namespace: "onboarding",
312315
origin: trigger,
313-
position: 3,
316+
step_order: 4,
314317
started_at: startedAt,
315318
ended_at: new Date().toISOString(),
316319
status: "COMPLETED",
320+
auth_token: authToken,
317321
},
318322
});
319323
return;
@@ -343,10 +347,11 @@ export async function configureAwsProfiles(options: {
343347
payload: {
344348
namespace: "onboarding",
345349
origin: trigger,
346-
position: 3,
350+
step_order: 4,
347351
started_at: startedAt,
348352
ended_at: new Date().toISOString(),
349353
status: "SKIPPED",
354+
auth_token: authToken,
350355
},
351356
});
352357
return;
@@ -376,10 +381,11 @@ export async function configureAwsProfiles(options: {
376381
payload: {
377382
namespace: "onboarding",
378383
origin: trigger,
379-
position: 3,
384+
step_order: 4,
380385
started_at: startedAt,
381386
ended_at: new Date().toISOString(),
382387
status: "COMPLETED",
388+
auth_token: authToken,
383389
},
384390
});
385391
} else if (configNeedsOverride) {
@@ -398,10 +404,11 @@ export async function configureAwsProfiles(options: {
398404
payload: {
399405
namespace: "onboarding",
400406
origin: trigger,
401-
position: 3,
407+
step_order: 4,
402408
started_at: startedAt,
403409
ended_at: new Date().toISOString(),
404410
status: "COMPLETED",
411+
auth_token: authToken,
405412
},
406413
});
407414
} else if (credentialsNeedsOverride) {
@@ -420,10 +427,11 @@ export async function configureAwsProfiles(options: {
420427
payload: {
421428
namespace: "onboarding",
422429
origin: trigger,
423-
position: 3,
430+
step_order: 4,
424431
started_at: startedAt,
425432
ended_at: new Date().toISOString(),
426433
status: "COMPLETED",
434+
auth_token: authToken,
427435
},
428436
});
429437
}

src/utils/install.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export async function runInstallProcess(
6464
payload: {
6565
namespace: "onboarding",
6666
origin: origin_trigger,
67-
position: 1,
67+
step_order: 1,
6868
started_at: startedAt,
6969
ended_at: new Date().toISOString(),
7070
status: "SKIPPED",
@@ -152,7 +152,7 @@ export async function runInstallProcess(
152152
payload: {
153153
namespace: "onboarding",
154154
origin: origin_trigger,
155-
position: 1,
155+
step_order: 1,
156156
started_at: startedAt,
157157
ended_at: new Date().toISOString(),
158158
status: "FAILED",
@@ -181,7 +181,7 @@ export async function runInstallProcess(
181181
payload: {
182182
namespace: "onboarding",
183183
origin: origin_trigger,
184-
position: 1,
184+
step_order: 1,
185185
started_at: startedAt,
186186
ended_at: new Date().toISOString(),
187187
status: "FAILED",
@@ -198,7 +198,7 @@ export async function runInstallProcess(
198198
payload: {
199199
namespace: "onboarding",
200200
origin: origin_trigger,
201-
position: 1,
201+
step_order: 1,
202202
started_at: startedAt,
203203
ended_at: new Date().toISOString(),
204204
status: "COMPLETED",

src/utils/license.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type { CancellationToken, LogOutputChannel } from "vscode";
22

3+
import { readAuthToken } from "./authenticate.ts";
34
import { execLocalStack } from "./cli.ts";
5+
import type { Telemetry } from "./telemetry.ts";
46

57
const LICENSE_VALIDITY_MARKER = "license validity: valid";
68

@@ -30,13 +32,28 @@ export async function activateLicense(outputChannel: LogOutputChannel) {
3032
export async function activateLicenseUntilValid(
3133
outputChannel: LogOutputChannel,
3234
cancellationToken: CancellationToken,
35+
telemetry: Telemetry,
36+
origin: "manual_trigger" | "extension_startup",
37+
startedAt: string,
3338
): Promise<void> {
3439
while (true) {
3540
if (cancellationToken.isCancellationRequested) {
3641
break;
3742
}
3843
const licenseIsValid = await checkIsLicenseValid(outputChannel);
3944
if (licenseIsValid) {
45+
telemetry.track({
46+
name: "license_setup_ended",
47+
payload: {
48+
namespace: "onboarding",
49+
step_order: 3,
50+
origin: origin,
51+
auth_token: await readAuthToken(),
52+
started_at: startedAt,
53+
ended_at: new Date().toISOString(),
54+
status: "COMPLETED",
55+
},
56+
});
4057
break;
4158
}
4259
await activateLicense(outputChannel);

0 commit comments

Comments
 (0)