Skip to content

Commit f0d0162

Browse files
committed
chore: enrich and improve telemetry events
1 parent 6dd75db commit f0d0162

File tree

8 files changed

+228
-62
lines changed

8 files changed

+228
-62
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";
@@ -38,26 +39,6 @@ export default createPlugin(
3839
payload: {
3940
namespace: "onboarding",
4041
origin: origin_trigger,
41-
expected_steps: [
42-
{
43-
name: "emulator_installed",
44-
is_first_step: true,
45-
is_last_step: false,
46-
position: 1,
47-
},
48-
{
49-
name: "auth_token_configured",
50-
is_first_step: false,
51-
is_last_step: false,
52-
position: 2,
53-
},
54-
{
55-
name: "aws_profile_configured",
56-
is_first_step: false,
57-
is_last_step: true,
58-
position: 3,
59-
},
60-
],
6142
},
6243
});
6344

@@ -84,7 +65,7 @@ export default createPlugin(
8465
payload: {
8566
namespace: "onboarding",
8667
origin: origin_trigger,
87-
position: 1,
68+
step_order: 1,
8869
started_at: installationStartedAt,
8970
ended_at: new Date().toISOString(),
9071
status: "CANCELLED",
@@ -113,8 +94,38 @@ export default createPlugin(
11394
name: "setup_ended",
11495
payload: {
11596
namespace: "onboarding",
116-
steps: [1, 2, 3],
97+
steps: [
98+
{
99+
name: "emulator_installed",
100+
is_first_step: true,
101+
is_last_step: false,
102+
step_order: 1,
103+
status: "COMPLETED",
104+
},
105+
{
106+
name: "auth_token_configured",
107+
is_first_step: false,
108+
is_last_step: false,
109+
step_order: 2,
110+
status: "CANCELLED",
111+
},
112+
{
113+
name: "license_setup_ended",
114+
is_first_step: false,
115+
is_last_step: false,
116+
step_order: 3,
117+
status: "SKIPPED",
118+
},
119+
{
120+
name: "aws_profile_configured",
121+
is_first_step: false,
122+
is_last_step: true,
123+
step_order: 4,
124+
status: "SKIPPED",
125+
},
126+
],
117127
status: "CANCELLED",
128+
auth_token: await readAuthToken(),
118129
},
119130
});
120131
return;
@@ -128,7 +139,7 @@ export default createPlugin(
128139
payload: {
129140
namespace: "onboarding",
130141
origin: origin_trigger,
131-
position: 2,
142+
step_order: 2,
132143
started_at: authStartedAuthAt,
133144
ended_at: new Date().toISOString(),
134145
status: "SKIPPED",
@@ -153,7 +164,7 @@ export default createPlugin(
153164
payload: {
154165
namespace: "onboarding",
155166
origin: origin_trigger,
156-
position: 2,
167+
step_order: 2,
157168
auth_token: authToken,
158169
started_at: authStartedAuthAt,
159170
ended_at: new Date().toISOString(),
@@ -174,7 +185,7 @@ export default createPlugin(
174185
payload: {
175186
namespace: "onboarding",
176187
origin: origin_trigger,
177-
position: 2,
188+
step_order: 2,
178189
auth_token: authToken,
179190
started_at: authStartedAuthAt,
180191
ended_at: new Date().toISOString(),
@@ -193,6 +204,7 @@ export default createPlugin(
193204
// then there will be no license info to be reported by `localstack license info`.
194205
// Also, an expired license could be cached.
195206
// Activating the license pre-emptively to know its state during the setup process.
207+
const licenseCheckStartedAt = new Date().toISOString();
196208
const licenseIsValid = await minDelay(
197209
activateLicense(outputChannel).then(() =>
198210
checkIsLicenseValid(outputChannel),
@@ -209,15 +221,28 @@ export default createPlugin(
209221
await activateLicenseUntilValid(
210222
outputChannel,
211223
cancellationToken,
224+
telemetry,
225+
origin_trigger,
226+
licenseCheckStartedAt,
212227
);
213228
}
214229

215230
if (cancellationToken.isCancellationRequested) {
231+
telemetry.track({
232+
name: "license_setup_ended",
233+
payload: {
234+
namespace: "onboarding",
235+
step_order: 3,
236+
origin: origin_trigger,
237+
auth_token: await readAuthToken(),
238+
started_at: licenseCheckStartedAt,
239+
ended_at: new Date().toISOString(),
240+
status: "COMPLETED",
241+
},
242+
});
216243
return;
217244
}
218245

219-
//TODO add telemetry
220-
221246
/////////////////////////////////////////////////////////////////////
222247
progress.report({
223248
message: "Configuring AWS profile...",
@@ -285,8 +310,38 @@ export default createPlugin(
285310
name: "setup_ended",
286311
payload: {
287312
namespace: "onboarding",
288-
steps: [1, 2, 3],
313+
steps: [
314+
{
315+
name: "emulator_installed",
316+
is_first_step: true,
317+
is_last_step: false,
318+
step_order: 1,
319+
status: "COMPLETED",
320+
},
321+
{
322+
name: "auth_token_configured",
323+
is_first_step: false,
324+
is_last_step: false,
325+
step_order: 2,
326+
status: "COMPLETED",
327+
},
328+
{
329+
name: "license_setup_ended",
330+
is_first_step: false,
331+
is_last_step: false,
332+
step_order: 3,
333+
status: "COMPLETED",
334+
},
335+
{
336+
name: "aws_profile_configured",
337+
is_first_step: false,
338+
is_last_step: true,
339+
step_order: 4,
340+
status: "COMPLETED",
341+
},
342+
],
289343
status: "COMPLETED",
344+
auth_token: await readAuthToken(),
290345
},
291346
});
292347
},

src/utils/authenticate.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export async function checkIsAuthenticated() {
143143
return false;
144144
}
145145
return true;
146-
} catch (error) {
146+
} catch {
147147
return false;
148148
}
149149
}
@@ -155,3 +155,21 @@ function isAuthTokenPresent(authObject: unknown) {
155155
AUTH_TOKEN_KEY in authObject
156156
);
157157
}
158+
159+
// Reads the auth token from the auth.json file for logging in the user
160+
export async function readAuthToken(): Promise<string> {
161+
try {
162+
const authJson = await fs.readFile(LOCALSTACK_AUTH_FILENAME, "utf-8");
163+
const authObject = JSON.parse(authJson) as unknown;
164+
if (!isAuthTokenPresent(authObject)) {
165+
return "";
166+
}
167+
const authToken = authObject[AUTH_TOKEN_KEY];
168+
if (typeof authToken !== "string") {
169+
return "";
170+
}
171+
return authToken;
172+
} catch {
173+
return "";
174+
}
175+
}

src/utils/configure-aws.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as path from "node:path";
66
import { window } from "vscode";
77
import type { LogOutputChannel } from "vscode";
88

9+
import { readAuthToken } from "./authenticate.ts";
910
import { parseIni, serializeIni, updateIniSection } from "./ini-parser.ts";
1011
import type { IniFile, IniSection } from "./ini-parser.ts";
1112
import type { Telemetry } from "./telemetry.ts";
@@ -318,6 +319,8 @@ export async function configureAwsProfiles(options: {
318319
const credentialsNeedsOverride =
319320
checkIfCredentialsNeedsOverride(credentialsSection);
320321

322+
const authToken = await readAuthToken();
323+
321324
// means sections exist, but we need to check what's inside
322325
if (credentialsSection && configSection) {
323326
if (!configNeedsOverride && !credentialsNeedsOverride) {
@@ -332,10 +335,11 @@ export async function configureAwsProfiles(options: {
332335
payload: {
333336
namespace: "onboarding",
334337
origin: trigger,
335-
position: 3,
338+
step_order: 4,
336339
started_at: startedAt,
337340
ended_at: new Date().toISOString(),
338341
status: "COMPLETED",
342+
auth_token: authToken,
339343
},
340344
});
341345
return;
@@ -365,10 +369,11 @@ export async function configureAwsProfiles(options: {
365369
payload: {
366370
namespace: "onboarding",
367371
origin: trigger,
368-
position: 3,
372+
step_order: 4,
369373
started_at: startedAt,
370374
ended_at: new Date().toISOString(),
371375
status: "SKIPPED",
376+
auth_token: authToken,
372377
},
373378
});
374379
return;
@@ -399,10 +404,11 @@ export async function configureAwsProfiles(options: {
399404
payload: {
400405
namespace: "onboarding",
401406
origin: trigger,
402-
position: 3,
407+
step_order: 4,
403408
started_at: startedAt,
404409
ended_at: new Date().toISOString(),
405410
status: "COMPLETED",
411+
auth_token: authToken,
406412
},
407413
});
408414
} else if (configNeedsOverride) {
@@ -422,10 +428,11 @@ export async function configureAwsProfiles(options: {
422428
payload: {
423429
namespace: "onboarding",
424430
origin: trigger,
425-
position: 3,
431+
step_order: 4,
426432
started_at: startedAt,
427433
ended_at: new Date().toISOString(),
428434
status: "COMPLETED",
435+
auth_token: authToken,
429436
},
430437
});
431438
} else if (credentialsNeedsOverride) {
@@ -444,10 +451,11 @@ export async function configureAwsProfiles(options: {
444451
payload: {
445452
namespace: "onboarding",
446453
origin: trigger,
447-
position: 3,
454+
step_order: 4,
448455
started_at: startedAt,
449456
ended_at: new Date().toISOString(),
450457
status: "COMPLETED",
458+
auth_token: authToken,
451459
},
452460
});
453461
}

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",
@@ -148,7 +148,7 @@ export async function runInstallProcess(
148148
payload: {
149149
namespace: "onboarding",
150150
origin: origin_trigger,
151-
position: 1,
151+
step_order: 1,
152152
started_at: startedAt,
153153
ended_at: new Date().toISOString(),
154154
status: "FAILED",
@@ -177,7 +177,7 @@ export async function runInstallProcess(
177177
payload: {
178178
namespace: "onboarding",
179179
origin: origin_trigger,
180-
position: 1,
180+
step_order: 1,
181181
started_at: startedAt,
182182
ended_at: new Date().toISOString(),
183183
status: "FAILED",
@@ -194,7 +194,7 @@ export async function runInstallProcess(
194194
payload: {
195195
namespace: "onboarding",
196196
origin: origin_trigger,
197-
position: 1,
197+
step_order: 1,
198198
started_at: startedAt,
199199
ended_at: new Date().toISOString(),
200200
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)