Skip to content

Commit

Permalink
Project refactoring; add stream selection menu.
Browse files Browse the repository at this point in the history
  • Loading branch information
STRML authored and joschi committed Nov 3, 2016
1 parent ca27173 commit e0432b0
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 263 deletions.
21 changes: 21 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"root": true,
"extends": "eslint:recommended",
"rules": {
"curly": [1, "multi-line"],
"no-console": 0,
"no-use-before-define": [1, "nofunc"],
"no-underscore-dangle": 0,
"no-unused-vars": [1, {"vars": "local", "args": "none"}],
"new-cap": 0,
"consistent-return": 0,
"prefer-const": 1,
"camelcase": 0,
"dot-notation": 0,
"semi": [1, "always"]
},
env: {
"node": true,
"es6": true,
}
}
123 changes: 45 additions & 78 deletions graylog-dashboard.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env node
'use strict';

/**
* This file is part of Graylog2.
Expand All @@ -17,99 +18,65 @@
* along with Graylog2. If not, see <http://www.gnu.org/licenses/>.
*/

var fs = require('fs')
var yaml = require('js-yaml')
var argv = require('yargs')
const fs = require('fs');
const yaml = require('js-yaml');
const argv = require('yargs')
.usage('Usage: graylog-dashboard --stream-id [stream-id] --host [graylog-server REST API URL]')
.demand(['s','h'])
.demand(['h'])
.alias('s', 'stream-id')
.alias('h', 'host')
.argv
.argv;

var graylog = require("./lib/graylog-api.js")
var ui = require("./lib/screen.js")
var handlers = require("./lib/handlers.js")

/*
*
* ┈╱╱▏┈┈╱╱╱╱▏╱╱▏┈┈┈ ┈╱╱▏┈┈╱╱╱╱▏╱╱▏┈┈┈ ┈╱╱▏┈┈╱╱╱╱▏╱╱▏┈┈┈
* ┈▇╱▏┈┈▇▇▇╱▏▇╱▏┈┈┈ ┈▇╱▏┈┈▇▇▇╱▏▇╱▏┈┈┈ ┈▇╱▏┈┈▇▇▇╱▏▇╱▏┈┈┈
* ┈▇╱▏▁┈▇╱▇╱▏▇╱▏▁┈┈ ┈▇╱▏▁┈▇╱▇╱▏▇╱▏▁┈┈ ┈▇╱▏▁┈▇╱▇╱▏▇╱▏▁┈┈
* ┈▇╱╱╱▏▇╱▇╱▏▇╱╱╱▏┈ ┈▇╱╱╱▏▇╱▇╱▏▇╱╱╱▏┈ ┈▇╱╱╱▏▇╱▇╱▏▇╱╱╱▏┈
* ┈▇▇▇╱┈▇▇▇╱┈▇▇▇╱┈┈ ┈▇▇▇╱┈▇▇▇╱┈▇▇▇╱┈┈ ┈▇▇▇╱┈▇▇▇╱┈▇▇▇╱┈┈
*
* I have no clue about JavaScript or even node.js and this is
* going to be pretty terrible code. It is a wonder that I got
* it running at all lol.
*
* I wish this was Java.
*
* Have fun in here! (Lennart, 01/2015)
*
*/
const Promise = require('bluebird');
const graylog = require('./lib/graylog-api');
const ui = require('./lib/screen');
const handlers = require('./lib/handlers');
const makeStreamMenu = require('./lib/menu');

// CLI arguments
var streamId = argv.s
var serverUrl = argv.h
let serverURL = argv.h;

// Make sure serverUrl has a trailing slash. (computers.)
var lastChar = serverUrl.substr(-1);
if (lastChar != '/') {
serverUrl = serverUrl + '/';
}
// Make sure serverURL has a trailing slash. (computers.)
if (serverURL[serverURL.length - 1] !== '/') serverURL += '/';

// Read user credentials.
var credFilePath = process.env['HOME'] + "/.graylog_dashboard"
const credFilePath = process.env['HOME'] + "/.graylog_dashboard";
let config;
try {
var config = yaml.safeLoad(fs.readFileSync(credFilePath, 'utf8'))
config = yaml.safeLoad(fs.readFileSync(credFilePath, 'utf8'));
} catch (err) {
throw new Error("Could not read Graylog user credentials file at " + credFilePath + " - Please create it "
+ "as described in the README. (" + err + ")")
throw new Error(`Could not read Graylog user credentials file at ${credFilePath} - Please create it ` +
`as described in the README. (${err.message})`);
}

// Check config.
if(config.username == undefined) {
throw new Error("No username defined in " + credFilePath)
}

if(config.password == undefined) {
throw new Error("No password defined in " + credFilePath)
}
['username', 'password'].forEach((k) => {
if (!config[k]) throw new Error(`No ${k} defined in ${credFilePath}.`);
});

var apiUser = config.username.toString()
var apiPass = config.password.toString()
const {username, password, poll_interval = 1000} = config;

setInterval(function() {
graylog.lastMessagesOfStream({
serverUrl: serverUrl,
streamId: streamId,
username: apiUser,
password: apiPass
}, handlers.updateMessagesList)
}, 1000)

setInterval(function() {
graylog.streamThroughput({
serverUrl: serverUrl,
streamId: streamId,
username: apiUser,
password: apiPass
}, handlers.updateStreamThroughput)
}, 1000)
// Ask the user for a stream ID if one is not specified.
function getStreamID() {
if (argv.s) return Promise.resolve(argv.s);
console.log('No stream selected, looking up available streams...');
// Resolves to a stream ID
return makeStreamMenu({username, password, serverURL});
}

setInterval(function() {
graylog.totalThroughput({
serverUrl: serverUrl,
username: apiUser,
password: apiPass
}, handlers.updateTotalThroughputLine)
}, 1000)
function poll(streamID) {
return Promise.all([
graylog.lastMessagesOfStream({serverURL, streamID, username, password}).then(handlers.updateMessagesList),
graylog.streamThroughput({serverURL, streamID, username, password}).then(handlers.updateStreamThroughput),
graylog.totalThroughput({serverURL, username, password}).then(handlers.updateTotalThroughputLine),
graylog.streamAlerts({serverURL, streamID, username, password}).then(handlers.renderAlerts),
])
.delay(poll_interval)
.then(() => poll(streamID));
}

setInterval(function() {
graylog.streamAlerts({
serverUrl: serverUrl,
streamId: streamId,
username: apiUser,
password: apiPass
}, handlers.renderAlerts)
}, 1000)
// Entry
getStreamID()
.tap(() => ui.create()) // tap as not to swallow streamID
.then(poll)
.catch((e) => { console.error(e); });
118 changes: 58 additions & 60 deletions lib/graylog-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,84 +16,82 @@
*/


var request = require('request')
const Promise = require('bluebird');
const request = require('request');
Promise.promisifyAll(request);

module.exports = {

streamAlerts: function(options, callback) {
var url = options.serverUrl + "streams/" + options.streamId + "/alerts/check"
streamAlerts(options) {
const url = `${options.serverURL}streams/${options.streamID}/alerts/check`;

request({uri: url, json: true}, function (error, response, body) {
if (!error && response.statusCode == 200) {
callback(body)
} else {
if(response == undefined) {
console.log("Could not get alerts of stream. Error: " + error)
} else {
console.log("Could not get alerts of stream. Error: HTTP " + response.statusCode)
}
}
}).auth(options.username, options.password, false)
return request.getAsync({uri: url, json: true, auth: makeAuth(options)})
.then((response) => {
return response.body;
})
.catch((error) => {
throw new Error('Could not get stream alerts. Error:' + error.message);
});
},

lastMessagesOfStream: function(options, callback) {
var url = options.serverUrl + "search/universal/relative"
var parameters = {
lastMessagesOfStream(options) {
const url = `${options.serverURL}search/universal/relative`;
const parameters = {
query: "*",
range: 86400,
fields: "timestamp,message",
filter: "streams:" + options.streamId,
filter: "streams:" + options.streamID,
limit: 50
}
};

request({uri: url, json: true, qs: parameters}, function (error, response, body) {
if (!error && response.statusCode == 200) {
var result = []
for(var i in body.messages) {
result.push(body.messages[i].message)
}
return request.getAsync({uri: url, json: true, qs: parameters, auth: makeAuth(options)})
.then((response) => {
return response.body.messages.map((m) => m.message);
})
.catch((error) => {
throw new Error('Could not get stream messages. ' + error.message);
});
},

streams(options) {
const url = `${options.serverURL}streams`;

callback(result)
} else {
if(response == undefined) {
console.log("Could not get messages of stream. Error: " + error)
} else {
console.log("Could not get messages of stream. Error: HTTP " + response.statusCode)
}
}
}).auth(options.username, options.password, false)
return request.getAsync({uri: url, json: true, auth: makeAuth(options)})
.then((response) => {
return response.body.streams;
})
.catch((error) => {
throw new Error('Could not get stream throughput. ' + error.stack);
});
},

streamThroughput: function(options, callback) {
var url = options.serverUrl + "system/metrics/org.graylog2.plugin.streams.Stream." + options.streamId + ".incomingMessages.1-sec-rate"
streamThroughput(options) {
const url = `${options.serverURL}system/metrics/org.graylog2.plugin.streams.Stream.${options.streamID}.incomingMessages.1-sec-rate`;

request({uri: url, json: true}, function (error, response, body) {
if (!error && response.statusCode == 200) {
callback(body.value)
} else {
if(response == undefined) {
console.log("Could not get stream throughput. Error: " + error)
} else {
console.log("Could not get stream throughput. Error: HTTP " + response.statusCode)
}
}
}).auth(options.username, options.password, false)
return request.getAsync({uri: url, json: true, auth: makeAuth(options)})
.then((response) => {
return response.body.value;
})
.catch((error) => {
throw new Error('Could not get stream throughput. ' + error.message);
});
},

totalThroughput: function(options, callback) {
var url = options.serverUrl + "system/throughput"
totalThroughput(options) {
const url = `${options.serverURL}system/throughput`;

request({uri: url, json: true}, function (error, response, body) {
if (!error && response.statusCode == 200) {
callback(body.throughput)
} else {
if(response == undefined) {
console.log("Could not get total throughput. Error: " + error)
} else {
console.log("Could not get total throughput. Error: HTTP " + response.statusCode)
}
}
}).auth(options.username, options.password, false)
return request.getAsync({uri: url, json: true, auth: makeAuth(options)})
.then((response) => {
return response.body.throughput;
})
.catch((error) => {
throw new Error('Could not get stream total throughput. ' + error.message);
});
}

};

// TODO API Token?
function makeAuth(options) {
return {user: options.username, pass: options.password, sendImmediately: true};
}
Loading

0 comments on commit e0432b0

Please sign in to comment.