Skip to content
This repository was archived by the owner on Mar 10, 2020. It is now read-only.

Commit 4421eb2

Browse files
hacdiasdaviddias
authored andcommitted
feat: add stats.bwPullStream and stats.bwReadableStream (#211)
1 parent 328726a commit 4421eb2

File tree

7 files changed

+199
-82
lines changed

7 files changed

+199
-82
lines changed

SPEC/BITSWAP.md

+9-7
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ Bitswap API
1717

1818
`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:
1919

20-
- `provideBufLen`
20+
- `provideBufLen` is an integer.
2121
- `wantlist` (array)
2222
- `peers` (array)
23-
- `blocksReceived`
24-
- `dataReceived`
25-
- `blocksSent`
26-
- `dataSent`
27-
- `dupBlksReceived`
28-
- `dupDataReceived`
23+
- `blocksReceived` is a [Big Int][1]
24+
- `dataReceived` is a [Big Int][1]
25+
- `blocksSent` is a [Big Int][1]
26+
- `dataSent` is a [Big Int][1]
27+
- `dupBlksReceived` is a [Big Int][1]
28+
- `dupDataReceived` is a [Big Int][1]
2929

3030
If no `callback` is passed, a promise is returned.
3131

@@ -47,3 +47,5 @@ ipfs.stats.bitswap((err, stats) => console.log(stats))
4747
// dupBlksReceived: 0,
4848
// dupDataReceived: 0 }
4949
```
50+
51+
[1]: https://github.com/MikeMcl/big.js/

SPEC/REPO.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ Where:
4242

4343
`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:
4444

45-
- `numObjects`
46-
- `repoSize`
47-
- `repoPath`
48-
- `version`
49-
- `storageMax`
45+
- `numObjects` is a [Big Int][1].
46+
- `repoSize` is a [Big Int][1], in bytes.
47+
- `repoPath` is a string.
48+
- `version` is a string.
49+
- `storageMax` is a [Big Int][1].
5050

5151
If no `callback` is passed, a promise is returned.
5252

@@ -81,3 +81,5 @@ ipfs.repo.version((err, version) => console.log(version))
8181

8282
// "6"
8383
```
84+
85+
[1]: https://github.com/MikeMcl/big.js/

SPEC/STATS.md

+74-10
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Stats API
1111

1212
#### `bw`
1313

14-
> 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).
14+
> Get IPFS bandwidth information as an object.
1515
1616
##### `Go` **WIP**
1717

@@ -25,12 +25,14 @@ Where:
2525
- `poll` is used to print bandwidth at an interval.
2626
- `interval` is the time interval to wait between updating output, if `poll` is true.
2727

28-
`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:
28+
`callback` must follow `function (err, stat) {}` signature, where `err` is an Error if the operation was not successful.
2929

30-
- `totalIn`
31-
- `totalOut`
32-
- `rateIn`
33-
- `rateOut`
30+
`stat` is, in both cases, an Object containing the following keys:
31+
32+
- `totalIn` - is a [Big Int][big], in bytes.
33+
- `totalOut` - is a [Big Int][big], in bytes.
34+
- `rateIn` - is a [Big Int][big], in bytes.
35+
- `rateOut` - is a [Big Int][big], in bytes.
3436

3537
If no `callback` is passed, a promise is returned.
3638

@@ -39,8 +41,70 @@ If no `callback` is passed, a promise is returned.
3941
```JavaScript
4042
ipfs.stats.bw((err, stats) => console.log(stats))
4143

42-
// { totalIn: 15456,
43-
// totalOut: 15420,
44-
// rateIn: 905.0873512246716,
45-
// rateOut: 893.7400053359125 }
44+
// { totalIn: Big {...},
45+
// totalOut: Big {...},
46+
// rateIn: Big {...},
47+
// rateOut: Big {...} }
48+
```
49+
50+
#### `bwPullStream`
51+
52+
> Get IPFS bandwidth information as a [Pull Stream][ps].
53+
54+
##### `Go` **WIP**
55+
56+
##### `JavaScript` - ipfs.stats.bwPullStream([options]) -> [Pull Stream][ps]
57+
58+
Options are described on [`ipfs.stats.bw`](#bw).
59+
60+
**Example:**
61+
62+
```JavaScript
63+
const pull = require('pull-stream')
64+
const log = require('pull-stream/sinks/log')
65+
66+
const stream = ipfs.stats.bwReadableStream({ poll: true })
67+
68+
pull(
69+
stream,
70+
log()
71+
)
72+
73+
// { totalIn: Big {...},
74+
// totalOut: Big {...},
75+
// rateIn: Big {...},
76+
// rateOut: Big {...} }
77+
// ...
78+
// Ad infinitum
4679
```
80+
81+
#### `bwReadableStream`
82+
83+
> Get IPFS bandwidth information as a [Readable Stream][rs].
84+
85+
##### `Go` **WIP**
86+
87+
##### `JavaScript` - ipfs.stats.bwReadableStream([options]) -> [Readable Stream][rs]
88+
89+
Options are described on [`ipfs.stats.bw`](#bw).
90+
91+
**Examples:**
92+
93+
```JavaScript
94+
const stream = ipfs.stats.bwReadableStream({ poll: true })
95+
96+
stream.on('data', (data) => {
97+
console.log(data)
98+
}))
99+
100+
// { totalIn: Big {...},
101+
// totalOut: Big {...},
102+
// rateIn: Big {...},
103+
// rateOut: Big {...} }
104+
// ...
105+
// Ad infinitum
106+
```
107+
108+
[big]: https://github.com/MikeMcl/big.js/
109+
[rs]: https://www.npmjs.com/package/readable-stream
110+
[ps]: https://www.npmjs.com/package/pull-stream

js/src/repo.js

+5-15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
const chai = require('chai')
77
const dirtyChai = require('dirty-chai')
8+
const statsTests = require('./utils/stats')
89
const expect = chai.expect
910
chai.use(dirtyChai)
1011

@@ -46,26 +47,15 @@ module.exports = (common) => {
4647
})
4748

4849
it('.stat', (done) => {
49-
ipfs.repo.stat((err, stat) => {
50-
expect(err).to.not.exist()
51-
expect(stat).to.exist()
52-
expect(stat).to.have.property('numObjects')
53-
expect(stat).to.have.property('repoSize')
54-
expect(stat).to.have.property('repoPath')
55-
expect(stat).to.have.property('version')
56-
expect(stat).to.have.property('storageMax')
50+
ipfs.repo.stat((err, res) => {
51+
statsTests.expectIsRepo(err, res)
5752
done()
5853
})
5954
})
6055

6156
it('.stat Promise', () => {
62-
return ipfs.repo.stat().then((stat) => {
63-
expect(stat).to.exist()
64-
expect(stat).to.have.property('numObjects')
65-
expect(stat).to.have.property('repoSize')
66-
expect(stat).to.have.property('repoPath')
67-
expect(stat).to.have.property('version')
68-
expect(stat).to.have.property('storageMax')
57+
return ipfs.repo.stat().then((res) => {
58+
statsTests.expectIsRepo(null, res)
6959
})
7060
})
7161

js/src/stats.js

+40-45
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
const chai = require('chai')
77
const dirtyChai = require('dirty-chai')
8+
const statsTests = require('./utils/stats')
89
const expect = chai.expect
10+
const pull = require('pull-stream')
911
chai.use(dirtyChai)
1012

1113
module.exports = (common) => {
@@ -43,17 +45,7 @@ module.exports = (common) => {
4345
}
4446

4547
ipfs.stats.bitswap((err, res) => {
46-
expect(err).to.not.exist()
47-
expect(res).to.exist()
48-
expect(res).to.have.a.property('provideBufLen')
49-
expect(res).to.have.a.property('wantlist')
50-
expect(res).to.have.a.property('peers')
51-
expect(res).to.have.a.property('blocksReceived')
52-
expect(res).to.have.a.property('dataReceived')
53-
expect(res).to.have.a.property('blocksSent')
54-
expect(res).to.have.a.property('dataSent')
55-
expect(res).to.have.a.property('dupBlksReceived')
56-
expect(res).to.have.a.property('dupDataReceived')
48+
statsTests.expectIsBitswap(err, res)
5749
done()
5850
})
5951
})
@@ -65,16 +57,7 @@ module.exports = (common) => {
6557
}
6658

6759
return ipfs.stats.bitswap().then((res) => {
68-
expect(res).to.exist()
69-
expect(res).to.have.a.property('provideBufLen')
70-
expect(res).to.have.a.property('wantlist')
71-
expect(res).to.have.a.property('peers')
72-
expect(res).to.have.a.property('blocksReceived')
73-
expect(res).to.have.a.property('dataReceived')
74-
expect(res).to.have.a.property('blocksSent')
75-
expect(res).to.have.a.property('dataSent')
76-
expect(res).to.have.a.property('dupBlksReceived')
77-
expect(res).to.have.a.property('dupDataReceived')
60+
statsTests.expectIsBitswap(null, res)
7861
})
7962
})
8063

@@ -85,12 +68,7 @@ module.exports = (common) => {
8568
}
8669

8770
ipfs.stats.bw((err, res) => {
88-
expect(err).to.not.exist()
89-
expect(res).to.exist()
90-
expect(res).to.have.a.property('totalIn')
91-
expect(res).to.have.a.property('totalOut')
92-
expect(res).to.have.a.property('rateIn')
93-
expect(res).to.have.a.property('rateOut')
71+
statsTests.expectIsBandwidth(err, res)
9472
done()
9573
})
9674
})
@@ -102,28 +80,50 @@ module.exports = (common) => {
10280
}
10381

10482
return ipfs.stats.bw().then((res) => {
105-
expect(res).to.exist()
106-
expect(res).to.have.a.property('totalIn')
107-
expect(res).to.have.a.property('totalOut')
108-
expect(res).to.have.a.property('rateIn')
109-
expect(res).to.have.a.property('rateOut')
83+
statsTests.expectIsBandwidth(null, res)
84+
})
85+
})
86+
87+
it('.bwReadableStream', (done) => {
88+
if (!withGo) {
89+
console.log('Not supported in js-ipfs yet')
90+
return done()
91+
}
92+
93+
const stream = ipfs.stats.bwReadableStream()
94+
95+
stream.once('data', (data) => {
96+
statsTests.expectIsBandwidth(null, data)
97+
stream.destroy()
98+
done()
11099
})
111100
})
112101

102+
it('.bwPullStream', (done) => {
103+
if (!withGo) {
104+
console.log('Not supported in js-ipfs yet')
105+
return done()
106+
}
107+
108+
const stream = ipfs.stats.bwPullStream()
109+
110+
pull(
111+
stream,
112+
pull.collect((err, data) => {
113+
statsTests.expectIsBandwidth(err, data[0])
114+
done()
115+
})
116+
)
117+
})
118+
113119
it('.repo', (done) => {
114120
if (!withGo) {
115121
console.log('Not supported in js-ipfs yet')
116122
return done()
117123
}
118124

119125
ipfs.stats.repo((err, res) => {
120-
expect(err).to.not.exist()
121-
expect(res).to.exist()
122-
expect(res).to.have.a.property('numObjects')
123-
expect(res).to.have.a.property('repoSize')
124-
expect(res).to.have.a.property('repoPath')
125-
expect(res).to.have.a.property('version')
126-
expect(res).to.have.a.property('storageMax')
126+
statsTests.expectIsRepo(err, res)
127127
done()
128128
})
129129
})
@@ -135,12 +135,7 @@ module.exports = (common) => {
135135
}
136136

137137
return ipfs.stats.repo().then((res) => {
138-
expect(res).to.exist()
139-
expect(res).to.have.a.property('numObjects')
140-
expect(res).to.have.a.property('repoSize')
141-
expect(res).to.have.a.property('repoPath')
142-
expect(res).to.have.a.property('version')
143-
expect(res).to.have.a.property('storageMax')
138+
statsTests.expectIsRepo(null, res)
144139
})
145140
})
146141
})

js/src/utils/stats.js

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/* eslint-env mocha */
2+
/* eslint max-nested-callbacks: ["error", 8] */
3+
4+
'use strict'
5+
6+
const Big = require('big.js')
7+
const { expect } = require('chai')
8+
9+
const isBigInt = (n) => {
10+
return n.constructor.name === 'Big'
11+
}
12+
13+
module.exports.expectIsBitswap = (err, stats) => {
14+
expect(err).to.not.exist()
15+
expect(stats).to.exist()
16+
expect(stats).to.have.a.property('provideBufLen')
17+
expect(stats).to.have.a.property('wantlist')
18+
expect(stats).to.have.a.property('peers')
19+
expect(stats).to.have.a.property('blocksReceived')
20+
expect(stats).to.have.a.property('dataReceived')
21+
expect(stats).to.have.a.property('blocksSent')
22+
expect(stats).to.have.a.property('dataSent')
23+
expect(stats).to.have.a.property('dupBlksReceived')
24+
expect(stats).to.have.a.property('dupDataReceived')
25+
26+
expect(stats.provideBufLen).to.a('number')
27+
expect(stats.wantlist).to.be.an('array')
28+
expect(stats.peers).to.be.an('array')
29+
expect(isBigInt(stats.blocksReceived)).to.eql(true)
30+
expect(isBigInt(stats.dataReceived)).to.eql(true)
31+
expect(isBigInt(stats.blocksSent)).to.eql(true)
32+
expect(isBigInt(stats.dataSent)).to.eql(true)
33+
expect(isBigInt(stats.dupBlksReceived)).to.eql(true)
34+
expect(isBigInt(stats.dupDataReceived)).to.eql(true)
35+
}
36+
37+
module.exports.expectIsBandwidth = (err, stats) => {
38+
expect(err).to.not.exist()
39+
expect(stats).to.exist()
40+
expect(stats).to.have.a.property('totalIn')
41+
expect(stats).to.have.a.property('totalOut')
42+
expect(stats).to.have.a.property('rateIn')
43+
expect(stats).to.have.a.property('rateOut')
44+
expect(isBigInt(stats.totalIn)).to.eql(true)
45+
expect(isBigInt(stats.totalOut)).to.eql(true)
46+
expect(isBigInt(stats.rateIn)).to.eql(true)
47+
expect(isBigInt(stats.rateOut)).to.eql(true)
48+
}
49+
50+
module.exports.expectIsRepo = (err, res) => {
51+
expect(err).to.not.exist()
52+
expect(res).to.exist()
53+
expect(res).to.have.a.property('numObjects')
54+
expect(res).to.have.a.property('repoSize')
55+
expect(res).to.have.a.property('repoPath')
56+
expect(res).to.have.a.property('version')
57+
expect(res).to.have.a.property('storageMax')
58+
expect(isBigInt(res.numObjects)).to.eql(true)
59+
expect(isBigInt(res.repoSize)).to.eql(true)
60+
expect(isBigInt(res.storageMax)).to.eql(true)
61+
expect(res.repoPath).to.be.a('string')
62+
expect(res.version).to.be.a('string')
63+
}

0 commit comments

Comments
 (0)