Add recordSuccessMetric utility

Summary: Wraps a future and records the success rate. This will be stored along with the sessionId and the userId, so we can drill down and get the success rate at different levels.

Reviewed By: passy

Differential Revision: D13635049

fbshipit-source-id: 4e0e6bdc0f9b76b08cf37c5d9fe87909f7338534
This commit is contained in:
John Knox
2019-01-14 06:25:35 -08:00
committed by Facebook Github Bot
parent 4a5dae8f4f
commit 90de3c6868
3 changed files with 98 additions and 12 deletions

View File

@@ -17,6 +17,7 @@ import {Single} from 'rsocket-flowable';
import Client from './Client.js';
import type {UninitializedClient} from './UninitializedClient';
import {RecurringError} from './utils/errors';
import {recordSuccessMetric} from './utils/metrics';
const EventEmitter = (require('events'): any);
const invariant = require('invariant');
@@ -177,8 +178,15 @@ export default class Server extends EventEmitter {
const {csr, destination} = json;
return new Single(subscriber => {
subscriber.onSubscribe();
this.certificateProvider
.processCertificateSigningRequest(csr, clientData.os, destination)
recordSuccessMetric(
this.certificateProvider.processCertificateSigningRequest(
csr,
clientData.os,
destination,
),
'processCertificateSigningRequest',
this.logger,
)
.then(result => {
subscriber.onComplete({
data: JSON.stringify({
@@ -190,20 +198,10 @@ export default class Server extends EventEmitter {
client,
deviceId: result.deviceId,
});
this.logger.track(
'success-rate',
'processCertificateSigningRequest',
1,
);
})
.catch(e => {
subscriber.onError(e);
this.emit('client-setup-error', {client, error: e});
this.logger.track(
'success-rate',
'processCertificateSigningRequest',
0,
);
});
});
}

View File

@@ -0,0 +1,58 @@
/**
* 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 {recordSuccessMetric} from '../metrics';
import type Logger from '../../fb-stubs/Logger';
//$FlowFixMe pretend logger is the right type
const logger: Logger = {
track: jest.fn(),
};
beforeAll(() => {
logger.track.mockClear();
});
test('Wrapping a successful promise preserves result and logs correctly', () => {
const successPromise = Promise.resolve('Yay!');
const wrappedPromise = recordSuccessMetric(
successPromise,
'test metric',
logger,
);
return wrappedPromise
.then(wrappedValue => {
expect(wrappedValue).toBe('Yay!');
})
.then(() => {
expect(logger.track).toHaveBeenCalledWith(
'success-rate',
'test metric',
1,
);
});
});
test('Wrapping a rejected promise preserves result and logs correctly', () => {
const successPromise = Promise.reject('Oh no!');
const wrappedPromise = recordSuccessMetric(
successPromise,
'test metric',
logger,
);
expect.assertions(2); // Make sure to fail if catch block isn't visited
return wrappedPromise
.catch(wrappedValue => {
expect(wrappedValue).toBe('Oh no!');
})
.then(() => {
expect(logger.track).toHaveBeenCalledWith(
'success-rate',
'test metric',
0,
);
});
});

30
src/utils/metrics.js Normal file
View File

@@ -0,0 +1,30 @@
/**
* 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 Logger from '../fb-stubs/Logger';
/*
* 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.
*/
export function recordSuccessMetric(
promise: Promise<*>,
name: string,
logger: Logger,
): Promise<*> {
return promise.then(
fulfilledValue => {
logger.track('success-rate', name, 1);
return fulfilledValue;
},
rejectionReason => {
logger.track('success-rate', name, 0);
return Promise.reject(rejectionReason);
},
);
}