From 220483fd3b3ef1febcea970d9cfbcedb796d903a Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Thu, 25 Jan 2018 11:53:21 +0000 Subject: [PATCH] feat: add stats spec --- SPEC/STATS.md | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/index.js | 1 + src/stats.js | 112 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 SPEC/STATS.md create mode 100644 src/stats.js diff --git a/SPEC/STATS.md b/SPEC/STATS.md new file mode 100644 index 00000000..70c6cf7c --- /dev/null +++ b/SPEC/STATS.md @@ -0,0 +1,114 @@ +Stats API +======= + +#### `bitswap` + +> Adds an IPFS object to the pinset and also stores it to the IPFS repo. pinset is the set of hashes currently pinned (not gc'able). + +##### `Go` **WIP** + +##### `JavaScript` - ipfs.stats.bitswap([callback]) + +`callback` must follow `function (err, stats) {}` signature, where `err` is an error if the operation was not successful. `stats` is an Object containing the following keys: + +- `provideBufLen` +- `wantlist` (array) +- `peers` (array) +- `blocksReceived` +- `dataReceived` +- `blocksSent` +- `dataSent` +- `dupBlksReceived` +- `dupDataReceived` + +If no `callback` is passed, a promise is returned. + +**Example:** + +```JavaScript +ipfs.stats.bitswap((err, stats) => console.log(stats)) + +// { provideBufLen: 0, +// wantlist: null, +// peers: +// [ 'QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', +// 'QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', +// 'QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd' ], +// blocksReceived: 0, +// dataReceived: 0, +// blocksSent: 0, +// dataSent: 0, +// dupBlksReceived: 0, +// dupDataReceived: 0 } +``` + +#### `bw` + +> Adds an IPFS object to the pinset and also stores it to the IPFS repo. pinset is the set of hashes currently pinned (not gc'able). + +##### `Go` **WIP** + +##### `JavaScript` - ipfs.stats.bw([options, callback]) + +Where: + +- `options` is an opcional object that might contain the following keys: + - `peer` specifies a peer to print bandwidth for. + - `proto` specifies a protocol to print bandwidth for. + - `poll` is used to print bandwidth at an interval. + - `interval` is the time interval to wait between updating output, if `poll` is true. + +`callback` must follow `function (err, stats) {}` signature, where `err` is an error if the operation was not successful. `stats` is an Object containing the following keys: + +- `totalIn` +- `totalOut` +- `rateIn` +- `rateOut` + +If no `callback` is passed, a promise is returned. + +**Example:** + +```JavaScript +ipfs.stats.bw((err, stats) => console.log(stats)) + +// { totalIn: 15456, +// totalOut: 15420, +// rateIn: 905.0873512246716, +// rateOut: 893.7400053359125 } +``` + +#### `stat` + +> Get stats for the currently used repo. + +##### `Go` **WIP** + +##### `JavaScript` - ipfs.repo.stat([options, callback]) + +Where: + +- `options` is an object that contains following properties + - `human` a Boolean value to output `repoSize` in MiB. + +`callback` must follow `function (err, stats) {}` signature, where `err` is an Error if the operation was not successful and `stats` is an object containing the following keys: + +- `numObjects` +- `repoSize` +- `repoPath` +- `version` +- `storageMax` + +If no `callback` is passed, a promise is returned. + +**Example:** + +```JavaScript +ipfs.repo.stat((err, stats) => console.log(stats)) + +// { numObjects: 15, +// repoSize: 64190, +// repoPath: 'C:\\Users\\henri\\AppData\\Local\\Temp\\ipfs_687c6eb3da07d3b16fe3c63ce17560e9', +// version: 'fs-repo@6', +// storageMax: 10000000000 } +``` diff --git a/src/index.js b/src/index.js index 60f79d0e..fe35236a 100644 --- a/src/index.js +++ b/src/index.js @@ -12,3 +12,4 @@ exports.dht = require('./dht') exports.dag = require('./dag') exports.pubsub = require('./pubsub') exports.key = require('./key') +exports.stats = require('./stats') diff --git a/src/stats.js b/src/stats.js new file mode 100644 index 00000000..8393e5e7 --- /dev/null +++ b/src/stats.js @@ -0,0 +1,112 @@ +/* eslint-env mocha */ +/* eslint max-nested-callbacks: ["error", 8] */ + +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) + +module.exports = (common) => { + describe('.stats', () => { + let ipfs + + before(function (done) { + // CI takes longer to instantiate the daemon, so we need to increase the + // timeout for the before step + this.timeout(60 * 1000) + + common.setup((err, factory) => { + expect(err).to.not.exist() + factory.spawnNode((err, node) => { + expect(err).to.not.exist() + ipfs = node + done() + }) + }) + }) + + after((done) => { + common.teardown(done) + }) + + it('.bitswap', (done) => { + ipfs.stats.bitswap((err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + expect(res).to.have.a.property('provideBufLen') + expect(res).to.have.a.property('wantlist') + expect(res).to.have.a.property('peers') + expect(res).to.have.a.property('blocksReceived') + expect(res).to.have.a.property('dataReceived') + expect(res).to.have.a.property('blocksSent') + expect(res).to.have.a.property('dataSent') + expect(res).to.have.a.property('dupBlksReceived') + expect(res).to.have.a.property('dupDataReceived') + done() + }) + }) + + it('.bitswap Promise', () => { + return ipfs.stats.bitswap().then((res) => { + expect(res).to.exist() + expect(res).to.have.a.property('provideBufLen') + expect(res).to.have.a.property('wantlist') + expect(res).to.have.a.property('peers') + expect(res).to.have.a.property('blocksReceived') + expect(res).to.have.a.property('dataReceived') + expect(res).to.have.a.property('blocksSent') + expect(res).to.have.a.property('dataSent') + expect(res).to.have.a.property('dupBlksReceived') + expect(res).to.have.a.property('dupDataReceived') + }) + }) + + it('.bw', (done) => { + ipfs.stats.bw((err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + expect(res).to.have.a.property('totalIn') + expect(res).to.have.a.property('totalOut') + expect(res).to.have.a.property('rateIn') + expect(res).to.have.a.property('rateOut') + done() + }) + }) + + it('.bw Promise', () => { + return ipfs.stats.bw().then((res) => { + expect(res).to.exist() + expect(res).to.have.a.property('totalIn') + expect(res).to.have.a.property('totalOut') + expect(res).to.have.a.property('rateIn') + expect(res).to.have.a.property('rateOut') + }) + }) + + it('.repo', (done) => { + ipfs.stats.repo((err, res) => { + expect(err).to.not.exist() + expect(res).to.exist() + expect(res).to.have.a.property('numObjects') + expect(res).to.have.a.property('repoSize') + expect(res).to.have.a.property('repoPath') + expect(res).to.have.a.property('version') + expect(res).to.have.a.property('storageMax') + done() + }) + }) + + it('.repo Promise', () => { + return ipfs.stats.repo().then((res) => { + expect(res).to.exist() + expect(res).to.have.a.property('numObjects') + expect(res).to.have.a.property('repoSize') + expect(res).to.have.a.property('repoPath') + expect(res).to.have.a.property('version') + expect(res).to.have.a.property('storageMax') + }) + }) + }) +}