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:
committed by
Facebook Github Bot
parent
451db57fa5
commit
2599dffe48
@@ -29,6 +29,8 @@ import {
|
|||||||
finishHealthchecks,
|
finishHealthchecks,
|
||||||
} from '../reducers/healthchecks';
|
} from '../reducers/healthchecks';
|
||||||
|
|
||||||
|
import {reportUsage} from '../utils/metrics';
|
||||||
|
|
||||||
type StateFromProps = {
|
type StateFromProps = {
|
||||||
healthcheckResult: HealthcheckResult;
|
healthcheckResult: HealthcheckResult;
|
||||||
} & HealthcheckSettings;
|
} & HealthcheckSettings;
|
||||||
@@ -58,6 +60,7 @@ class DoctorBar extends Component<Props, State> {
|
|||||||
!this.props.healthcheckResult.isAcknowledged
|
!this.props.healthcheckResult.isAcknowledged
|
||||||
) {
|
) {
|
||||||
this.setVisible(true);
|
this.setVisible(true);
|
||||||
|
reportUsage('doctor:warning:shown');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import runHealthchecks, {
|
|||||||
HealthcheckEventsHandler,
|
HealthcheckEventsHandler,
|
||||||
} from '../utils/runHealthchecks';
|
} from '../utils/runHealthchecks';
|
||||||
import {shell} from 'electron';
|
import {shell} from 'electron';
|
||||||
|
import {reportUsage} from '../utils/metrics';
|
||||||
|
|
||||||
type StateFromProps = {
|
type StateFromProps = {
|
||||||
healthcheckReport: HealthcheckReport;
|
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 {
|
static getDerivedStateFromProps(props: Props, state: State): State | null {
|
||||||
if (
|
if (
|
||||||
!state.acknowledgeCheckboxVisible &&
|
!state.acknowledgeCheckboxVisible &&
|
||||||
@@ -264,8 +269,16 @@ class DoctorSheet extends Component<Props, State> {
|
|||||||
|
|
||||||
componentWillUnmount(): void {
|
componentWillUnmount(): void {
|
||||||
if (this.state.acknowledgeOnClose) {
|
if (this.state.acknowledgeOnClose) {
|
||||||
|
if (hasNewProblems(this.props.healthcheckReport.result)) {
|
||||||
|
reportUsage('doctor:report:closed:newProblems:acknowledged');
|
||||||
|
}
|
||||||
|
reportUsage('doctor:report:closed:acknowleged');
|
||||||
this.props.acknowledgeProblems();
|
this.props.acknowledgeProblems();
|
||||||
} else {
|
} else {
|
||||||
|
if (hasNewProblems(this.props.healthcheckReport.result)) {
|
||||||
|
reportUsage('doctor:report:closed:newProblems:notAcknowledged');
|
||||||
|
}
|
||||||
|
reportUsage('doctor:report:closed:notAcknowledged');
|
||||||
this.props.resetAcknowledgedProblems();
|
this.props.resetAcknowledgedProblems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export function reportUsage(
|
|||||||
getInstance().track('usage', action, data, plugin);
|
getInstance().track('usage', action, data, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
function logPlatformSuccessRate(name: string, result: Result) {
|
export function logPlatformSuccessRate(name: string, result: Result) {
|
||||||
if (result.kind === 'success') {
|
if (result.kind === 'success') {
|
||||||
getInstance().track('success-rate', name, {value: 1});
|
getInstance().track('success-rate', name, {value: 1});
|
||||||
} else if (result.kind === 'cancelled') {
|
} else if (result.kind === 'cancelled') {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
import {HealthcheckResult} from '../reducers/healthchecks';
|
import {HealthcheckResult} from '../reducers/healthchecks';
|
||||||
import {getHealthchecks, getEnvInfo, Healthchecks} from 'flipper-doctor';
|
import {getHealthchecks, getEnvInfo, Healthchecks} from 'flipper-doctor';
|
||||||
|
import {logPlatformSuccessRate, reportPlatformFailures} from '../utils/metrics';
|
||||||
|
|
||||||
let healthcheckIsRunning: boolean;
|
let healthcheckIsRunning: boolean;
|
||||||
let runningHealthcheck: Promise<void>;
|
let runningHealthcheck: Promise<void>;
|
||||||
@@ -41,12 +42,26 @@ async function launchHealthchecks(options: HealthcheckOptions): Promise<void> {
|
|||||||
}
|
}
|
||||||
options.startHealthchecks(healthchecks);
|
options.startHealthchecks(healthchecks);
|
||||||
const environmentInfo = await getEnvInfo();
|
const environmentInfo = await getEnvInfo();
|
||||||
|
let hasProblems = false;
|
||||||
for (const [categoryKey, category] of Object.entries(healthchecks)) {
|
for (const [categoryKey, category] of Object.entries(healthchecks)) {
|
||||||
if (category.isSkipped) {
|
if (category.isSkipped) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (const h of category.healthchecks) {
|
for (const h of category.healthchecks) {
|
||||||
const checkResult = await h.run(environmentInfo);
|
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 =
|
const result: HealthcheckResult =
|
||||||
checkResult.hasProblem && h.isRequired
|
checkResult.hasProblem && h.isRequired
|
||||||
? {
|
? {
|
||||||
@@ -63,6 +78,17 @@ async function launchHealthchecks(options: HealthcheckOptions): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
options.finishHealthchecks();
|
options.finishHealthchecks();
|
||||||
|
if (hasProblems) {
|
||||||
|
logPlatformSuccessRate('doctor.healthcheck', {
|
||||||
|
kind: 'failure',
|
||||||
|
supportedOperation: true,
|
||||||
|
error: null,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
logPlatformSuccessRate('doctor.healthcheck', {
|
||||||
|
kind: 'success',
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function runHealthchecks(
|
export default async function runHealthchecks(
|
||||||
@@ -71,6 +97,9 @@ export default async function runHealthchecks(
|
|||||||
if (healthcheckIsRunning) {
|
if (healthcheckIsRunning) {
|
||||||
return runningHealthcheck;
|
return runningHealthcheck;
|
||||||
}
|
}
|
||||||
runningHealthcheck = launchHealthchecks(options);
|
runningHealthcheck = reportPlatformFailures(
|
||||||
|
launchHealthchecks(options),
|
||||||
|
'doctor:runHealthchecks',
|
||||||
|
);
|
||||||
return runningHealthcheck;
|
return runningHealthcheck;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user