From 44fec7dfb1bce680f9179023c47fd5e088599778 Mon Sep 17 00:00:00 2001 From: geek Date: Thu, 17 Aug 2017 14:07:08 -0500 Subject: [PATCH] feat(portal-api): retrieve metrics from prometheus --- packages/cp-gql-schema/package.json | 2 +- packages/cp-gql-schema/schema.gql | 2 +- packages/portal-api/lib/data/index.js | 76 ++++++++++++++++++++++++--- packages/portal-api/lib/resolvers.js | 3 +- packages/portal-api/package.json | 9 ++-- 5 files changed, 77 insertions(+), 15 deletions(-) diff --git a/packages/cp-gql-schema/package.json b/packages/cp-gql-schema/package.json index 24222df0..84286a43 100644 --- a/packages/cp-gql-schema/package.json +++ b/packages/cp-gql-schema/package.json @@ -1,6 +1,6 @@ { "name": "joyent-cp-gql-schema", - "version": "1.4.0", + "version": "1.5.0", "license": "MPL-2.0", "repository": "github:yldio/joyent-portal", "main": "index.js", diff --git a/packages/cp-gql-schema/schema.gql b/packages/cp-gql-schema/schema.gql index 0e658f2b..958208f9 100644 --- a/packages/cp-gql-schema/schema.gql +++ b/packages/cp-gql-schema/schema.gql @@ -263,7 +263,7 @@ type Query { ): [Service] importableDeploymentGroups: [DeploymentGroup] # start and end should be .toISOString() date strings - metrics(names: [MerticName], instances: [String], start: String, end: String): [InstanceMetric] + metrics(deploymentGroupId: ID!, names: [MerticName]!, instances: [String]!, start: String!, end: String!): [InstanceMetric] } type Mutation { diff --git a/packages/portal-api/lib/data/index.js b/packages/portal-api/lib/data/index.js index 6d552cf2..7788d236 100644 --- a/packages/portal-api/lib/data/index.js +++ b/packages/portal-api/lib/data/index.js @@ -9,19 +9,19 @@ const Url = require('url'); const Util = require('util'); // 3rd party modules -// const CPClient = require('cp-client'); +const Boom = require('boom'); const DockerClient = require('docker-compose-client'); const Dockerode = require('dockerode'); +const ForceArray = require('force-array'); const Hoek = require('hoek'); -const Boom = require('boom'); -const Triton = require('triton'); +const Find = require('lodash.find'); +const Flatten = require('lodash.flatten'); +const Get = require('lodash.get'); +const UniqBy = require('lodash.uniqby'); const ParamCase = require('param-case'); const Penseur = require('penseur'); -const UniqBy = require('lodash.uniqby'); -const Find = require('lodash.find'); -const Get = require('lodash.get'); -const Flatten = require('lodash.flatten'); -const ForceArray = require('force-array'); +const Prometheus = require('prom-query'); +const Triton = require('triton'); const Uuid = require('uuid/v4'); const VAsync = require('vasync'); @@ -2463,6 +2463,66 @@ class Data extends EventEmitter { this.createDeploymentGroup(deploymentGroup, handleNewDeploymentGroup); } + + getMetrics ({ deploymentGroupId, names, instances, start, end }, cb) { + this.deploymentGroupId({ deploymentGroupId, name: 'prometheus' }, (err, services) => { + if (err || !services || !services.length) { + return cb(err); + } + + const service = services.shift(); + service.instances().then((instances) => { + const instance = instances.shift(); + this._triton.getInstance(instance.machine_id, (err, inst) => { + if (err) { + return cb(err); + } + + const metricNames = [ + 'mem_agg_usage', + 'cpu_sys_usage', + 'net_agg_bytes_in' + ]; + const metricNameEnum = [ + 'AVG_MEM_BYTES', + 'AVG_LOAD_PERCENT', + 'AGG_NETWORK_BYTES' + ]; + + const formattedNames = names.map((name) => { + const i = metricNameEnum.indexOf(name); + + return (i === -1) ? name : metricNames[i]; + }); + + const prometheus = new Prometheus({ url: `http://${inst.primaryIp}:9090` }); + prometheus.getMetrics({ names: formattedNames, instances, start, end }, (err, metrics) => { + if (err) { + return cb(err); + } + + const formattedMetrics = metrics.map((metric) => { + const i = metricNames.indexOf(metric.name); + if (i !== -1) { + metric.name = metricNameEnum[i]; + } + + metric.metrics = metric.metrics.map((entry) => { + entry.time = entry.time.toISOString(); + return entry; + }); + + return metric; + }); + + cb(null, metrics); + }); + }); + }).catch((err) => { + return cb(err); + }); + }); + } } module.exports = Data; diff --git a/packages/portal-api/lib/resolvers.js b/packages/portal-api/lib/resolvers.js index fa309847..7b8db891 100644 --- a/packages/portal-api/lib/resolvers.js +++ b/packages/portal-api/lib/resolvers.js @@ -27,7 +27,8 @@ module.exports = (data) => { 'datacenters', 'instanceMetric', 'config', - 'importableDeploymentGroups' + 'importableDeploymentGroups', + 'metrics' ]; const mutations = [ diff --git a/packages/portal-api/package.json b/packages/portal-api/package.json index e8904cfe..6bbe5884 100644 --- a/packages/portal-api/package.json +++ b/packages/portal-api/package.json @@ -25,8 +25,8 @@ "good": "^7.2.0", "good-console": "^6.4.0", "good-squeeze": "^5.0.2", - "hapi": "^16.4.3", - "lab": "^14.1.1", + "hapi": "^16.5.2", + "lab": "^14.2.0", "lodash.findindex": "^4.6.0", "wreck": "^12.2.3" }, @@ -38,7 +38,7 @@ "force-array": "^3.1.0", "graphi": "^2.2.1", "hoek": "^4.1.1", - "joyent-cp-gql-schema": "^1.3.0", + "joyent-cp-gql-schema": "^1.5.0", "lodash.find": "^4.6.0", "lodash.flatten": "^4.4.0", "lodash.get": "^4.4.2", @@ -47,9 +47,10 @@ "param-case": "^2.1.1", "penseur": "^7.12.3", "piloted": "^3.1.1", + "prom-query": "^1.0.0", "throat": "^4.0.0", "toppsy": "^1.1.0", - "triton": "^5.2.0", + "triton": "^5.3.1", "triton-watch": "^1.1.0", "uuid": "^3.1.0", "vasync": "^1.6.4"