From 738c26fd62873fa76e13e884808b214de9f5cb49 Mon Sep 17 00:00:00 2001 From: ivaosthu Date: Tue, 4 Dec 2018 08:50:45 +0100 Subject: [PATCH] chore(modernize): Admin MetricsController --- lib/routes/admin-api/index.js | 4 +- lib/routes/admin-api/metrics.js | 210 ++++++++++++++++---------------- 2 files changed, 109 insertions(+), 105 deletions(-) diff --git a/lib/routes/admin-api/index.js b/lib/routes/admin-api/index.js index f8b9002bbf..88a6e76b5b 100644 --- a/lib/routes/admin-api/index.js +++ b/lib/routes/admin-api/index.js @@ -5,7 +5,7 @@ const FeatureController = require('./feature.js'); const ArchiveController = require('./archive.js'); const EventController = require('./event.js'); const strategies = require('./strategy'); -const metrics = require('./metrics'); +const MetricsController = require('./metrics'); const UserController = require('./user'); const apiDef = require('./api-def.json'); @@ -20,7 +20,7 @@ class AdminApi extends Controller { this.app.use('/archive', new ArchiveController(stores).router); this.app.use('/strategies', strategies.router(config)); this.app.use('/events', new EventController(stores).router); - this.app.use('/metrics', metrics.router(config)); + this.app.use('/metrics', new MetricsController(stores).router); this.app.use('/user', new UserController().router); } diff --git a/lib/routes/admin-api/metrics.js b/lib/routes/admin-api/metrics.js index ed68eeb195..54d2622db4 100644 --- a/lib/routes/admin-api/metrics.js +++ b/lib/routes/admin-api/metrics.js @@ -1,138 +1,142 @@ 'use strict'; -const { Router } = require('express'); - +const Controller = require('../controller'); const logger = require('../../logger')('/admin-api/metrics.js'); const ClientMetrics = require('../../client-metrics'); -const catchLogAndSendErrorResponse = (err, res) => { - logger.error(err); - res.status(500).end(); -}; - -exports.router = function(config) { - const { +class MetricsController extends Controller { + constructor({ clientMetricsStore, clientInstanceStore, clientApplicationsStore, strategyStore, featureToggleStore, - } = config.stores; + }) { + super(); + this.metrics = new ClientMetrics(clientMetricsStore); + this.clientInstanceStore = clientInstanceStore; + this.clientApplicationsStore = clientApplicationsStore; + this.strategyStore = strategyStore; + this.featureToggleStore = featureToggleStore; - const metrics = new ClientMetrics(clientMetricsStore); - const router = Router(); + 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); + this.get('/applications/', this.getApplications); + this.get('/applications/:appName', this.getApplication); + } - router.get('/seen-toggles', (req, res) => { - const seenAppToggles = metrics.getAppsWithToggles(); + getSeenToggles(req, res) { + const seenAppToggles = this.metrics.getAppsWithToggles(); res.json(seenAppToggles); - }); + } - router.get('/seen-apps', (req, res) => { - const seenApps = metrics.getSeenAppsPerToggle(); - clientApplicationsStore - .getApplications() - .then(toLookup) - .then(metaData => { - Object.keys(seenApps).forEach(key => { - seenApps[key] = seenApps[key].map(entry => { - if (metaData[entry.appName]) { - return Object.assign( - {}, - entry, - metaData[entry.appName] - ); - } - return entry; - }); - }); - res.json(seenApps); + async getSeenApps(req, res) { + const seenApps = this.metrics.getSeenAppsPerToggle(); + const applications = await this.clientApplicationsStore.getApplications(); + const metaData = applications.reduce((result, entry) => { + result[entry.appName] = entry; + return result; + }, {}); + + Object.keys(seenApps).forEach(key => { + seenApps[key] = seenApps[key].map(entry => { + if (metaData[entry.appName]) { + return Object.assign({}, entry, metaData[entry.appName]); + } + return entry; }); - }); + }); + res.json(seenApps); + } - router.get('/feature-toggles', (req, res) => { - res.json(metrics.getTogglesMetrics()); - }); + getFeatureToggles(req, res) { + res.json(this.metrics.getTogglesMetrics()); + } - router.get('/feature-toggles/:name', (req, res) => { + getFeatureToggle(req, res) { const name = req.params.name; - const data = metrics.getTogglesMetrics(); + const data = this.metrics.getTogglesMetrics(); const lastHour = data.lastHour[name] || {}; const lastMinute = data.lastMinute[name] || {}; res.json({ lastHour, lastMinute, }); - }); + } - router.post('/applications/:appName', (req, res) => { + // Todo: add joi-schema validation + async createApplication(req, res) { const input = Object.assign({}, req.body, { appName: req.params.appName, }); - clientApplicationsStore - .upsert(input) - .then(() => res.status(202).end()) - .catch(err => catchLogAndSendErrorResponse(err, res)); - }); - function toLookup(metaData) { - return metaData.reduce((result, entry) => { - result[entry.appName] = entry; - return result; - }, {}); + try { + await this.clientApplicationsStore.upsert(input); + res.status(202).end(); + } catch (err) { + logger.error(err); + res.status(500).end(); + } } - router.get('/applications/', (req, res) => { - clientApplicationsStore - .getApplications(req.query) - .then(applications => res.json({ applications })) - .catch(err => catchLogAndSendErrorResponse(err, res)); - }); + async getApplications(req, res) { + try { + const applications = await this.clientApplicationsStore.getApplications( + req.query + ); + res.json({ applications }); + } catch (err) { + logger.error(err); + res.status(500).end(); + } + } - router.get('/applications/:appName', (req, res) => { + async getApplication(req, res) { const appName = req.params.appName; - const seenToggles = metrics.getSeenTogglesByAppName(appName); + const seenToggles = this.metrics.getSeenTogglesByAppName(appName); - Promise.all([ - clientApplicationsStore.getApplication(appName), - clientInstanceStore.getByAppName(appName), - strategyStore.getStrategies(), - featureToggleStore.getFeatures(), - ]) - .then(([application, instances, strategies, features]) => { - 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( - feature => feature.name === name - ); - if (found) { - return found; - } - return { name, notFound: true }; - }), - instances, - seenToggles: seenToggles.map(name => { - const found = features.find( - feature => feature.name === name - ); - if (found) { - return found; - } - return { name, notFound: true }; - }), - links: { - self: `/api/applications/${application.appName}`, - }, - }; - res.json(appDetails); - }) - .catch(err => catchLogAndSendErrorResponse(err, res)); - }); + try { + const [ + application, + instances, + strategies, + features, + ] = await Promise.all([ + this.clientApplicationsStore.getApplication(appName), + this.clientInstanceStore.getByAppName(appName), + this.strategyStore.getStrategies(), + this.featureToggleStore.getFeatures(), + ]); - return router; -}; + 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 ? found : { name, notFound: true }; + }), + instances, + seenToggles: seenToggles.map(name => { + const found = features.find(f => f.name === name); + return found ? found : { name, notFound: true }; + }), + links: { + self: `/api/applications/${application.appName}`, + }, + }; + res.json(appDetails); + } catch (err) { + logger.error(err); + res.status(500).end(); + } + } +} + +module.exports = MetricsController;