From ecb04c0a5387f1bbc3c0d7524ceb878def92e99b Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Tue, 20 Feb 2018 19:04:41 +0000 Subject: [PATCH] feat: .stats.bw* --- src/cli/commands/stats/bw.js | 45 ++++++++++++++++++++++++++ src/core/components/stats.js | 57 ++++++++++++++++++++++++++++++++- src/http/api/resources/stats.js | 38 ++++++++++++++++++++++ src/http/api/routes/stats.js | 8 +++++ 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 src/cli/commands/stats/bw.js diff --git a/src/cli/commands/stats/bw.js b/src/cli/commands/stats/bw.js new file mode 100644 index 0000000000..ba0b7040e4 --- /dev/null +++ b/src/cli/commands/stats/bw.js @@ -0,0 +1,45 @@ +'use strict' + +const print = require('../../utils').print + +module.exports = { + command: 'bw', + + describe: 'Get bandwidth information.', + + builder: { + peer: { + type: 'string', + default: '' + }, + proto: { + type: 'string', + default: '' + }, + poll: { + type: 'boolean', + default: false + }, + interval: { + type: 'string', + default: '1s' + } + }, + + handler (argv) { + const stream = argv.ipfs.stats.bwReadableStream({ + peer: argv.peer, + proto: argv.proto, + poll: argv.poll, + interval: argv.interval + }) + + stream.once('data', function (stats) { + print(`bandwidth status + total in: ${stats.totalIn}B + total out: ${stats.totalOut}B + rate in: ${stats.rateIn}B/s + rate out: ${stats.rateOut}B/s`) + }) + } +} diff --git a/src/core/components/stats.js b/src/core/components/stats.js index 6bc7121301..7d826e08e8 100644 --- a/src/core/components/stats.js +++ b/src/core/components/stats.js @@ -1,8 +1,63 @@ 'use strict' +const promisify = require('promisify-es6') +const Big = require('big.js') +const Pushable = require('pull-pushable') +const human = require('human-to-milliseconds') +const toStream = require('pull-stream-to-stream') + +function bandwidthStats (self, opts) { + // TODO: get the true stats :) + return new Promise((resolve, reject) => { + resolve({ + totalIn: new Big(0), + totalOut: new Big(0), + rateIn: new Big(0), + rateOut: new Big(0) + }) + }) +} + module.exports = function stats (self) { + const _bwPullStream = (opts) => { + let interval = null + let stream = Pushable(true, () => { + if (interval) { + clearInterval(interval) + } + }) + + if (opts.poll) { + human(opts.interval || '1s', (err, value) => { + if (err) throw err + + interval = setInterval(() => { + bandwidthStats(self, opts) + .then((stats) => stream.push(stats)) + .catch((err) => stream.end(err)) + }, value) + }) + } else { + bandwidthStats(self, opts) + .then((stats) => { + stream.push(stats) + stream.end() + }) + .catch((err) => stream.end(err)) + } + + return stream.source + } + return { bitswap: require('./bitswap')(self).stat, - repo: require('./repo')(self).stat + repo: require('./repo')(self).stat, + bw: promisify((opts, callback) => { + bandwidthStats(self, opts) + .then((stats) => callback(null, stats)) + .catch((err) => callback(err)) + }), + bwReadableStream: (opts) => toStream.source(_bwPullStream(opts)), + bwPullStream: _bwPullStream } } diff --git a/src/http/api/resources/stats.js b/src/http/api/resources/stats.js index 839f92a3b3..f0c3d537f9 100644 --- a/src/http/api/resources/stats.js +++ b/src/http/api/resources/stats.js @@ -1,7 +1,45 @@ 'use strict' +const { Transform, Readable } = require('readable-stream') + +const transformBandwidth = (stat) => { + return { + TotalIn: stat.totalIn, + TotalOut: stat.totalOut, + RateIn: stat.rateIn, + RateOut: stat.rateOut + } +} + exports = module.exports exports.bitswap = require('./bitswap').stat exports.repo = require('./repo').stat + +exports.bw = (request, reply) => { + const ipfs = request.server.app.ipfs + const options = { + peer: request.query.peer, + proto: request.query.proto, + poll: request.query.poll === 'true', + interval: request.query.interval || '1s' + } + + const res = ipfs.stats.bwReadableStream(options) + const output = new Transform({ + objectMode: true, + transform (chunk, encoding, cb) { + this.push(JSON.stringify(transformBandwidth(chunk)) + '\n') + cb() + } + }) + + request.on('disconnect', () => { + res.destroy() + }) + + res.pipe(output) + reply(new Readable().wrap(output)) + .header('x-chunked-output', '1') +} diff --git a/src/http/api/routes/stats.js b/src/http/api/routes/stats.js index c167ec58c0..35ec768083 100644 --- a/src/http/api/routes/stats.js +++ b/src/http/api/routes/stats.js @@ -20,4 +20,12 @@ module.exports = (server) => { handler: resources.stats.repo } }) + + api.route({ + method: '*', + path: '/api/v0/stats/bw', + config: { + handler: resources.stats.bw + } + }) }