Healthcheck failures analytics

Summary:
Send per-healthcheck success/failure event to be able to analyze most common problems.
Send event when doctor warning bar shown.
Send event when doctor report is opened by user.
Send event when user set flag "Do not show warning again" in the doctor report.

Reviewed By: passy

Differential Revision: D19312127

fbshipit-source-id: 01b648d1154a3aeadc85980190cb9e5e221b572e
This commit is contained in:
Anton Nikolaev
2020-01-10 06:16:48 -08:00
committed by Facebook Github Bot
parent 451db57fa5
commit 2599dffe48
4 changed files with 47 additions and 2 deletions

View File

@@ -29,6 +29,8 @@ import {
finishHealthchecks,
} from '../reducers/healthchecks';
import {reportUsage} from '../utils/metrics';
type StateFromProps = {
healthcheckResult: HealthcheckResult;
} & HealthcheckSettings;
@@ -58,6 +60,7 @@ class DoctorBar extends Component<Props, State> {
!this.props.healthcheckResult.isAcknowledged
) {
this.setVisible(true);
reportUsage('doctor:warning:shown');
}
}
render() {

View File

@@ -38,6 +38,7 @@ import runHealthchecks, {
HealthcheckEventsHandler,
} from '../utils/runHealthchecks';
import {shell} from 'electron';
import {reportUsage} from '../utils/metrics';
type StateFromProps = {
healthcheckReport: HealthcheckReport;
@@ -234,6 +235,10 @@ class DoctorSheet extends Component<Props, State> {
};
}
componentDidMount() {
reportUsage('doctor:report:opened');
}
static getDerivedStateFromProps(props: Props, state: State): State | null {
if (
!state.acknowledgeCheckboxVisible &&
@@ -264,8 +269,16 @@ class DoctorSheet extends Component<Props, State> {
componentWillUnmount(): void {
if (this.state.acknowledgeOnClose) {
if (hasNewProblems(this.props.healthcheckReport.result)) {
reportUsage('doctor:report:closed:newProblems:acknowledged');
}
reportUsage('doctor:report:closed:acknowleged');
this.props.acknowledgeProblems();
} else {
if (hasNewProblems(this.props.healthcheckReport.result)) {
reportUsage('doctor:report:closed:newProblems:notAcknowledged');
}
reportUsage('doctor:report:closed:notAcknowledged');
this.props.resetAcknowledgedProblems();
}
}

View File

@@ -123,7 +123,7 @@ export function reportUsage(
getInstance().track('usage', action, data, plugin);
}
function logPlatformSuccessRate(name: string, result: Result) {
export function logPlatformSuccessRate(name: string, result: Result) {
if (result.kind === 'success') {
getInstance().track('success-rate', name, {value: 1});
} else if (result.kind === 'cancelled') {

View File

@@ -9,6 +9,7 @@
import {HealthcheckResult} from '../reducers/healthchecks';
import {getHealthchecks, getEnvInfo, Healthchecks} from 'flipper-doctor';
import {logPlatformSuccessRate, reportPlatformFailures} from '../utils/metrics';
let healthcheckIsRunning: boolean;
let runningHealthcheck: Promise<void>;
@@ -41,12 +42,26 @@ async function launchHealthchecks(options: HealthcheckOptions): Promise<void> {
}
options.startHealthchecks(healthchecks);
const environmentInfo = await getEnvInfo();
let hasProblems = false;
for (const [categoryKey, category] of Object.entries(healthchecks)) {
if (category.isSkipped) {
continue;
}
for (const h of category.healthchecks) {
const checkResult = await h.run(environmentInfo);
const metricName = `doctor:${h.key.replace('.', ':')}.healthcheck`; // e.g. "doctor:ios:xcode-select.healthcheck"
if (checkResult.hasProblem) {
hasProblems = true;
logPlatformSuccessRate(metricName, {
kind: 'failure',
supportedOperation: true,
error: null,
});
} else {
logPlatformSuccessRate(metricName, {
kind: 'success',
});
}
const result: HealthcheckResult =
checkResult.hasProblem && h.isRequired
? {
@@ -63,6 +78,17 @@ async function launchHealthchecks(options: HealthcheckOptions): Promise<void> {
}
}
options.finishHealthchecks();
if (hasProblems) {
logPlatformSuccessRate('doctor.healthcheck', {
kind: 'failure',
supportedOperation: true,
error: null,
});
} else {
logPlatformSuccessRate('doctor.healthcheck', {
kind: 'success',
});
}
}
export default async function runHealthchecks(
@@ -71,6 +97,9 @@ export default async function runHealthchecks(
if (healthcheckIsRunning) {
return runningHealthcheck;
}
runningHealthcheck = launchHealthchecks(options);
runningHealthcheck = reportPlatformFailures(
launchHealthchecks(options),
'doctor:runHealthchecks',
);
return runningHealthcheck;
}