Migrate metrics

Summary:
Had to mess with the tagged union we had, to distinguish based on
a string rather a bool which is a bit rubbish.

Reviewed By: danielbuechele

Differential Revision: D16764797

fbshipit-source-id: c33536f17b0705ca40abef8448802f9961c4c114
This commit is contained in:
Pascal Hartig
2019-08-14 04:36:51 -07:00
committed by Facebook Github Bot
parent 46e0abecdf
commit 2a34125413
3 changed files with 40 additions and 39 deletions

149
src/utils/metrics.tsx Normal file
View File

@@ -0,0 +1,149 @@
/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
import {getInstance} from '../fb-stubs/Logger';
import {CancelledPromiseError} from './errors';
type Result =
| {kind: 'success'}
| {kind: 'cancelled'}
| {kind: 'failure'; supportedOperation: boolean; error: any};
export class UnsupportedError extends Error {
constructor(message: string) {
super(message);
}
}
/*
* Wraps a Promise, preserving it's functionality but logging the success or
failure state of it, with a given name, based on whether it's fulfilled or
rejected.
Use this variant to report failures in core platform (Flipper) code.
*/
export function reportPlatformFailures<T>(
promise: Promise<T>,
name: string,
): Promise<T> {
return promise.then(
fulfilledValue => {
logPlatformSuccessRate(name, {kind: 'success'});
return fulfilledValue;
},
rejectionReason => {
if (rejectionReason instanceof CancelledPromiseError) {
logPlatformSuccessRate(name, {
kind: 'cancelled',
});
} else {
logPlatformSuccessRate(name, {
kind: 'failure',
supportedOperation: !(rejectionReason instanceof UnsupportedError),
error: rejectionReason,
});
}
return Promise.reject(rejectionReason);
},
);
}
/*
* Wraps a Promise, preserving it's functionality but logging the success or
failure state of it, with a given name, based on whether it's fulfilled or
rejected.
Use this variant to report failures in plugin code.
*/
export function reportPluginFailures<T>(
promise: Promise<T>,
name: string,
plugin: string,
): Promise<T> {
return promise.then(
fulfilledValue => {
logPluginSuccessRate(name, plugin, {kind: 'success'});
return fulfilledValue;
},
rejectionReason => {
if (rejectionReason instanceof CancelledPromiseError) {
logPlatformSuccessRate(name, {
kind: 'cancelled',
});
} else {
logPlatformSuccessRate(name, {
kind: 'failure',
supportedOperation: !(rejectionReason instanceof UnsupportedError),
error: rejectionReason,
});
}
return Promise.reject(rejectionReason);
},
);
}
/*
* Wraps a closure, preserving it's functionality but logging the success or
failure state of it.
*/
export function tryCatchReportPlatformFailures<T>(
closure: () => T,
name: string,
): T {
try {
const result = closure();
logPlatformSuccessRate(name, {kind: 'success'});
return result;
} catch (e) {
logPlatformSuccessRate(name, {
kind: 'failure',
supportedOperation: !(e instanceof UnsupportedError),
error: e,
});
throw e;
}
}
function logPlatformSuccessRate(name: string, result: Result) {
if (result.kind === 'success') {
getInstance().track('success-rate', name, {value: 1});
} else if (result.kind === 'cancelled') {
getInstance().track('operation-cancelled', name);
} else {
getInstance().track('success-rate', name, {
value: 0,
supportedOperation: result.supportedOperation ? 1 : 0,
error: extractMessage(result.error),
});
}
}
function logPluginSuccessRate(name: string, plugin: string, result: Result) {
if (result.kind === 'success') {
getInstance().track('success-rate', name, {value: 1}, plugin);
} else if (result.kind === 'cancelled') {
getInstance().track('operation-cancelled', name, undefined, plugin);
} else {
getInstance().track(
'success-rate',
name,
{
value: 0,
supportedOperation: result.supportedOperation ? 1 : 0,
error: extractMessage(result.error),
},
plugin,
);
}
}
function extractMessage(error: any) {
if (error instanceof Error) {
return error.message;
}
return JSON.stringify(error);
}