Skip to content

Commit

Permalink
add some metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
vmarchaud committed Oct 23, 2018
1 parent 18f7964 commit 3ba97b6
Show file tree
Hide file tree
Showing 5 changed files with 312 additions and 86 deletions.
50 changes: 25 additions & 25 deletions app.js
Expand Up @@ -4,35 +4,35 @@
* can be found in the LICENSE file.
*/

var pmx = require('pmx');
var elasticsearch = require('elasticsearch');
var Probe = pmx.probe();
var stats = require('./lib/stats');
var Actions = require('./lib/actions');

pmx.initModule({

pid : pmx.resolvePidPaths(['/var/run/elasticsearch/elasticsearch.pid',
'/var/run/elasticsearch.pid']),
widget : {
type : 'generic',
const io = require('@pm2/io')
const elasticsearch = require('elasticsearch')
const stats = require('./lib/stats')
const Actions = require('./lib/actions')

io.initModule({
widget: {
type: 'generic',
logo: 'https://www.elastic.co/static/img/logo-elastic.png',
theme : ['#39bdb1', '#1B2228', 'white', '#807C7C'],
el : {
probes : true,
actions : true
theme: ['#39bdb1', '#1B2228', 'white', '#807C7C'],
el: {
probes: true,
actions: true
},

block : {
issues : true,
meta : true,
main_probes : ['Elastic status', 'Nodes', 'Shards', 'Indices', 'Documents', 'Store size']
block: {
issues: true,
meta: true,
main_probes: ['Elastic status', 'Nodes', 'Shards', 'Indices', 'Documents', 'Store size']
}
}
}, function(err, conf) {
var ELASTICSEARCH_URI = conf.elasticsearchUri || process.env.PM2_ELASTICSEARCH_URI;
}, function (err, conf) {
if (err) {
console.error(err)
return process.exit(1)
}
const ELASTICSEARCH_URI = conf.elasticsearchUri || process.env.PM2_ELASTICSEARCH_URI

var client = new elasticsearch.Client({
const client = new elasticsearch.Client({
host: ELASTICSEARCH_URI,
log: 'error'
})
Expand All @@ -46,7 +46,7 @@ pmx.initModule({
return stats.update(client)
}, 1000)

/** Register PMX actions */
var actions = new Actions(client)
// Register PMX actions
const actions = new Actions(client)
actions.register()
})
122 changes: 101 additions & 21 deletions lib/metrics.json
Expand Up @@ -4,28 +4,28 @@
"path": "fs.io_stats.total.write_operations",
"compareToLastValue": true,
"name": "Write Ops",
"unit": "secs"
"unit": "/min"
},
{
"from": "node",
"path": "fs.io_stats.total.read_operations",
"compareToLastValue": true,
"name": "Read Ops",
"unit": "secs"
"unit": "/min"
},
{
"from": "node",
"path": "fs.io_stats.total.read_kilobytes",
"compareToLastValue": true,
"name": "Read Bandwith",
"unit": "ko/s"
"unit": "ko/min"
},
{
"from": "node",
"path": "fs.io_stats.total.write_kilobytes",
"compareToLastValue": true,
"name": "Write Bandwith",
"unit": "ko/s"
"unit": "ko/min"
},
{
"from": "node",
Expand Down Expand Up @@ -120,30 +120,54 @@
"name": "Current Queries"
},
{
"from": "cluster",
"path": "status",
"name": "Elastic status"
},
{
"from": "cluster",
"path": "cluster_name",
"name": "Cluster"
},
{
"from": "cluster",
"from": "node",
"path": "indices.docs.count",
"name": "Documents"
},
{
"from": "cluster",
"from": "node",
"path": "indices.docs.deleted",
"name": "Deleted Documents"
},
{
"from": "cluster",
"from": "node",
"path": "indices.store.size",
"name": "Store size"
},
{
"from": "node",
"path": "process.cpu.percent",
"name": "CPU Usage",
"unit": "%"
},
{
"from": "node",
"path": "os.mem.used_percent",
"name": "Memory Usage",
"unit": "%"
},
{
"from": "node",
"path": "os.swap.used_in_bytes",
"divide_by": "os.swap.total_in_bytes",
"multiply_by": 100,
"name": "Swap Memory Usage",
"unit": "%"
},
{
"from": "node",
"path": "thread_pool.bulk.completed",
"name": "Bulk Op. Completed",
"compareToLastValue": true,
"unit": "/min"
},
{
"from": "node",
"path": "thread_pool.bulk.rejected",
"name": "Bulk Op. Failed",
"compareToLastValue": true,
"unit": "/min"
},
{
"from": "cluster",
"path": "nodes.count.total",
Expand All @@ -156,12 +180,68 @@
},
{
"from": "cluster",
"path": "indices.shards.total",
"name": "Shards"
"path": "indices.count",
"name": "Indices"
},
{
"from": "cluster",
"path": "indices.count",
"name": "Indices"
"path": "status",
"name": "Elastic status"
},
{
"from": "cluster",
"path": "cluster_name",
"name": "Cluster"
},
{
"from": "cluster",
"path": "indices.shards.replication",
"name": "Active Secondy Shards"
},
{
"from": "cluster",
"path": "indices.shards.index.shards.avg",
"name": "Avg. Shards per Index"
},
{
"from": "cluster",
"path": "indices.shards.index.primaries.avg",
"name": "Avg. Primary Shards per Index"
},
{
"from": "cluster",
"path": "indices.shards.index.replication.avg",
"name": "Avg. Secondary Shards per Index"
},
{
"from": "cluster_health",
"path": "active_shards",
"name": "Active Shards"
},
{
"from": "cluster_health",
"path": "active_primary_shards",
"name": "Active Primary Shards"
},
{
"from": "cluster_health",
"path": "unassigned_shards",
"name": "Unassigned Shards"
},
{
"from": "cluster_health",
"path": "relocating_shards",
"name": "Relocating Shards"
},
{
"from": "cluster_health",
"path": "number_of_pending_tasks",
"name": "Pending Tasks"
},
{
"from": "cluster_health",
"path": "task_max_waiting_in_queue_millis",
"name": "Max Task Queue Duration",
"unit": "ms"
}
]
70 changes: 46 additions & 24 deletions lib/stats.js
Expand Up @@ -4,22 +4,20 @@
* can be found in the LICENSE file.
*/

var pmx = require('pmx')
var Probe = pmx.probe()
var async = require('async')
var getObject = require('object-path').get
var metrics = require('./metrics.json')
const io = require('@pm2/io')
const async = require('async')
const getObject = require('object-path').get
const metrics = require('./metrics.json')

var values = new Map()
const values = new Map()

/** Init all probes */
exports.init = function () {
metrics.forEach(function (metric) {
// instanciate each probe
metric.probe = Probe.metric({
metric.probe = io.metric({
name: metric.name,
unit: metric.unit || '',
value: function () { return 'N/A' }
unit: metric.unit || ''
})
})
}
Expand All @@ -38,40 +36,64 @@ exports.update = function (esClient) {
human: true,
nodeId: '_local'
}, next)
},
function (next) {
return esClient.cluster.health({
human: true
}, next)
}
], (err, data) => {
if (err) {
console.error(err)
return pmx.notify(err)
return io.notifyError(err)
}
// lets update metrics
for (let i = 0, max = metrics.length; i < max; i++) {
var metric = metrics[i]
var stats = metric.from === 'cluster' ? data[0][0] : data[1][0]
let stats = {}

// in the case of the node, we need to get the actual node stats
// and since elasticsearch send a map style document we need to trick
if (metric.from === 'node') {
var nodes = Object.keys(stats.nodes)
stats = stats.nodes[nodes[0]]
// depending on the stats source
switch (metric.from) {
case 'cluster': {
stats = data[0][0]
break
}
case 'cluster_health': {
stats = data[2][0]
break
}
case 'node': {
var nodes = Object.keys(data[1][0].nodes)
stats = data[1][0].nodes[nodes[0]]
break
}
}

let value = getObject(stats, metric.path)
if (typeof value === 'undefined') continue

if (metric.compareToLastValue) {
var old = values.get(metric.path) + 0
values.set(metric.path, value)
// continue to next metric if old value isnt found (must be the first run)
if (!old) continue
var current = value - old
// if the metric dont need to be devined, compute it and continue
metric.probe.set(current)
if (typeof metric.counter !== 'number') {
metric.counter = 0
values.set(metric.path, value)
}
// increment the counter
metric.counter++
// when we are arrive at one minute, compare & update
if (metric.counter === 60) {
metric.counter = 0
const old = values.get(metric.path) + 0
values.set(metric.path, value)
// continue to next metric if old value isnt found (must be the first run)
if (old === undefined) continue
metric.probe.set(value - old)
}
} else if (metric.divide_by) {
let divideBy = getObject(stats, metric.divide_by)
if (typeof divideBy === 'undefined') continue
if (divideBy === '0' || divideBy === 0) continue

metric.probe.set(parseFloat(value / divideBy).toFixed(2))
metric.probe.set(parseFloat(value / divideBy * (metric.multiply_by || 1)).toFixed(2))
} else {
metric.probe.set(value)
}
Expand Down
5 changes: 2 additions & 3 deletions package.json
Expand Up @@ -13,13 +13,12 @@
"start": "node app"
},
"dependencies": {
"@pm2/io": "^2.4.5",
"async": "^2.5.0",
"elasticsearch": "*",
"object-path": "^0.11.4",
"pmx": "*"
"object-path": "^0.11.4"
},
"config": {
"workerInterval": 2,
"elasticsearchUri": "http://localhost:9200/"
},
"author": "vmarchaud",
Expand Down

0 comments on commit 3ba97b6

Please sign in to comment.