2017-06-28 10:20:22 +02:00
|
|
|
'use strict';
|
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
const Controller = require('../controller');
|
2017-06-28 10:20:22 +02:00
|
|
|
const ClientMetrics = require('../../client-metrics');
|
2018-12-19 10:36:56 +01:00
|
|
|
const schema = require('./metrics-schema');
|
|
|
|
const { UPDATE_APPLICATION } = require('../../permissions');
|
2018-01-17 15:31:53 +01:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
class MetricsController extends Controller {
|
2018-12-19 14:50:01 +01:00
|
|
|
constructor(config) {
|
|
|
|
super(config);
|
2019-04-30 21:14:23 +02:00
|
|
|
this.logger = config.getLogger('/admin-api/metrics.js');
|
2018-12-19 14:50:01 +01:00
|
|
|
const {
|
2018-12-19 10:36:56 +01:00
|
|
|
clientMetricsStore,
|
|
|
|
clientInstanceStore,
|
|
|
|
clientApplicationsStore,
|
|
|
|
strategyStore,
|
|
|
|
featureToggleStore,
|
2018-12-19 14:50:01 +01:00
|
|
|
} = config.stores;
|
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
this.metrics = new ClientMetrics(clientMetricsStore);
|
|
|
|
this.clientInstanceStore = clientInstanceStore;
|
|
|
|
this.clientApplicationsStore = clientApplicationsStore;
|
|
|
|
this.strategyStore = strategyStore;
|
|
|
|
this.featureToggleStore = featureToggleStore;
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
this.get('/seen-toggles', this.getSeenToggles);
|
|
|
|
this.get('/seen-apps', this.getSeenApps);
|
|
|
|
this.get('/feature-toggles', this.getFeatureToggles);
|
|
|
|
this.get('/feature-toggles/:name', this.getFeatureToggle);
|
2018-12-19 10:36:56 +01:00
|
|
|
this.post(
|
|
|
|
'/applications/:appName',
|
|
|
|
this.createApplication,
|
2020-04-14 22:29:11 +02:00
|
|
|
UPDATE_APPLICATION,
|
2018-12-19 10:36:56 +01:00
|
|
|
);
|
2018-12-04 08:50:45 +01:00
|
|
|
this.get('/applications/', this.getApplications);
|
|
|
|
this.get('/applications/:appName', this.getApplication);
|
|
|
|
}
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
getSeenToggles(req, res) {
|
|
|
|
const seenAppToggles = this.metrics.getAppsWithToggles();
|
2017-06-28 10:20:22 +02:00
|
|
|
res.json(seenAppToggles);
|
2018-12-04 08:50:45 +01:00
|
|
|
}
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
async getSeenApps(req, res) {
|
|
|
|
const seenApps = this.metrics.getSeenAppsPerToggle();
|
|
|
|
const applications = await this.clientApplicationsStore.getApplications();
|
|
|
|
const metaData = applications.reduce((result, entry) => {
|
2020-04-14 22:29:11 +02:00
|
|
|
// eslint-disable-next-line no-param-reassign
|
2018-12-04 08:50:45 +01:00
|
|
|
result[entry.appName] = entry;
|
|
|
|
return result;
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
Object.keys(seenApps).forEach(key => {
|
|
|
|
seenApps[key] = seenApps[key].map(entry => {
|
|
|
|
if (metaData[entry.appName]) {
|
2020-04-14 22:29:11 +02:00
|
|
|
return { ...entry, ...metaData[entry.appName] };
|
2018-12-04 08:50:45 +01:00
|
|
|
}
|
|
|
|
return entry;
|
2017-06-28 10:20:22 +02:00
|
|
|
});
|
2018-12-04 08:50:45 +01:00
|
|
|
});
|
|
|
|
res.json(seenApps);
|
|
|
|
}
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
getFeatureToggles(req, res) {
|
|
|
|
res.json(this.metrics.getTogglesMetrics());
|
|
|
|
}
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
getFeatureToggle(req, res) {
|
2020-04-14 22:29:11 +02:00
|
|
|
const { name } = req.params;
|
2018-12-04 08:50:45 +01:00
|
|
|
const data = this.metrics.getTogglesMetrics();
|
2017-06-28 10:20:22 +02:00
|
|
|
const lastHour = data.lastHour[name] || {};
|
|
|
|
const lastMinute = data.lastMinute[name] || {};
|
|
|
|
res.json({
|
|
|
|
lastHour,
|
|
|
|
lastMinute,
|
|
|
|
});
|
2018-12-04 08:50:45 +01:00
|
|
|
}
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
async createApplication(req, res) {
|
2020-04-14 22:29:11 +02:00
|
|
|
const input = { ...req.body, appName: req.params.appName };
|
2020-01-02 19:23:52 +01:00
|
|
|
const { value: applicationData, error } = schema.validate(input);
|
2018-12-19 10:36:56 +01:00
|
|
|
|
|
|
|
if (error) {
|
2019-04-30 21:14:23 +02:00
|
|
|
this.logger.warn('Invalid application data posted', error);
|
2018-12-19 10:36:56 +01:00
|
|
|
return res.status(400).json(error);
|
|
|
|
}
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
try {
|
2018-12-19 10:36:56 +01:00
|
|
|
await this.clientApplicationsStore.upsert(applicationData);
|
2020-04-14 22:29:11 +02:00
|
|
|
return res.status(202).end();
|
2018-12-04 08:50:45 +01:00
|
|
|
} catch (err) {
|
2019-04-30 21:14:23 +02:00
|
|
|
this.logger.error(err);
|
2020-04-14 22:29:11 +02:00
|
|
|
return res.status(500).end();
|
2018-12-04 08:50:45 +01:00
|
|
|
}
|
2017-06-28 10:20:22 +02:00
|
|
|
}
|
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
async getApplications(req, res) {
|
|
|
|
try {
|
|
|
|
const applications = await this.clientApplicationsStore.getApplications(
|
2020-04-14 22:29:11 +02:00
|
|
|
req.query,
|
2018-12-04 08:50:45 +01:00
|
|
|
);
|
|
|
|
res.json({ applications });
|
|
|
|
} catch (err) {
|
2019-04-30 21:14:23 +02:00
|
|
|
this.logger.error(err);
|
2018-12-04 08:50:45 +01:00
|
|
|
res.status(500).end();
|
|
|
|
}
|
|
|
|
}
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
async getApplication(req, res) {
|
2020-04-14 22:29:11 +02:00
|
|
|
const { appName } = req.params;
|
2018-12-04 08:50:45 +01:00
|
|
|
const seenToggles = this.metrics.getSeenTogglesByAppName(appName);
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
try {
|
|
|
|
const [
|
|
|
|
application,
|
|
|
|
instances,
|
|
|
|
strategies,
|
|
|
|
features,
|
|
|
|
] = await Promise.all([
|
|
|
|
this.clientApplicationsStore.getApplication(appName),
|
|
|
|
this.clientInstanceStore.getByAppName(appName),
|
|
|
|
this.strategyStore.getStrategies(),
|
|
|
|
this.featureToggleStore.getFeatures(),
|
|
|
|
]);
|
|
|
|
|
|
|
|
const appDetails = {
|
|
|
|
appName: application.appName,
|
|
|
|
createdAt: application.createdAt,
|
|
|
|
description: application.description,
|
|
|
|
url: application.url,
|
|
|
|
color: application.color,
|
|
|
|
icon: application.icon,
|
|
|
|
strategies: application.strategies.map(name => {
|
|
|
|
const found = strategies.find(f => f.name === name);
|
2020-04-14 22:29:11 +02:00
|
|
|
return found || { name, notFound: true };
|
2018-12-04 08:50:45 +01:00
|
|
|
}),
|
|
|
|
instances,
|
|
|
|
seenToggles: seenToggles.map(name => {
|
|
|
|
const found = features.find(f => f.name === name);
|
2020-04-14 22:29:11 +02:00
|
|
|
return found || { name, notFound: true };
|
2018-12-04 08:50:45 +01:00
|
|
|
}),
|
|
|
|
links: {
|
|
|
|
self: `/api/applications/${application.appName}`,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
res.json(appDetails);
|
|
|
|
} catch (err) {
|
2019-04-30 21:14:23 +02:00
|
|
|
this.logger.error(err);
|
2018-12-04 08:50:45 +01:00
|
|
|
res.status(500).end();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-06-28 10:20:22 +02:00
|
|
|
|
2018-12-04 08:50:45 +01:00
|
|
|
module.exports = MetricsController;
|