Report versions of plugins and plugin load success rate (#1270)
Summary: Pull Request resolved: https://github.com/facebook/flipper/pull/1270 1) Report versions of loaded plugins so we can track auto-updates 2) Report plugin load success rate Reviewed By: jknoxville Differential Revision: D22066598 fbshipit-source-id: 23ef2fb37260438cc1a9a873c88a50b75cd718f4
This commit is contained in:
committed by
Facebook GitHub Bot
parent
fec52a3989
commit
c995fc8fc2
@@ -8,6 +8,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
jest.mock('../../defaultPlugins');
|
jest.mock('../../defaultPlugins');
|
||||||
|
try {
|
||||||
|
jest.mock('../../fb/Logger', () => require('../../fb-stubs/Logger'));
|
||||||
|
} catch {}
|
||||||
|
|
||||||
import dispatcher, {
|
import dispatcher, {
|
||||||
getDynamicPlugins,
|
getDynamicPlugins,
|
||||||
@@ -158,6 +161,7 @@ test('requirePlugin loads plugin', () => {
|
|||||||
entry: path.join(__dirname, 'TestPlugin'),
|
entry: path.join(__dirname, 'TestPlugin'),
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
});
|
});
|
||||||
|
expect(plugin).not.toBeNull();
|
||||||
expect(plugin!.prototype).toBeInstanceOf(FlipperPlugin);
|
expect(plugin!.prototype).toBeInstanceOf(FlipperPlugin);
|
||||||
expect(plugin!.id).toBe(TestPlugin.id);
|
expect(plugin!.id).toBe(TestPlugin.id);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import semver from 'semver';
|
|||||||
import {PluginDetails} from 'flipper-plugin-lib';
|
import {PluginDetails} from 'flipper-plugin-lib';
|
||||||
import {addNotification} from '../reducers/notifications';
|
import {addNotification} from '../reducers/notifications';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
import {tryCatchReportPluginFailures, reportUsage} from '../utils/metrics';
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-unresolved
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import getPluginIndex from '../utils/getDefaultPluginsIndex';
|
import getPluginIndex from '../utils/getDefaultPluginsIndex';
|
||||||
@@ -58,6 +59,7 @@ export default (store: Store, logger: Logger) => {
|
|||||||
const initialPlugins: Array<
|
const initialPlugins: Array<
|
||||||
typeof FlipperPlugin | typeof FlipperDevicePlugin
|
typeof FlipperPlugin | typeof FlipperDevicePlugin
|
||||||
> = filterNewestVersionOfEachPlugin(getBundledPlugins(), getDynamicPlugins())
|
> = filterNewestVersionOfEachPlugin(getBundledPlugins(), getDynamicPlugins())
|
||||||
|
.map(reportVersion)
|
||||||
.filter(checkDisabled(disabledPlugins))
|
.filter(checkDisabled(disabledPlugins))
|
||||||
.filter(checkGK(gatekeepedPlugins))
|
.filter(checkGK(gatekeepedPlugins))
|
||||||
.map(requirePlugin(failedPlugins, defaultPluginsIndex))
|
.map(requirePlugin(failedPlugins, defaultPluginsIndex))
|
||||||
@@ -70,7 +72,6 @@ export default (store: Store, logger: Logger) => {
|
|||||||
const deprecatedSpecPlugins = initialPlugins.filter(
|
const deprecatedSpecPlugins = initialPlugins.filter(
|
||||||
(p) => !p.isDefault && p.details.specVersion === 1,
|
(p) => !p.isDefault && p.details.specVersion === 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const plugin of deprecatedSpecPlugins) {
|
for (const plugin of deprecatedSpecPlugins) {
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
addNotification({
|
addNotification({
|
||||||
@@ -149,6 +150,17 @@ export default (store: Store, logger: Logger) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function reportVersion(pluginDetails: PluginDetails) {
|
||||||
|
reportUsage(
|
||||||
|
'plugin:version',
|
||||||
|
{
|
||||||
|
version: pluginDetails.version,
|
||||||
|
},
|
||||||
|
pluginDetails.id,
|
||||||
|
);
|
||||||
|
return pluginDetails;
|
||||||
|
}
|
||||||
|
|
||||||
export function filterNewestVersionOfEachPlugin(
|
export function filterNewestVersionOfEachPlugin(
|
||||||
bundledPlugins: PluginDetails[],
|
bundledPlugins: PluginDetails[],
|
||||||
dynamicPlugins: PluginDetails[],
|
dynamicPlugins: PluginDetails[],
|
||||||
@@ -237,33 +249,43 @@ export const requirePlugin = (
|
|||||||
pluginDetails: PluginDetails,
|
pluginDetails: PluginDetails,
|
||||||
): typeof FlipperPlugin | typeof FlipperDevicePlugin | null => {
|
): typeof FlipperPlugin | typeof FlipperDevicePlugin | null => {
|
||||||
try {
|
try {
|
||||||
let plugin = pluginDetails.isDefault
|
return tryCatchReportPluginFailures(
|
||||||
? defaultPluginsIndex[pluginDetails.name]
|
() => requirePluginInternal(pluginDetails, defaultPluginsIndex, reqFn),
|
||||||
: reqFn(pluginDetails.entry);
|
'plugin:load',
|
||||||
if (plugin.default) {
|
pluginDetails.id,
|
||||||
plugin = plugin.default;
|
);
|
||||||
}
|
|
||||||
if (!(plugin.prototype instanceof FlipperBasePlugin)) {
|
|
||||||
throw new Error(`Plugin ${plugin.name} is not a FlipperBasePlugin`);
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.id = plugin.id || pluginDetails.id;
|
|
||||||
plugin.packageName = pluginDetails.name;
|
|
||||||
plugin.details = pluginDetails;
|
|
||||||
|
|
||||||
// set values from package.json as static variables on class
|
|
||||||
Object.keys(pluginDetails).forEach((key) => {
|
|
||||||
if (key !== 'name' && key !== 'id') {
|
|
||||||
plugin[key] =
|
|
||||||
plugin[key] || pluginDetails[key as keyof PluginDetails];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return plugin;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
failedPlugins.push([pluginDetails, e.message]);
|
failedPlugins.push([pluginDetails, e.message]);
|
||||||
console.error(pluginDetails, e);
|
console.error(`Plugin ${pluginDetails.id} failed to load`, e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const requirePluginInternal = (
|
||||||
|
pluginDetails: PluginDetails,
|
||||||
|
defaultPluginsIndex: any,
|
||||||
|
reqFn: Function = global.electronRequire,
|
||||||
|
) => {
|
||||||
|
let plugin = pluginDetails.isDefault
|
||||||
|
? defaultPluginsIndex[pluginDetails.name]
|
||||||
|
: reqFn(pluginDetails.entry);
|
||||||
|
if (plugin.default) {
|
||||||
|
plugin = plugin.default;
|
||||||
|
}
|
||||||
|
if (!(plugin.prototype instanceof FlipperBasePlugin)) {
|
||||||
|
throw new Error(`Plugin ${plugin.name} is not a FlipperBasePlugin`);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.id = plugin.id || pluginDetails.id;
|
||||||
|
plugin.packageName = pluginDetails.name;
|
||||||
|
plugin.details = pluginDetails;
|
||||||
|
|
||||||
|
// set values from package.json as static variables on class
|
||||||
|
Object.keys(pluginDetails).forEach((key) => {
|
||||||
|
if (key !== 'name' && key !== 'id') {
|
||||||
|
plugin[key] = plugin[key] || pluginDetails[key as keyof PluginDetails];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|||||||
@@ -110,6 +110,29 @@ export function tryCatchReportPlatformFailures<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wraps a closure, preserving it's functionality but logging the success or
|
||||||
|
failure state of it.
|
||||||
|
*/
|
||||||
|
export function tryCatchReportPluginFailures<T>(
|
||||||
|
closure: () => T,
|
||||||
|
name: string,
|
||||||
|
plugin: string,
|
||||||
|
): T {
|
||||||
|
try {
|
||||||
|
const result = closure();
|
||||||
|
logPluginSuccessRate(name, plugin, {kind: 'success'});
|
||||||
|
return result;
|
||||||
|
} catch (e) {
|
||||||
|
logPluginSuccessRate(name, plugin, {
|
||||||
|
kind: 'failure',
|
||||||
|
supportedOperation: !(e instanceof UnsupportedError),
|
||||||
|
error: e,
|
||||||
|
});
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Track usage of a feature.
|
* Track usage of a feature.
|
||||||
* @param action Unique name for the action performed. E.g. captureScreenshot
|
* @param action Unique name for the action performed. E.g. captureScreenshot
|
||||||
|
|||||||
Reference in New Issue
Block a user