Skip to content

Commit

Permalink
Ensure async telemetry hooks flush during error report
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Sitter committed Apr 27, 2024
1 parent d351d37 commit 35d5f7c
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@microsoft/rush",
"comment": "Ensure async telemetry tasks are flushed by error reporter",
"type": "patch"
}
],
"packageName": "@microsoft/rush"
}
26 changes: 17 additions & 9 deletions libraries/rush-lib/src/cli/RushCommandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,16 +436,24 @@ export class RushCommandLineParser extends CommandLineParser {

this.flushTelemetry();

// Ideally we want to eliminate all calls to process.exit() from our code, and replace them
// with normal control flow that properly cleans up its data structures.
// For this particular call, we have a problem that the RushCommandLineParser constructor
// performs nontrivial work that can throw an exception. Either the Rush class would need
// to handle reporting for those exceptions, or else _populateActions() should be moved
// to a RushCommandLineParser lifecycle stage that can handle it.
if (process.exitCode !== undefined) {
process.exit(process.exitCode);
const handleExit = () => {
// Ideally we want to eliminate all calls to process.exit() from our code, and replace them
// with normal control flow that properly cleans up its data structures.
// For this particular call, we have a problem that the RushCommandLineParser constructor
// performs nontrivial work that can throw an exception. Either the Rush class would need
// to handle reporting for those exceptions, or else _populateActions() should be moved
// to a RushCommandLineParser lifecycle stage that can handle it.
if (process.exitCode !== undefined) {
process.exit(process.exitCode);
} else {
process.exit(1);
}
}

if (this.telemetry) {
this.telemetry.ensureFlushedAsync().finally(handleExit);
} else {
process.exit(1);
handleExit();
}
}
}
24 changes: 24 additions & 0 deletions libraries/rush-lib/src/cli/test/RushCommandLineParser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,5 +397,29 @@ describe('RushCommandLineParser', () => {
expect(telemetryStore?.[0].name).toEqual('build');
});
});

it('custom telemetry reports errors', async () => {
const repoName: string = 'tapFlushTelemetryAndRunBuildActionRepo';
const instance: IParserTestInstance = await getCommandLineParserInstanceAsync(repoName, 'build');
setSpawnMock({ emitError: true, returnCode: 1 });
const telemetryFilePath: string = `${instance.parser.rushConfiguration.commonTempFolder}/test-telemetry.json`;
FileSystem.deleteFile(telemetryFilePath);

/**
* The plugin is copied into the autoinstaller folder using an option in /config/heft.json
*/
jest.spyOn(Autoinstaller.prototype, 'prepareAsync').mockImplementation(async function () {});

await expect(instance.parser.execute()).resolves.toEqual(false);

expect(FileSystem.exists(telemetryFilePath)).toEqual(true);

let telemetryStore: ITelemetryData[] = [];
expect(() => {
telemetryStore = JsonFile.load(telemetryFilePath);
}).not.toThrowError();
expect(telemetryStore?.[0].name).toEqual('build');
expect(telemetryStore?.[0].result).toEqual('Failed');
});
});
});

0 comments on commit 35d5f7c

Please sign in to comment.