mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
Cleanup route/metrics a bit
This commit is contained in:
parent
b14c766e97
commit
4f25533230
@ -22,7 +22,7 @@ class ClientMetricsStore {
|
|||||||
this.db(TABLE)
|
this.db(TABLE)
|
||||||
.whereRaw('created_at < now() - interval \'1 hour\'')
|
.whereRaw('created_at < now() - interval \'1 hour\'')
|
||||||
.del()
|
.del()
|
||||||
.then((res) => logger.info(`Delted ${res} metrics`));
|
.then((res) => logger.info(`Deleted ${res} metrics`));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert new client metrics
|
// Insert new client metrics
|
||||||
|
24
lib/routes/metrics-schema.js
Normal file
24
lib/routes/metrics-schema.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
const joi = require('joi');
|
||||||
|
|
||||||
|
const clientMetricsSchema = joi.object().keys({
|
||||||
|
appName: joi.string().required(),
|
||||||
|
instanceId: joi.string().required(),
|
||||||
|
bucket: joi.object().required()
|
||||||
|
.keys({
|
||||||
|
start: joi.date().required(),
|
||||||
|
stop: joi.date().required(),
|
||||||
|
toggles: joi.object(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const clientRegisterSchema = joi.object().keys({
|
||||||
|
appName: joi.string().required(),
|
||||||
|
instanceId: joi.string().required(),
|
||||||
|
strategies: joi.array()
|
||||||
|
.required()
|
||||||
|
.items(joi.string(), joi.any().strip()),
|
||||||
|
started: joi.date().required(),
|
||||||
|
interval: joi.number().required(),
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = { clientMetricsSchema, clientRegisterSchema }
|
@ -4,6 +4,7 @@ const logger = require('../logger');
|
|||||||
const ClientMetrics = require('../client-metrics');
|
const ClientMetrics = require('../client-metrics');
|
||||||
const ClientMetricsService = require('../client-metrics/service');
|
const ClientMetricsService = require('../client-metrics/service');
|
||||||
const joi = require('joi');
|
const joi = require('joi');
|
||||||
|
const { clientMetricsSchema, clientRegisterSchema } = require('./metrics-schema');
|
||||||
|
|
||||||
module.exports = function (app, config) {
|
module.exports = function (app, config) {
|
||||||
const {
|
const {
|
||||||
@ -11,6 +12,7 @@ module.exports = function (app, config) {
|
|||||||
clientStrategyStore,
|
clientStrategyStore,
|
||||||
clientInstanceStore,
|
clientInstanceStore,
|
||||||
} = config.stores;
|
} = config.stores;
|
||||||
|
|
||||||
const metrics = new ClientMetrics();
|
const metrics = new ClientMetrics();
|
||||||
const service = new ClientMetricsService(clientMetricsStore);
|
const service = new ClientMetricsService(clientMetricsStore);
|
||||||
|
|
||||||
@ -28,45 +30,17 @@ module.exports = function (app, config) {
|
|||||||
res.json(metrics.getTogglesMetrics());
|
res.json(metrics.getTogglesMetrics());
|
||||||
});
|
});
|
||||||
|
|
||||||
const clientMetricsSchema = joi.object().keys({
|
|
||||||
appName: joi.string().required(),
|
|
||||||
instanceId: joi.string().required(),
|
|
||||||
bucket: joi.object().required()
|
|
||||||
.keys({
|
|
||||||
start: joi.date().required(),
|
|
||||||
stop: joi.date().required(),
|
|
||||||
toggles: joi.object()
|
|
||||||
.required()
|
|
||||||
.unknown()
|
|
||||||
.min(1)
|
|
||||||
.max(1000),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
app.post('/client/metrics', (req, res) => {
|
app.post('/client/metrics', (req, res) => {
|
||||||
try {
|
const data = req.body;
|
||||||
const data = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
|
joi.validate(data, clientMetricsSchema, (err, cleaned) => {
|
||||||
const result = joi.validate(data, clientMetricsSchema);
|
if (err) {
|
||||||
if (result.error) {
|
return res.status(400).json(err);
|
||||||
throw result.error;
|
|
||||||
}
|
}
|
||||||
service
|
service.insert(cleaned)
|
||||||
.insert(result.value)
|
|
||||||
.catch(e => logger.error('Error inserting metrics data', e));
|
.catch(e => logger.error('Error inserting metrics data', e));
|
||||||
} catch (e) {
|
|
||||||
logger.error('Error receiving metrics', e);
|
res.status(202).end();
|
||||||
}
|
});
|
||||||
res.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
const clientRegisterSchema = joi.object().keys({
|
|
||||||
appName: joi.string().required(),
|
|
||||||
instanceId: joi.string().required(),
|
|
||||||
strategies: joi.array()
|
|
||||||
.required()
|
|
||||||
.items(joi.string(), joi.any().strip()),
|
|
||||||
started: joi.date().required(),
|
|
||||||
interval: joi.number().required(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/client/register', (req, res) => {
|
app.post('/client/register', (req, res) => {
|
||||||
@ -84,10 +58,10 @@ module.exports = function (app, config) {
|
|||||||
instanceId: cleaned.instanceId,
|
instanceId: cleaned.instanceId,
|
||||||
clientIp,
|
clientIp,
|
||||||
}))
|
}))
|
||||||
.then(() => console.log('new client registerd'))
|
.then(() => logger.info('New client registered!'))
|
||||||
.catch((error) => logger.error('Error registering client', error));
|
.catch((error) => logger.error('Error registering client', error));
|
||||||
|
|
||||||
res.end();
|
res.status(202).end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -98,6 +72,6 @@ module.exports = function (app, config) {
|
|||||||
app.get('/client/instances', (req, res) => {
|
app.get('/client/instances', (req, res) => {
|
||||||
clientInstanceStore.getAll()
|
clientInstanceStore.getAll()
|
||||||
.then(data => res.json(data))
|
.then(data => res.json(data))
|
||||||
.catch(err => console.error(err));
|
.catch(err => logger.error(err));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,32 +1,23 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const clientMetricsStore = require('./mocks/fake-metrics-store');
|
const store = require('./mocks/store');
|
||||||
const featureToggleStore = require('./mocks/fake-feature-toggle-store');
|
|
||||||
const strategyStore = require('./mocks/fake-strategies-store');
|
|
||||||
|
|
||||||
const supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const sinon = require('sinon');
|
|
||||||
|
|
||||||
let request;
|
let request;
|
||||||
|
let featureToggleStore;
|
||||||
|
|
||||||
describe('Unit: The features api', () => {
|
describe('Unit: The features api', () => {
|
||||||
beforeEach(done => {
|
beforeEach(done => {
|
||||||
featureToggleStore.reset();
|
const stores = store.createStores();
|
||||||
|
|
||||||
const app = require('../../../app')({
|
const app = require('../../../app')({
|
||||||
baseUriPath: '',
|
baseUriPath: '',
|
||||||
stores: {
|
stores: stores,
|
||||||
db: sinon.stub(),
|
|
||||||
eventStore: sinon.stub(),
|
|
||||||
featureToggleStore,
|
|
||||||
clientMetricsStore,
|
|
||||||
strategyStore,
|
|
||||||
clientStrategyStore: sinon.stub(),
|
|
||||||
clientInstanceStore: sinon.stub(),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
featureToggleStore = stores.featureToggleStore;
|
||||||
request = supertest(app);
|
request = supertest(app);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -1,28 +1,17 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const clientMetricsStore = require('./mocks/fake-metrics-store');
|
const store = require('./mocks/store');
|
||||||
const clientStrategyStore = require('./mocks/fake-client-strategy-store');
|
|
||||||
const clientInstanceStore = require('./mocks/fake-client-instance-store');
|
|
||||||
|
|
||||||
const supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const sinon = require('sinon');
|
|
||||||
|
|
||||||
let request;
|
let request;
|
||||||
|
|
||||||
describe('Unit: The metrics api', () => {
|
describe('Unit: The metrics api', () => {
|
||||||
beforeEach(done => {
|
beforeEach(done => {
|
||||||
|
const stores = store.createStores();
|
||||||
const app = require('../../../app')({
|
const app = require('../../../app')({
|
||||||
baseUriPath: '',
|
baseUriPath: '',
|
||||||
stores: {
|
stores: stores,
|
||||||
db: sinon.stub(),
|
|
||||||
eventStore: sinon.stub(),
|
|
||||||
featureToggleStore: sinon.stub(),
|
|
||||||
clientMetricsStore,
|
|
||||||
strategyStore: sinon.stub(),
|
|
||||||
clientStrategyStore,
|
|
||||||
clientInstanceStore,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
request = supertest(app);
|
request = supertest(app);
|
||||||
@ -32,8 +21,14 @@ describe('Unit: The metrics api', () => {
|
|||||||
it('should register client', (done) => {
|
it('should register client', (done) => {
|
||||||
request
|
request
|
||||||
.post('/api/client/register')
|
.post('/api/client/register')
|
||||||
.send({ appName: 'demo', instanceId: 'test', strategies: ['default'], started: Date.now(), interval: 10 })
|
.send({
|
||||||
.expect(200, done);
|
appName: 'demo',
|
||||||
|
instanceId: 'test',
|
||||||
|
strategies: ['default'],
|
||||||
|
started: Date.now(),
|
||||||
|
interval: 10
|
||||||
|
})
|
||||||
|
.expect(202, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require appName field', (done) => {
|
it('should require appName field', (done) => {
|
||||||
@ -41,4 +36,33 @@ describe('Unit: The metrics api', () => {
|
|||||||
.post('/api/client/register')
|
.post('/api/client/register')
|
||||||
.expect(400, done)
|
.expect(400, done)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should require strategies field', (done) => {
|
||||||
|
request
|
||||||
|
.post('/api/client/register')
|
||||||
|
.send({
|
||||||
|
appName: 'demo',
|
||||||
|
instanceId: 'test',
|
||||||
|
//strategies: ['default'],
|
||||||
|
started: Date.now(),
|
||||||
|
interval: 10
|
||||||
|
})
|
||||||
|
.expect(400, done)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should accept client metrics', (done) => {
|
||||||
|
request
|
||||||
|
.post('/api/client/metrics')
|
||||||
|
.send({
|
||||||
|
appName: 'demo',
|
||||||
|
instanceId: '1',
|
||||||
|
bucket: {
|
||||||
|
start: Date.now(),
|
||||||
|
stop: Date.now(),
|
||||||
|
toggles: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.expect(202, done)
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
reset: () => {},
|
||||||
insert: () => Promise.resolve(),
|
insert: () => Promise.resolve(),
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
reset: () => {},
|
||||||
insert: () => Promise.resolve(),
|
insert: () => Promise.resolve(),
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
reset: () => {},
|
||||||
getMetricsLastHour: () => Promise.resolve([]),
|
getMetricsLastHour: () => Promise.resolve([]),
|
||||||
|
insert: () => Promise.resolve(),
|
||||||
};
|
};
|
||||||
|
27
test/unit/routes/mocks/store.js
Normal file
27
test/unit/routes/mocks/store.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const sinon = require('sinon');
|
||||||
|
|
||||||
|
const clientMetricsStore = require('./fake-metrics-store');
|
||||||
|
const clientStrategyStore = require('./fake-client-strategy-store');
|
||||||
|
const clientInstanceStore = require('./fake-client-instance-store');
|
||||||
|
const featureToggleStore = require('./fake-feature-toggle-store');
|
||||||
|
const strategyStore = require('./fake-strategies-store');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createStores: () => {
|
||||||
|
clientMetricsStore.reset();
|
||||||
|
clientStrategyStore.reset();
|
||||||
|
clientInstanceStore.reset();
|
||||||
|
featureToggleStore.reset();
|
||||||
|
strategyStore.reset();
|
||||||
|
|
||||||
|
return {
|
||||||
|
db: sinon.stub(),
|
||||||
|
clientMetricsStore,
|
||||||
|
clientStrategyStore,
|
||||||
|
clientInstanceStore,
|
||||||
|
featureToggleStore,
|
||||||
|
strategyStore,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
@ -1,32 +1,23 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const clientMetricsStore = require('./mocks/fake-metrics-store');
|
const store = require('./mocks/store');
|
||||||
const featureToggleStore = require('./mocks/fake-feature-toggle-store');
|
|
||||||
const strategyStore = require('./mocks/fake-strategies-store');
|
|
||||||
|
|
||||||
const supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const sinon = require('sinon');
|
const sinon = require('sinon');
|
||||||
|
|
||||||
let request;
|
let request;
|
||||||
|
let strategyStore;
|
||||||
|
|
||||||
describe('Unit: The strategies api', () => {
|
describe('Unit: The strategies api', () => {
|
||||||
beforeEach(done => {
|
beforeEach(done => {
|
||||||
strategyStore.reset();
|
const stores = store.createStores();
|
||||||
|
|
||||||
const app = require('../../../app')({
|
const app = require('../../../app')({
|
||||||
baseUriPath: '',
|
baseUriPath: '',
|
||||||
stores: {
|
stores: stores,
|
||||||
db: sinon.stub(),
|
|
||||||
eventStore: sinon.stub(),
|
|
||||||
featureToggleStore,
|
|
||||||
clientMetricsStore,
|
|
||||||
strategyStore,
|
|
||||||
clientStrategyStore: sinon.stub(),
|
|
||||||
clientInstanceStore: sinon.stub(),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
strategyStore = stores.strategyStore;
|
||||||
request = supertest(app);
|
request = supertest(app);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user