mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | ||
| 
 | ||
| const logger = require('../logger');
 | ||
| const ClientMetrics = require('../client-metrics');
 | ||
| const joi = require('joi');
 | ||
| const { clientMetricsSchema, clientRegisterSchema } = require('./metrics-schema');
 | ||
| const { catchLogAndSendErrorResponse } = require('./route-utils');
 | ||
| 
 | ||
| module.exports = function (app, config) {
 | ||
|     const {
 | ||
|         clientMetricsStore,
 | ||
|         clientInstanceStore,
 | ||
|         clientApplicationsStore,
 | ||
|         strategyStore,
 | ||
|         featureToggleStore,
 | ||
|     } = config.stores;
 | ||
| 
 | ||
|     const metrics = new ClientMetrics(clientMetricsStore);
 | ||
| 
 | ||
|     app.get('/client/seen-toggles', (req, res) => {
 | ||
|         const seenAppToggles = metrics.getAppsWithToggles();
 | ||
|         res.json(seenAppToggles);
 | ||
|     });
 | ||
| 
 | ||
|     app.get('/client/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);
 | ||
|             });
 | ||
|     });
 | ||
| 
 | ||
|     app.get('/client/metrics/feature-toggles', (req, res) => {
 | ||
|         res.json(metrics.getTogglesMetrics());
 | ||
|     });
 | ||
| 
 | ||
|     app.get('/client/metrics/feature-toggles/:name', (req, res) => {
 | ||
|         const name = req.params.name;
 | ||
|         const data = metrics.getTogglesMetrics();
 | ||
|         const lastHour = data.lastHour[name] || {};
 | ||
|         const lastMinute = data.lastMinute[name] || {};
 | ||
|         res.json({
 | ||
|             lastHour,
 | ||
|             lastMinute,
 | ||
|         });
 | ||
|     });
 | ||
| 
 | ||
|     app.post('/client/metrics', (req, res) => {
 | ||
|         const data = req.body;
 | ||
|         const clientIp = req.ip;
 | ||
| 
 | ||
|         joi.validate(data, clientMetricsSchema, (err, cleaned) => {
 | ||
|             if (err) {
 | ||
|                 return res.status(400).json(err);
 | ||
|             }
 | ||
| 
 | ||
|             clientMetricsStore
 | ||
|                 .insert(cleaned)
 | ||
|                 .then(() => clientInstanceStore.insert({
 | ||
|                     appName: cleaned.appName,
 | ||
|                     instanceId: cleaned.instanceId,
 | ||
|                     clientIp,
 | ||
|                 }))
 | ||
|                 .catch(err => logger.error('failed to store metrics', err));
 | ||
| 
 | ||
|             res.status(202).end();
 | ||
|         });
 | ||
|     });
 | ||
| 
 | ||
|     app.post('/client/register', (req, res) => {
 | ||
|         const data = req.body;
 | ||
| 
 | ||
|         joi.validate(data, clientRegisterSchema, (err, clientRegistration) => {
 | ||
|             if (err) {
 | ||
|                 return res.status(400).json(err);
 | ||
|             }
 | ||
| 
 | ||
|             clientRegistration.clientIp = req.ip;
 | ||
| 
 | ||
|             clientApplicationsStore
 | ||
|                 .upsert(clientRegistration)
 | ||
|                 .then(() => clientInstanceStore.insert(clientRegistration))
 | ||
|                 .then(() => logger.info(`New client registered with
 | ||
|                             appName=${clientRegistration.appName} and instanceId=${clientRegistration.instanceId}`))
 | ||
|                 .catch(err => logger.error('failed to register client', err));
 | ||
| 
 | ||
|             res.status(202).end();
 | ||
|         });
 | ||
|     });
 | ||
| 
 | ||
|     app.post('/client/applications/:appName', (req, res) => {
 | ||
|         const input = Object.assign({}, req.body, {
 | ||
|             appName: req.params.appName,
 | ||
|         });
 | ||
|         clientApplicationsStore
 | ||
|             .upsert(input)
 | ||
|             .then(() => res.status(202).end())
 | ||
|             .catch((e) => {
 | ||
|                 logger.error(e);
 | ||
|                 res.status(500).end();
 | ||
|             });
 | ||
|     });
 | ||
| 
 | ||
|     function toLookup (metaData) {
 | ||
|         return metaData.reduce((result, entry) => {
 | ||
|             result[entry.appName] = entry;
 | ||
|             return result;
 | ||
|         }, {});
 | ||
|     }
 | ||
| 
 | ||
|     app.get('/client/applications/', (req, res) => {
 | ||
|         clientApplicationsStore
 | ||
|             .getApplications(req.query)
 | ||
|             .then(applications => res.json({ applications }))
 | ||
|             .catch(err => catchLogAndSendErrorResponse(err, res));
 | ||
|     });
 | ||
| 
 | ||
|     app.get('/client/applications/:appName', (req, res) => {
 | ||
|         const appName = req.params.appName;
 | ||
|         const seenToggles = 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/client/applications/${application.appName}`,
 | ||
|                 },
 | ||
|             };
 | ||
|             res.json(appDetails);
 | ||
|         })
 | ||
|         .catch(err => catchLogAndSendErrorResponse(err, res));
 | ||
|     });
 | ||
| };
 |