Skip to content

Commit

Permalink
fix(@angular/cli): add builders and schematic names as page titles in…
Browse files Browse the repository at this point in the history
… collected analytics

With this commit the builder and schematic names are added as page title to page events.

Also, we address a bug where during a watch or error in some cases analytics where not flushed. Examples when the builder has a watch mode.

(cherry picked from commit 23c233c)
  • Loading branch information
alan-agius4 authored and clydin committed Sep 23, 2022
1 parent a2ac84a commit 05b18f4
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,15 @@ export abstract class ArchitectBaseCommandModule<T extends object>
return this.onMissingTarget(e.message);
}

await this.reportAnalytics({
...(await architectHost.getOptionsForTarget(target)),
...options,
});
await this.reportAnalytics(
{
...(await architectHost.getOptionsForTarget(target)),
...options,
},
undefined /** paths */,
undefined /** dimensions */,
builderName,
);

const { logger } = this.context;

Expand Down
28 changes: 27 additions & 1 deletion packages/angular/cli/src/command-builder/command-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,11 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI

// Gather and report analytics.
const analytics = await this.getAnalytics();
let stopPeriodicFlushes: (() => Promise<void>) | undefined;

if (this.shouldReportAnalytics) {
await this.reportAnalytics(camelCasedOptions);
stopPeriodicFlushes = this.periodicAnalyticsFlush(analytics);
}

let exitCode: number | void | undefined;
Expand All @@ -151,7 +154,6 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
exitCode = await this.run(camelCasedOptions as Options<T> & OtherOptions);
const endTime = Date.now();
analytics.timing(this.commandName, 'duration', endTime - startTime);
await analytics.flush();
} catch (e) {
if (e instanceof schema.SchemaValidationException) {
this.context.logger.fatal(`Error: ${e.message}`);
Expand All @@ -160,6 +162,8 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
throw e;
}
} finally {
await stopPeriodicFlushes?.();

if (typeof exitCode === 'number' && exitCode > 0) {
process.exitCode = exitCode;
}
Expand All @@ -170,6 +174,7 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
options: (Options<T> & OtherOptions) | OtherOptions,
paths: string[] = [],
dimensions: (boolean | number | string)[] = [],
title?: string,
): Promise<void> {
for (const [name, ua] of this.optionsWithAnalytics) {
const value = options[name];
Expand All @@ -183,6 +188,7 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
analytics.pageview('/command/' + [this.commandName, ...paths].join('/'), {
dimensions,
metrics: [],
title,
});
}

Expand Down Expand Up @@ -275,6 +281,26 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI

return workspace;
}

/**
* Flush on an interval (if the event loop is waiting).
*
* @returns a method that when called will terminate the periodic
* flush and call flush one last time.
*/
private periodicAnalyticsFlush(analytics: analytics.Analytics): () => Promise<void> {
let analyticsFlushPromise = Promise.resolve();
const analyticsFlushInterval = setInterval(() => {
analyticsFlushPromise = analyticsFlushPromise.then(() => analytics.flush());
}, 2000);

return () => {
clearInterval(analyticsFlushInterval);

// Flush one last time.
return analyticsFlushPromise.then(() => analytics.flush());
};
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,13 @@ export abstract class SchematicsCommandModule
workflow.engineHost.registerOptionsTransform(async (schematic, options) => {
if (shouldReportAnalytics) {
shouldReportAnalytics = false;
// ng generate lib -> ng generate
const commandName = this.command?.split(' ', 1)[0];

await this.reportAnalytics(options as {}, [
commandName,
schematic.collection.name.replace(/\//g, '_'),
schematic.name.replace(/\//g, '_'),
]);

await this.reportAnalytics(
options as {},
undefined /** paths */,
undefined /** dimensions */,
schematic.collection.name + ':' + schematic.name,
);
}

// TODO: The below should be removed in version 15 when we change 1P schematics to use the `workingDirectory smart default`.
Expand Down

0 comments on commit 05b18f4

Please sign in to comment.