From 8e02736222f86494f45fdaf960ae94c4e1cd06e1 Mon Sep 17 00:00:00 2001 From: Dan Janosik Date: Thu, 31 Jan 2019 14:31:34 -0500 Subject: [PATCH] - optional logging of network stats to configurable influxdb instance - cleaner support for handling credentials (new app/defaultCredentials.js has the defaults, git-ignored app/credentials.js overwrites) - update some dependencies --- .gitignore | 2 + README.md | 7 +- app.js | 73 ++++++++++++++++ app/config.js | 8 +- app/credentials.js | 23 ----- app/defaultCredentials.js | 31 +++++++ package-lock.json | 178 ++++++++++++++------------------------ package.json | 5 +- 8 files changed, 182 insertions(+), 145 deletions(-) delete mode 100644 app/credentials.js create mode 100644 app/defaultCredentials.js diff --git a/.gitignore b/.gitignore index 31f1139..eebb1de 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,5 @@ typings/ public/css/radial-progress.css + +app/credentials.js \ No newline at end of file diff --git a/README.md b/README.md index c136409..63dc60d 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,10 @@ The below instructions are geared toward BTC, but can be adapted easily to other 1. Clone this repo: `git clone https://github.com/janoside/btc-rpc-explorer` 2. `npm install` 3. `npm run build` -4. Edit the "rpc" settings in [app/credentials.js](app/credentials.js) to target your node +4. Optional: Create git-ignored file [app/credentials.js](app/credentials.js) with values to overwrite those in [app/defaultCredentials.js](app/defaultCredentials.js). 5. Optional: Change the "coin" value in [app/config.js](app/config.js). Currently supported values are "BTC" and "LTC". -6. Optional: Add an ipstack.com API access key to [app/credentials.js](app/credentials.js). Doing so will add a map to the /peers page. -7. `npm start` to start the local server -8. Visit http://127.0.0.1:3002/ +6. `npm start` +7. Open [http://127.0.0.1:3002/](http://127.0.0.1:3002/) ## Run via Docker diff --git a/app.js b/app.js index b2b2339..b4a1d6b 100755 --- a/app.js +++ b/app.js @@ -23,6 +23,8 @@ var request = require("request"); var qrcode = require("qrcode"); var fs = require('fs'); var electrumApi = require("./app/api/electrumApi.js"); +var Influx = require("influx"); +var coreApi = require("./app/api/coreApi.js"); var crawlerBotUserAgentStrings = [ "Googlebot", "Bingbot", "Slurp", "DuckDuckBot", "Baiduspider", "YandexBot", "Sogou", "Exabot", "facebot", "ia_archiver" ]; @@ -60,6 +62,68 @@ process.on("unhandledRejection", (reason, p) => { }); +function logNetworkStats() { + if (global.influxdb) { + var promises = []; + + promises.push(coreApi.getMempoolInfo()); + promises.push(coreApi.getMiningInfo()); + + promises.push(coreApi.getBlockchainInfo()); + + Promise.all(promises).then(function(promiseResults) { + var mempoolInfo = promiseResults[0]; + var miningInfo = promiseResults[1]; + var blockchainInfo = promiseResults[2]; + + //console.log("mempoolInfo: " + JSON.stringify(mempoolInfo)); + //console.log("miningInfo: " + JSON.stringify(miningInfo)); + //console.log("blockchainInfo: " + JSON.stringify(blockchainInfo)); + + var points = []; + + var mempoolMapping = {size:"tx_count", bytes:"tx_vsize_total", usage:"total_memory_usage"}; + for (var key in mempoolInfo) { + if (mempoolMapping[key]) { + points.push({measurement:`bitcoin.mempool.${mempoolMapping[key]}`, fields:{value:mempoolInfo[key]}}) + } + } + + var miningMapping = { + difficulty:{ + name:"mining_difficulty", + transform:function(rawval) {return parseFloat(rawval);} + }, + networkhashps:{ + name:"networkhashps", + transform:function(rawval) {return parseFloat(rawval);} + } + }; + + for (var key in miningInfo) { + if (miningMapping[key]) { + points.push({measurement:`bitcoin.mining.${miningMapping[key].name}`, fields:{value:miningMapping[key].transform(miningInfo[key])}}) + } + } + + var blockchainMapping = {size_on_disk:"size_on_disk"}; + for (var key in blockchainInfo) { + if (blockchainMapping[key]) { + points.push({measurement:`bitcoin.blockchain.${blockchainMapping[key]}`, fields:{value:blockchainInfo[key]}}) + } + } + + //console.log("Points to send to InfluxDB: " + JSON.stringify(points, null, 4)); + + global.influxdb.writePoints(points).catch(err => { + console.error(`Error saving data to InfluxDB: ${err.stack}`) + }); + }).catch(err => { + console.log(`Error logging network stats: ${err}`); + }); + } +} + app.runOnStartup = function() { global.config = config; @@ -100,6 +164,15 @@ app.runOnStartup = function() { }); } + if (config.credentials.influxdb.active) { + global.influxdb = new Influx.InfluxDB(config.credentials.influxdb); + + console.log(`Connected to InfluxDB: ${config.credentials.influxdb.host}:${config.credentials.influxdb.port}/${config.credentials.influxdb.database}`); + + logNetworkStats(); + setInterval(logNetworkStats, 5 * 60000); + } + if (config.donationAddresses) { var getDonationAddressQrCode = function(coinId) { qrcode.toDataURL(config.donationAddresses[coinId].address, function(err, url) { diff --git a/app/config.js b/app/config.js index 6ca46b0..7eb9f4f 100644 --- a/app/config.js +++ b/app/config.js @@ -1,8 +1,14 @@ -var credentials = require("./credentials.js"); var coins = require("./coins.js"); var currentCoin = "BTC"; +var credentials = require("./defaultCredentials.js"); +var overwriteCredentials = require("./credentials.js"); + +for (var key in overwriteCredentials) { + credentials[key] = overwriteCredentials[key]; +} + module.exports = { cookiePassword: "0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f", demoSite: true, diff --git a/app/credentials.js b/app/credentials.js deleted file mode 100644 index 30c08a1..0000000 --- a/app/credentials.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - - // Edit "rpc" below to target your node. - // You may delete this section if you wish to connect manually via the UI. - - rpc: { - host:"localhost", - port:8332, - username:"username", - password:"password" - }, - - // optional: enter your api access key from ipstack.com below - // to include a map of the estimated locations of your node's - // peers - ipStackComApiAccessKey:"", - - // optional: GA tracking code - googleAnalyticsTrackingId:"", - - // optional: sentry.io error-tracking url - sentryUrl:"", -}; diff --git a/app/defaultCredentials.js b/app/defaultCredentials.js new file mode 100644 index 0000000..de3af18 --- /dev/null +++ b/app/defaultCredentials.js @@ -0,0 +1,31 @@ +module.exports = { + rpc: { + host:"127.0.0.1", + port:8332, + username:"rpc_username", + password:"rpc_password" + }, + + influxdb:{ + active:false, + host:"127.0.0.1", + port:8086, + database:"influxdb", + username:"admin", + password:"admin" + }, + + // optional: enter your api access key from ipstack.com below + // to include a map of the estimated locations of your node's + // peers + // format: "ID_FROM_IPSTACK" + ipStackComApiAccessKey:null, + + // optional: GA tracking code + // format: "UA-..." + googleAnalyticsTrackingId:null, + + // optional: sentry.io error-tracking url + // format: "SENTRY_IO_URL" + sentryUrl:null, +}; diff --git a/package-lock.json b/package-lock.json index e5bcdd7..414bff8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -370,9 +370,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -421,18 +421,18 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "color-convert": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", - "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { - "color-name": "1.1.1" + "color-name": "1.1.3" } }, "color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "combined-stream": { @@ -621,12 +621,6 @@ "nan": "^2.10.0" } }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -683,27 +677,28 @@ } }, "es-abstract": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", - "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", "dev": true, "requires": { - "es-to-primitive": "^1.1.1", + "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" } }, "es-to-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "dev": true, "requires": { - "is-callable": "^1.1.1", + "is-callable": "^1.1.4", "is-date-object": "^1.0.1", - "is-symbol": "^1.0.1" + "is-symbol": "^1.0.2" } }, "escape-html": { @@ -727,21 +722,6 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, - "event-stream": { - "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", @@ -890,12 +870,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -965,6 +939,12 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "hash-base": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", @@ -1025,6 +1005,11 @@ "wrappy": "1" } }, + "influx": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/influx/-/influx-5.0.7.tgz", + "integrity": "sha1-NeZfa/E8uqF2MQi1WWqAanJ6Upo=" + }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -1113,10 +1098,13 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } }, "is-typedarray": { "version": "1.0.0", @@ -1295,12 +1283,6 @@ "yallist": "^2.1.2" } }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, "markdown-it": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", @@ -1408,9 +1390,9 @@ } }, "moment": { - "version": "2.22.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", - "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" }, "moment-duration-format": { "version": "2.2.2", @@ -1463,9 +1445,9 @@ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, "nice-try": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "normalize-package-data": { @@ -1480,17 +1462,17 @@ } }, "npm-run-all": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.3.tgz", - "integrity": "sha512-aOG0N3Eo/WW+q6sUIdzcV2COS8VnTZCmdji0VQIAZF3b+a3YWb0AD0vFIyjKec18A7beLGbaQ5jFTNI2bPt9Cg==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.4", + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", "memorystream": "^0.3.1", "minimatch": "^3.0.4", - "ps-tree": "^1.1.0", + "pidtree": "^0.3.0", "read-pkg": "^3.0.0", "shell-quote": "^1.6.1", "string.prototype.padend": "^3.0.0" @@ -1605,6 +1587,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "optional": true, "requires": { "wrappy": "1" } @@ -1692,20 +1675,17 @@ "pify": "^2.0.0" } }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "~2.3" - } - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "pidtree": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", + "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", + "dev": true + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -1740,15 +1720,6 @@ "dev": true, "optional": true }, - "ps-tree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz", - "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=", - "dev": true, - "requires": { - "event-stream": "~3.3.0" - } - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -2264,15 +2235,6 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2" - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -2304,15 +2266,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -2380,12 +2333,6 @@ "has-flag": "^3.0.0" } }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", @@ -2604,7 +2551,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "optional": true }, "y18n": { "version": "3.2.1", diff --git a/package.json b/package.json index 688a1e1..0f528cf 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,10 @@ "electrum-client": "github:chaintools/node-electrum-client#43a999036f9c5", "express": "^4.16.4", "express-session": "1.15.6", + "influx": "5.0.7", "jstransformer-markdown-it": "^2.0.0", "lru-cache": "4.1.3", - "moment": "^2.21.0", + "moment": "^2.24.0", "moment-duration-format": "2.2.2", "morgan": "^1.9.1", "pug": "2.0.1", @@ -43,6 +44,6 @@ }, "devDependencies": { "less": "3.8.0", - "npm-run-all": "^4.1.3" + "npm-run-all": "^4.1.5" } }