Added metrics argument to headless inorder to export metrics
Summary:
This diff makes headless flipper accept `metrics` argument. Once this is passed. The headless flipper will terminate to export the metrics of the plugins, the type of the export looks like the following.
```
export type MetricType = {[metricName: string]: number};
type MetricPluginType = {[pluginID: string]: MetricType};
export type ExportMetricType = {[clientID: string]: MetricPluginType};
```
This diff, uses the store to export the metrics. I will modify the logic to accept the data which gets exported through `exportData`
Reviewed By: passy
Differential Revision: D14933499
fbshipit-source-id: dade5b7bc59ea4beb6d16c5ef471737e8597358a
This commit is contained in:
committed by
Facebook Github Bot
parent
7bbb8c10c4
commit
afd729deb6
@@ -46,8 +46,7 @@ public final class ExampleActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void sendGetRequest() {
|
public static void sendGetRequest() {
|
||||||
final Request request =
|
final Request request = new Request.Builder().url("https://api.github.com/repos/facebook/yoga").get().build();
|
||||||
new Request.Builder().url("https://api.github.com/repos/facebook/yoga").get().build();
|
|
||||||
FlipperSampleApplication.sOkHttpClient
|
FlipperSampleApplication.sOkHttpClient
|
||||||
.newCall(request)
|
.newCall(request)
|
||||||
.enqueue(
|
.enqueue(
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import dispatcher from '../src/dispatcher/index.js';
|
|||||||
import {init as initLogger} from '../src/fb-stubs/Logger.js';
|
import {init as initLogger} from '../src/fb-stubs/Logger.js';
|
||||||
import reducers from '../src/reducers/index.js';
|
import reducers from '../src/reducers/index.js';
|
||||||
import {exportStore} from '../src/utils/exportData.js';
|
import {exportStore} from '../src/utils/exportData.js';
|
||||||
|
import exportMetrics from '../src/utils/exportMetrics.js';
|
||||||
|
|
||||||
// $FlowFixMe this file exist, trust me, flow!
|
// $FlowFixMe this file exist, trust me, flow!
|
||||||
import setup from '../static/setup.js';
|
import setup from '../static/setup.js';
|
||||||
|
|
||||||
@@ -50,6 +52,12 @@ yargs
|
|||||||
describe: 'Enable verbose logging',
|
describe: 'Enable verbose logging',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
});
|
});
|
||||||
|
yargs.option('metrics', {
|
||||||
|
alias: 'metrics',
|
||||||
|
default: false,
|
||||||
|
describe: 'Will export metrics instead of data when flipper terminates',
|
||||||
|
type: 'boolean',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
startFlipper,
|
startFlipper,
|
||||||
)
|
)
|
||||||
@@ -59,6 +67,7 @@ yargs
|
|||||||
function startFlipper({
|
function startFlipper({
|
||||||
dev,
|
dev,
|
||||||
verbose,
|
verbose,
|
||||||
|
metrics,
|
||||||
exit,
|
exit,
|
||||||
'insecure-port': insecurePort,
|
'insecure-port': insecurePort,
|
||||||
'secure-port': securePort,
|
'secure-port': securePort,
|
||||||
@@ -100,12 +109,21 @@ function startFlipper({
|
|||||||
// TODO(T42325892): Investigate why the export stalls without exiting the
|
// TODO(T42325892): Investigate why the export stalls without exiting the
|
||||||
// current eventloop task here.
|
// current eventloop task here.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
exportStore(store)
|
if (metrics) {
|
||||||
.then(({serializedString}) => {
|
exportMetrics(store)
|
||||||
originalConsole.log(serializedString);
|
.then(payload => {
|
||||||
process.exit();
|
originalConsole.log(payload);
|
||||||
})
|
process.exit();
|
||||||
.catch(console.error);
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
} else {
|
||||||
|
exportStore(store)
|
||||||
|
.then(({serializedString}) => {
|
||||||
|
originalConsole.log(serializedString);
|
||||||
|
process.exit();
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
}
|
||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
return next(action);
|
return next(action);
|
||||||
@@ -122,9 +140,14 @@ function startFlipper({
|
|||||||
if (exit == 'sigint') {
|
if (exit == 'sigint') {
|
||||||
process.on('SIGINT', async () => {
|
process.on('SIGINT', async () => {
|
||||||
try {
|
try {
|
||||||
const {serializedString, errorArray} = await exportStore(store);
|
if (metrics) {
|
||||||
errorArray.forEach(console.error);
|
const payload = await exportMetrics(store);
|
||||||
originalConsole.log(serializedString);
|
originalConsole.log(payload);
|
||||||
|
} else {
|
||||||
|
const {serializedString, errorArray} = await exportStore(store);
|
||||||
|
errorArray.forEach(console.error);
|
||||||
|
originalConsole.log(serializedString);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ export class FlipperBasePlugin<
|
|||||||
method: string,
|
method: string,
|
||||||
data: Object,
|
data: Object,
|
||||||
) => $Shape<PersistedState>;
|
) => $Shape<PersistedState>;
|
||||||
|
static exportMetrics: ?(
|
||||||
|
persistedState: PersistedState,
|
||||||
|
) => Promise<Map<string, number | string>>;
|
||||||
static exportPersistedState: ?(
|
static exportPersistedState: ?(
|
||||||
callClient: (string, ?Object) => Promise<Object>,
|
callClient: (string, ?Object) => Promise<Object>,
|
||||||
persistedState: ?PersistedState,
|
persistedState: ?PersistedState,
|
||||||
|
|||||||
@@ -107,6 +107,19 @@ export default class extends FlipperPlugin<State, *, PersistedState> {
|
|||||||
responses: {},
|
responses: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static exportMetrics = (
|
||||||
|
persistedState: PersistedState,
|
||||||
|
): Promise<Map<string, number | string>> => {
|
||||||
|
const failures = Object.keys(persistedState.responses).reduce(function(
|
||||||
|
previous,
|
||||||
|
key,
|
||||||
|
) {
|
||||||
|
return previous + (persistedState.responses[key].status >= 400);
|
||||||
|
},
|
||||||
|
0);
|
||||||
|
return Promise.resolve(new Map([['NUMBER_NETWORK_FAILURES', failures]]));
|
||||||
|
};
|
||||||
|
|
||||||
static persistedStateReducer = (
|
static persistedStateReducer = (
|
||||||
persistedState: PersistedState,
|
persistedState: PersistedState,
|
||||||
method: string,
|
method: string,
|
||||||
|
|||||||
52
src/utils/exportMetrics.js
Normal file
52
src/utils/exportMetrics.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* 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 type {MiddlewareAPI} from '../reducers';
|
||||||
|
import {serialize} from './serialization.js';
|
||||||
|
import type {FlipperPlugin, FlipperDevicePlugin} from 'flipper';
|
||||||
|
|
||||||
|
type MetricType = Map<string, Map<string, string | number>>;
|
||||||
|
|
||||||
|
export type ExportMetricType = Map<string, MetricType>;
|
||||||
|
|
||||||
|
export default async function exportMetrics(
|
||||||
|
store: MiddlewareAPI,
|
||||||
|
): Promise<string> {
|
||||||
|
const state = store.getState();
|
||||||
|
let metrics: ExportMetricType = new Map();
|
||||||
|
for (let key in state.pluginStates) {
|
||||||
|
const pluginStateData = state.pluginStates[key];
|
||||||
|
const arr = key.split('#');
|
||||||
|
const pluginName = arr.pop();
|
||||||
|
const clientID = arr.join('#');
|
||||||
|
const pluginsMap: Map<
|
||||||
|
string,
|
||||||
|
Class<FlipperDevicePlugin<> | FlipperPlugin<>>,
|
||||||
|
> = new Map([]);
|
||||||
|
state.plugins.clientPlugins.forEach((val, key) => {
|
||||||
|
pluginsMap.set(key, val);
|
||||||
|
});
|
||||||
|
state.plugins.devicePlugins.forEach((val, key) => {
|
||||||
|
pluginsMap.set(key, val);
|
||||||
|
});
|
||||||
|
const exportMetrics1: ?(
|
||||||
|
persistedState: any,
|
||||||
|
) => Promise<Map<string, string | number>> = pluginsMap.get(pluginName)
|
||||||
|
?.exportMetrics;
|
||||||
|
if (pluginsMap.has(pluginName) && exportMetrics1) {
|
||||||
|
const metricMap = await exportMetrics1(pluginStateData);
|
||||||
|
const pluginMap = new Map([[pluginName, metricMap]]);
|
||||||
|
if (!metrics.get(clientID)) {
|
||||||
|
metrics.set(clientID, pluginMap);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const prevMetricMap = metrics.get(clientID);
|
||||||
|
// $FlowFixMe: prevMetricMap cannot be null, because clientID is added only when the pluingMetricMap is available
|
||||||
|
metrics.set(clientID, new Map([...prevMetricMap, ...pluginMap]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.resolve(serialize(metrics));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user