fix leak<->prometheus integration

This commit is contained in:
Sérgio Ramos 2017-03-06 17:15:16 +00:00
parent 5e21ff1e64
commit f33f91988d
6 changed files with 1675 additions and 1107 deletions

View File

@ -53,7 +53,7 @@ services:
depends_on: depends_on:
- plain-node - plain-node
telemetry: telemetry:
image: prom/prometheus image: prom/prometheus:v1.5.2
ports: ports:
- "9090:9090" - "9090:9090"
volumes: volumes:

View File

@ -5,63 +5,64 @@
"license": "private", "license": "private",
"main": "src/server/index.js", "main": "src/server/index.js",
"dependencies": { "dependencies": {
"artillery": "^1.5.0-17", "apr-map": "^1.0.3",
"async": "^2.1.4", "artillery": "^1.5.2",
"async": "^2.1.5",
"build-array": "^1.0.0", "build-array": "^1.0.0",
"chart.js": "^2.4.0", "chart.js": "^2.5.0",
"date.js": "^0.3.1", "date.js": "^0.3.1",
"epimetheus": "^1.0.46", "epimetheus": "^1.0.46",
"force-array": "^3.1.0", "force-array": "^3.1.0",
"good": "^7.0.2", "good": "^7.1.0",
"good-console": "^6.3.1", "good-console": "^6.4.0",
"good-squeeze": "^5.0.1", "good-squeeze": "^5.0.1",
"got": "^6.6.3", "got": "^6.7.1",
"hapi": "^15.2.0", "hapi": "^16.1.0",
"hapi-webpack-dev-plugin": "1.1.4", "hapi-webpack-dev-plugin": "1.2.0",
"inert": "^4.0.2", "inert": "^4.1.0",
"internet-timestamp": "^0.0.1", "internet-timestamp": "^0.0.1",
"lodash.first": "^3.0.0", "lodash.first": "^3.0.0",
"lodash.get": "^4.4.2", "lodash.get": "^4.4.2",
"lodash.take": "^4.1.1", "lodash.take": "^4.1.1",
"minimist": "^1.2.0", "minimist": "^1.2.0",
"nes": "^6.3.1", "nes": "^6.4.0",
"pretty-hrtime": "^1.0.3", "pretty-hrtime": "^1.0.3",
"prom-client": "^6.1.2", "prom-client": "^6.3.0",
"qs": "^6.3.0", "qs": "^6.4.0",
"react": "^15.4.1", "react": "^15.4.2",
"react-dom": "^15.4.1", "react-dom": "^15.4.2",
"react-hot-loader": "^3.0.0-beta.6", "react-hot-loader": "^3.0.0-beta.6",
"react-redux": "^4.4.6", "react-redux": "^5.0.3",
"redux": "^3.6.0", "redux": "^3.6.0",
"redux-logger": "^2.7.4", "redux-logger": "^2.8.2",
"redux-promise-middleware": "^4.1.0", "redux-promise-middleware": "^4.2.0",
"redux-thunk": "^2.1.0", "redux-thunk": "^2.2.0",
"relative-date": "^1.1.3", "relative-date": "^1.1.3",
"require-dir": "^0.3.1", "require-dir": "^0.3.1",
"simple-statistics": "^2.2.0" "simple-statistics": "^2.5.0"
}, },
"devDependencies": { "devDependencies": {
"async": "^2.1.4", "async": "^2.1.5",
"babel-core": "^6.18.2", "babel-core": "^6.23.1",
"babel-eslint": "^7.1.1", "babel-eslint": "^7.1.1",
"babel-loader": "^6.2.8", "babel-loader": "^6.4.0",
"babel-plugin-add-module-exports": "^0.2.1", "babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-transform-es2015-modules-commonjs": "^6.18.0", "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0",
"babel-plugin-transform-object-rest-spread": "^6.19.0", "babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-preset-es2015": "^6.18.0", "babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.16.0", "babel-preset-react": "^6.23.0",
"diskusage": "^0.1.5", "diskusage": "^0.2.1",
"eslint": "^3.10.2", "eslint": "^3.17.0",
"eslint-config-semistandard": "^7.0.0", "eslint-config-semistandard": "^7.0.0",
"eslint-config-standard": "^6.2.1", "eslint-config-standard": "^7.0.0",
"eslint-plugin-babel": "^4.0.0", "eslint-plugin-babel": "^4.1.0",
"eslint-plugin-promise": "^3.4.0", "eslint-plugin-promise": "^3.5.0",
"eslint-plugin-react": "^6.7.1", "eslint-plugin-react": "^6.10.0",
"eslint-plugin-standard": "^2.0.1", "eslint-plugin-standard": "^2.1.1",
"json-loader": "^0.5.4", "json-loader": "^0.5.4",
"os-utils": "^0.0.14", "os-utils": "^0.0.14",
"simple-statistics": "^2.2.0", "simple-statistics": "^2.5.0",
"webpack": "^1.13.3", "webpack": "^2.2.1",
"webpack-dev-server": "^1.16.2" "webpack-dev-server": "^2.4.1"
} }
} }

View File

@ -1,17 +1,17 @@
scrape_configs: scrape_configs:
- job_name: 'leak-fast' - job_name: 'leak-fast'
scrape_interval: 1s scrape_interval: 15s
static_configs: static_configs:
- targets: ['fast-node:8000', 'another-fast-node:8000'] - targets: ['fast-node:8000', 'another-fast-node:8000']
- job_name: 'leak-slow' - job_name: 'leak-slow'
scrape_interval: 1s scrape_interval: 15s
static_configs: static_configs:
- targets: ['slow-node:8000'] - targets: ['slow-node:8000']
- job_name: 'no-leak' - job_name: 'no-leak'
scrape_interval: 1s scrape_interval: 15s
static_configs: static_configs:
- targets: ['plain-node:8000'] - targets: ['plain-node:8000']
- job_name: 'leak' # - job_name: 'leak'
scrape_interval: 1s # scrape_interval: 1s
static_configs: # static_configs:
- targets: ['fast-node:8000', 'another-fast-node:8000', 'slow-node:8000', 'plain-node:8000'] # - targets: ['fast-node:8000', 'another-fast-node:8000', 'slow-node:8000', 'plain-node:8000']

View File

@ -1,3 +1,4 @@
const map = require('apr-map');
const forceArray = require('force-array'); const forceArray = require('force-array');
const get = require('lodash.get'); const get = require('lodash.get');
const date = require('date.js'); const date = require('date.js');
@ -7,11 +8,7 @@ const url = require('url');
const qs = require('qs'); const qs = require('qs');
const transform = (res) => { const transform = (res) => {
return forceArray(res).reduce((sum, r) => { return forceArray(res).reduce((sum, { data }) => {
const {
data
} = JSON.parse(r.body);
const result = !Array.isArray(data) const result = !Array.isArray(data)
? data.result ? data.result
: data; : data;
@ -33,12 +30,12 @@ const transform = (res) => {
} = metric; } = metric;
const oldJob = get(sum, job, {}); const oldJob = get(sum, job, {});
const oldQuery = get(sum, `${job}.${__name__}`, {}); const oldInstance = get(sum, `${job}.${instance}`, {});
const _value = values.length ? values : value const _value = values.length ? values : value
return Object.assign(sum, { return Object.assign(sum, {
[job]: Object.assign(oldJob, { [job]: Object.assign(oldJob, {
[instance]: Object.assign(oldQuery, { [instance]: Object.assign(oldInstance, {
[__name__]: _value [__name__]: _value
}) })
}) })
@ -47,17 +44,17 @@ const transform = (res) => {
}, {}); }, {});
}; };
const range = module.exports.range = ({ const range = module.exports.range = async ({
query = [], query = [],
ago = '1h ago', ago = '1h ago',
step = '1s', step = '15s',
hostname = 'localhost' hostname = 'localhost'
}) => { }) => {
const end = timestamp(new Date()); const end = timestamp(new Date());
const start = timestamp(date(ago)); const start = timestamp(date(ago));
return Promise.all(query.map((query) => { const ranges = await map(query, async (query) => {
return got(url.format({ return await got(url.format({
protocol: 'http:', protocol: 'http:',
slashes: true, slashes: true,
port: '9090', port: '9090',
@ -69,17 +66,20 @@ const range = module.exports.range = ({
step, step,
start start
} }
})); }))
})) });
.then(transform);
return transform(
ranges.map((range) => JSON.parse(range.body))
);
}; };
const query = module.exports.query = ({ const query = module.exports.query = async ({
hostname = 'localhost', hostname = 'localhost',
query = [] query = []
}) => { }) => {
return Promise.all(query.map((query) => { const res = await map(query, async (query) => {
return got(url.format({ return await got(url.format({
protocol: 'http:', protocol: 'http:',
slashes: true, slashes: true,
port: '9090', port: '9090',
@ -88,16 +88,19 @@ const query = module.exports.query = ({
query: { query: {
query: query query: query
} }
})); }))
})) });
.then(transform);
return transform(
res.map((res) => JSON.parse(res.body))
);
}; };
const tree = module.exports.tree = ({ const tree = module.exports.tree = async ({
hostname = 'localhost', hostname = 'localhost',
query = [] query = []
}) => { }) => {
return got(url.format({ const res = await got(url.format({
protocol: 'http:', protocol: 'http:',
slashes: true, slashes: true,
port: '9090', port: '9090',
@ -108,8 +111,9 @@ const tree = module.exports.tree = ({
}, { }, {
arrayFormat: 'brackets' arrayFormat: 'brackets'
}) })
})) }));
.then(transform);
return transform(res);
}; };
if (!module.parent) { if (!module.parent) {
@ -120,7 +124,7 @@ if (!module.parent) {
const usage = () => { const usage = () => {
console.error(` console.error(`
Usage: node metrics.js --type={type} --query={metric} --step={step} --ago={ago} Usage: node metrics.js --type={type} --query={metric} --step={step} --ago={ago}
node metrics.js --type=range --query=node_memory_heap_used_bytes --query=node_memory_heap_total_bytes node scripts/prometheus.js --type=range --query=node_memory_heap_used_bytes --query=node_memory_heap_total_bytes
`.trim()); `.trim());
return process.exit(1); return process.exit(1);

View File

@ -1,8 +1,6 @@
const webpack = require('webpack'); const webpack = require('webpack');
const path = require('path'); const path = require('path');
const cfg = require('../webpack.config.js');
module.exports = [ module.exports = [
require('inert'), require('inert'),
require('nes'), { require('nes'), {
@ -21,10 +19,4 @@ module.exports = [
}, 'stdout'] }, 'stdout']
} }
} }
}, {
register: require('hapi-webpack-dev-plugin'),
options: {
compiler: webpack(cfg),
devIndex: path.join(__dirname, '../static')
}
}]; }];

File diff suppressed because it is too large Load Diff