1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-23 00:22:19 +01:00
unleash.unleash/lib/routes/admin-api/metrics.js
Ivar Conradi Østhus cdfba8f7b1 feat: Adds last-seen dat on toggles
When an application updates metrics for a toggle we now
stores the timestamp on the toggle when it was last seen
used by an application. This will make it much easier to
detect toggles not in use anymore.

closes #642
2020-12-22 11:05:00 +01:00

177 lines
5.7 KiB
JavaScript

const Controller = require('../controller');
const schema = require('./metrics-schema');
const { UPDATE_APPLICATION } = require('../../permissions');
class MetricsController extends Controller {
constructor(config, { clientMetricsService }) {
super(config);
this.logger = config.getLogger('/admin-api/metrics.js');
const {
clientInstanceStore,
clientApplicationsStore,
strategyStore,
featureToggleStore,
} = config.stores;
this.metrics = clientMetricsService;
this.clientInstanceStore = clientInstanceStore;
this.clientApplicationsStore = clientApplicationsStore;
this.strategyStore = strategyStore;
this.featureToggleStore = featureToggleStore;
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);
this.post(
'/applications/:appName',
this.createApplication,
UPDATE_APPLICATION,
);
this.delete(
'/applications/:appName',
this.deleteApplication,
UPDATE_APPLICATION,
);
this.get('/applications/', this.getApplications);
this.get('/applications/:appName', this.getApplication);
}
getSeenToggles(req, res) {
const seenAppToggles = this.metrics.getAppsWithToggles();
res.json(seenAppToggles);
}
async getSeenApps(req, res) {
const seenApps = this.metrics.getSeenAppsPerToggle();
const applications = await this.clientApplicationsStore.getApplications();
const metaData = applications.reduce((result, entry) => {
// eslint-disable-next-line no-param-reassign
result[entry.appName] = entry;
return result;
}, {});
Object.keys(seenApps).forEach(key => {
seenApps[key] = seenApps[key].map(entry => {
if (metaData[entry.appName]) {
return { ...entry, ...metaData[entry.appName] };
}
return entry;
});
});
res.json(seenApps);
}
getFeatureToggles(req, res) {
res.json(this.metrics.getTogglesMetrics());
}
getFeatureToggle(req, res) {
const { name } = req.params;
const data = this.metrics.getTogglesMetrics();
const lastHour = data.lastHour[name] || {};
const lastMinute = data.lastMinute[name] || {};
res.json({
lastHour,
lastMinute,
});
}
async deleteApplication(req, res) {
const { appName } = req.params;
try {
await this.clientApplicationsStore.getApplication(appName);
} catch (e) {
this.logger.error(e);
res.status(409).end();
return;
}
try {
await this.clientInstanceStore.deleteForApplication(appName);
await this.clientApplicationsStore.deleteApplication(appName);
res.status(200).end();
} catch (e) {
this.logger.error(e);
res.status(500).end();
}
}
async createApplication(req, res) {
const input = { ...req.body, appName: req.params.appName };
const { value: applicationData, error } = schema.validate(input);
if (error) {
this.logger.warn('Invalid application data posted', error);
return res.status(400).json(error);
}
try {
await this.clientApplicationsStore.upsert(applicationData);
return res.status(202).end();
} catch (err) {
this.logger.error(err);
return res.status(500).end();
}
}
async getApplications(req, res) {
try {
const applications = await this.clientApplicationsStore.getApplications(
req.query,
);
res.json({ applications });
} catch (err) {
this.logger.error(err);
res.status(500).end();
}
}
async getApplication(req, res) {
const { appName } = req.params;
const seenToggles = this.metrics.getSeenTogglesByAppName(appName);
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);
return found || { name, notFound: true };
}),
instances,
seenToggles: seenToggles.map(name => {
const found = features.find(f => f.name === name);
return found || { name, notFound: true };
}),
links: {
self: `/api/applications/${application.appName}`,
},
};
res.json(appDetails);
} catch (err) {
this.logger.error(err);
res.status(500).end();
}
}
}
module.exports = MetricsController;