Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 028d2b0

Browse files
committed
feat: .stats.bw*
1 parent 9105700 commit 028d2b0

File tree

6 files changed

+172
-3
lines changed

6 files changed

+172
-3
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
"is-ipfs": "^0.3.2",
120120
"is-stream": "^1.1.0",
121121
"joi": "^13.1.2",
122-
"libp2p": "~0.18.0",
122+
"libp2p": "libp2p/js-libp2p#09069d4",
123123
"libp2p-circuit": "~0.1.4",
124124
"libp2p-floodsub": "~0.14.1",
125125
"libp2p-kad-dht": "~0.8.0",

src/cli/commands/stats/bw.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
'use strict'
2+
3+
const pull = require('pull-stream')
4+
5+
module.exports = {
6+
command: 'bw',
7+
8+
describe: 'Get bandwidth information.',
9+
10+
builder: {
11+
peer: {
12+
type: 'string',
13+
default: ''
14+
},
15+
proto: {
16+
type: 'string',
17+
default: ''
18+
},
19+
poll: {
20+
type: 'boolean',
21+
default: false
22+
},
23+
interval: {
24+
type: 'string',
25+
default: '1s'
26+
}
27+
},
28+
29+
handler (argv) {
30+
const stream = argv.ipfs.stats.bwPullStream({
31+
peer: argv.peer,
32+
proto: argv.proto,
33+
poll: argv.poll,
34+
interval: argv.interval
35+
})
36+
37+
pull(
38+
stream,
39+
pull.drain((chunk) => {
40+
console.log(`bandwidth status
41+
total in: ${chunk.totalIn}B
42+
total out: ${chunk.totalOut}B
43+
rate in: ${chunk.rateIn}B/s
44+
rate out: ${chunk.rateOut}B/s`)
45+
})
46+
)
47+
}
48+
}

src/core/components/stats.js

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,82 @@
11
'use strict'
22

3+
const promisify = require('promisify-es6')
4+
const Big = require('big.js')
5+
const Pushable = require('pull-pushable')
6+
const human = require('human-to-milliseconds')
7+
const toStream = require('pull-stream-to-stream')
8+
9+
function bandwidthStats (self, opts) {
10+
return new Promise((resolve, reject) => {
11+
let stats
12+
13+
if (opts.peer) {
14+
stats = self._libp2pNode.stats.forPeer(opts.peer)
15+
} else if (opts.proto) {
16+
stats = self._libp2pNode.stats.forProtocol(opts.proto)
17+
} else {
18+
stats = self._libp2pNode.stats.global
19+
}
20+
21+
if (!stats) {
22+
resolve({
23+
totalIn: new Big(0),
24+
totalOut: new Big(0),
25+
rateIn: new Big(0),
26+
rateOut: new Big(0)
27+
})
28+
return
29+
}
30+
31+
resolve({
32+
totalIn: stats.snapshot.dataReceived,
33+
totalOut: stats.snapshot.dataSent,
34+
rateIn: new Big(stats.movingAverages.dataReceived['60000'].movingAverage() / 60),
35+
rateOut: new Big(stats.movingAverages.dataSent['60000'].movingAverage() / 60)
36+
})
37+
})
38+
}
39+
340
module.exports = function stats (self) {
41+
const _bwPullStream = (opts) => {
42+
let interval = null
43+
let stream = Pushable(true, () => {
44+
if (interval) {
45+
clearInterval(interval)
46+
}
47+
})
48+
49+
if (opts.poll) {
50+
human(opts.interval || '1s', (err, value) => {
51+
if (err) throw err
52+
53+
interval = setInterval(() => {
54+
bandwidthStats(self, opts)
55+
.then((stats) => stream.push(stats))
56+
.catch((err) => stream.end(err))
57+
}, value)
58+
})
59+
} else {
60+
bandwidthStats(self, opts)
61+
.then((stats) => {
62+
stream.push(stats)
63+
stream.end()
64+
})
65+
.catch((err) => stream.end(err))
66+
}
67+
68+
return stream.source
69+
}
70+
471
return {
572
bitswap: require('./bitswap')(self).stat,
6-
repo: require('./repo')(self).stat
73+
repo: require('./repo')(self).stat,
74+
bw: promisify((opts, callback) => {
75+
bandwidthStats(self, opts)
76+
.then((stats) => callback(null, stats))
77+
.catch((err) => callback(err))
78+
}),
79+
bwReadableStream: (opts) => toStream.source(_bwPullStream(opts)),
80+
bwPullStream: _bwPullStream
781
}
882
}

src/http/api/resources/stats.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,46 @@
11
'use strict'
22

3+
const { Transform } = require('readable-stream')
4+
5+
const transformBandwidth = (stat) => {
6+
return {
7+
TotalIn: stat.totalIn,
8+
TotalOut: stat.totalOut,
9+
RateIn: stat.rateIn,
10+
RateOut: stat.rateOut
11+
}
12+
}
13+
314
exports = module.exports
415

516
exports.bitswap = require('./bitswap').stat
617

718
exports.repo = require('./repo').stat
19+
20+
exports.bw = (request, reply) => {
21+
const ipfs = request.server.app.ipfs
22+
const options = {
23+
peer: request.query.peer,
24+
proto: request.query.proto,
25+
poll: request.query.poll === 'true',
26+
interval: request.query.interval || '1s'
27+
}
28+
29+
const res = ipfs.stats.bwReadableStream(options)
30+
const output = new Transform({
31+
writableObjectMode: true,
32+
transform (chunk, encoding, cb) {
33+
this.push(JSON.stringify(transformBandwidth(chunk)) + '\n')
34+
cb()
35+
}
36+
})
37+
38+
request.on('disconnect', () => {
39+
res.destroy()
40+
})
41+
42+
res.pipe(output)
43+
reply(output)
44+
.header('content-type', 'application/json')
45+
.header('x-chunked-output', '1')
46+
}

src/http/api/routes/stats.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,12 @@ module.exports = (server) => {
2020
handler: resources.stats.repo
2121
}
2222
})
23+
24+
api.route({
25+
method: '*',
26+
path: '/api/v0/stats/bw',
27+
config: {
28+
handler: resources.stats.bw
29+
}
30+
})
2331
}

test/cli/commands.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
const expect = require('chai').expect
55
const runOnAndOff = require('../utils/on-and-off')
66

7-
const commandCount = 72
7+
const commandCount = 73
88
describe('commands', () => runOnAndOff((thing) => {
99
let ipfs
1010

0 commit comments

Comments
 (0)