-
Notifications
You must be signed in to change notification settings - Fork 53
NEW @W-17915999@ Added telemetry collection for run action #1778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/lib/actions/RunAction.ts
Outdated
|
|
||
| private emitEngineExecutionTelemetry(ruleSelection: RuleSelection, results: RunResults, coreEngineNames: string[]): Promise<void> { | ||
| const selectedEngineNames: Set<string> = new Set(ruleSelection.getEngineNames()); | ||
| const executedEngineNames: Set<string> = new Set(results.getEngineNames()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out that some of the tests started failing when I assumed that the ruleSelection and results would have the same .getEngineNames() results, so I added the separate boolean for execution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
? How could this ever be the case? Are you sure the tests are not incorrect?
Is it because the results.getEngineNames return the uninstantiated engines as well but the ruleSelection doesn't?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely sure. I'll look further into it.
src/lib/actions/RunAction.ts
Outdated
| pluginsFactory: EnginePluginsFactory; | ||
| logEventListeners: LogEventListener[]; | ||
| progressListeners: ProgressEventListener[]; | ||
| telemetryEmitter?: TelemetryEmitter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I deviated from the pattern I've been using with the Listeners.
src/lib/actions/RunAction.ts
Outdated
| // LogEventListeners should start listening as soon as the Core is instantiated, since Core can start emitting | ||
| // events they listen for basically immediately. | ||
| this.dependencies.logEventListeners.forEach(listener => listener.listen(core)); | ||
| const telemetryListener: TelemetryEventListener = new TelemetryEventListener(this.dependencies.telemetryEmitter ?? new NoOpTelemetryEmitter()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only instantiate one listener, and we'll use either the one we were given or a NoOp one. This should help avoid some messy nullchecks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this line. When would telemetryEmitter ever be null?
| return Promise.resolve(); | ||
| }); | ||
| receivedTelemetryEmissions = []; | ||
| jest.spyOn(SfCliTelemetryEmitter.prototype, 'emitTelemetry').mockImplementation((source, eventName, data) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this isn't the preferred way of doing this sort of test, but it was the best option available.
src/lib/actions/RunAction.ts
Outdated
| pluginsFactory: EnginePluginsFactory; | ||
| logEventListeners: LogEventListener[]; | ||
| progressListeners: ProgressEventListener[]; | ||
| telemetryEmitter?: TelemetryEmitter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When would you ever have this undefined?
src/lib/actions/RunAction.ts
Outdated
| // LogEventListeners should start listening as soon as the Core is instantiated, since Core can start emitting | ||
| // events they listen for basically immediately. | ||
| this.dependencies.logEventListeners.forEach(listener => listener.listen(core)); | ||
| const telemetryListener: TelemetryEventListener = new TelemetryEventListener(this.dependencies.telemetryEmitter ?? new NoOpTelemetryEmitter()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this line. When would telemetryEmitter ever be null?
src/lib/actions/RunAction.ts
Outdated
| engineTelemetryObject[`${coreEngineName}_selected`] = selected; | ||
| engineTelemetryObject[`${coreEngineName}_executed`] = executed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand this.
Is it that the results.getEngineNames is returning the uninstantiated engines as well?
3444516 to
0ba14f8
Compare
| if (!selectedEngineNames.has(coreEngineName)) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you really need to pass in coreEngineNames. Let's just loop over selectedEngineNames. Then back on line 81... we don't need to get the engine names from the plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have to use coreEngineNames in order to limit ourselves to the plugins that we ourselves ship. Otherwise, we're collecting telemetry on possibly-user-created engines, which is apparently a no-no.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh you are saying that enginePlugins which you get from the this.dependencies.pluginsFactory.create(); doesn't include the dynamic engines. OK makes sense.
src/lib/actions/RunAction.ts
Outdated
| const telemetryPromises: Promise<void>[] = []; | ||
| for (const selectionTelemetry of selectionTelemetryEvents) { | ||
| telemetryPromises.push(this.dependencies.telemetryEmitter.emitTelemetry('RunAction', Constants.TelemetryEventName, selectionTelemetry)); | ||
| } | ||
| for (const executionTelemetry of executionTelemetryEvents) { | ||
| telemetryPromises.push(this.dependencies.telemetryEmitter.emitTelemetry('RunAction', Constants.TelemetryEventName, executionTelemetry)); | ||
| } | ||
| return telemetryPromises; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you go over into lib/Telemetry.ts
and make
export interface TelemetryEmitter {
emitTelemetry(source: string, eventName: string, data: TelemetryData): Promise<void>;
}
export class SfCliTelemetryEmitter implements TelemetryEmitter {
// istanbul ignore next - No sense in covering SF-CLI core code.
public emitTelemetry(source: string, eventName: string, data: TelemetryData): Promise<void> {
return Lifecycle.getInstance().emitTelemetry({
...data,
source,
eventName
});
}
}
instead be the following (since we won't be awaiting these anyway):
export interface TelemetryEmitter {
emitTelemetry(source: string, eventName: string, data: TelemetryData): void;
}
export class SfCliTelemetryEmitter implements TelemetryEmitter {
// istanbul ignore next - No sense in covering SF-CLI core code.
public emitTelemetry(source: string, eventName: string, data: TelemetryData): void {
void Lifecycle.getInstance().emitTelemetry({
...data,
source,
eventName
});
}
}
then you won't need to create on line 103 and 104 these arrays, to then fill them, to then create promise arrays, to then push them, etc.
Instead you should be able to just immediately call the emitTelemetry('RunAction', ...) on lines 109 and 115.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's reasonable.
No description provided.