libp2p 0.40.0 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +21 -2
  2. package/dist/src/address-manager/index.d.ts.map +1 -1
  3. package/dist/src/address-manager/index.js +1 -1
  4. package/dist/src/address-manager/index.js.map +1 -1
  5. package/dist/src/config.d.ts.map +1 -1
  6. package/dist/src/config.js +0 -11
  7. package/dist/src/config.js.map +1 -1
  8. package/dist/src/connection/index.d.ts +83 -0
  9. package/dist/src/connection/index.d.ts.map +1 -0
  10. package/dist/src/connection/index.js +96 -0
  11. package/dist/src/connection/index.js.map +1 -0
  12. package/dist/src/connection-manager/dialer/index.d.ts +13 -14
  13. package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
  14. package/dist/src/connection-manager/dialer/index.js +82 -62
  15. package/dist/src/connection-manager/dialer/index.js.map +1 -1
  16. package/dist/src/connection-manager/index.d.ts +2 -10
  17. package/dist/src/connection-manager/index.d.ts.map +1 -1
  18. package/dist/src/connection-manager/index.js +21 -53
  19. package/dist/src/connection-manager/index.js.map +1 -1
  20. package/dist/src/fetch/index.d.ts.map +1 -1
  21. package/dist/src/fetch/index.js +15 -3
  22. package/dist/src/fetch/index.js.map +1 -1
  23. package/dist/src/get-peer.d.ts +2 -2
  24. package/dist/src/get-peer.d.ts.map +1 -1
  25. package/dist/src/get-peer.js +2 -5
  26. package/dist/src/get-peer.js.map +1 -1
  27. package/dist/src/index.d.ts +10 -6
  28. package/dist/src/index.d.ts.map +1 -1
  29. package/dist/src/index.js +7 -1
  30. package/dist/src/index.js.map +1 -1
  31. package/dist/src/keychain/index.d.ts +1 -1
  32. package/dist/src/keychain/index.d.ts.map +1 -1
  33. package/dist/src/libp2p.d.ts +3 -3
  34. package/dist/src/libp2p.d.ts.map +1 -1
  35. package/dist/src/libp2p.js +2 -3
  36. package/dist/src/libp2p.js.map +1 -1
  37. package/dist/src/registrar.d.ts +5 -0
  38. package/dist/src/registrar.d.ts.map +1 -1
  39. package/dist/src/registrar.js +25 -0
  40. package/dist/src/registrar.js.map +1 -1
  41. package/dist/src/transport-manager.d.ts.map +1 -1
  42. package/dist/src/transport-manager.js +1 -2
  43. package/dist/src/transport-manager.js.map +1 -1
  44. package/dist/src/upgrader.d.ts +1 -1
  45. package/dist/src/upgrader.d.ts.map +1 -1
  46. package/dist/src/upgrader.js +46 -59
  47. package/dist/src/upgrader.js.map +1 -1
  48. package/package.json +9 -10
  49. package/src/address-manager/index.ts +3 -2
  50. package/src/circuit/README.md +6 -6
  51. package/src/config.ts +0 -11
  52. package/src/connection/index.ts +171 -0
  53. package/src/connection-manager/dialer/index.ts +100 -75
  54. package/src/connection-manager/index.ts +21 -58
  55. package/src/fetch/index.ts +16 -3
  56. package/src/get-peer.ts +3 -7
  57. package/src/index.ts +15 -7
  58. package/src/keychain/index.ts +1 -1
  59. package/src/libp2p.ts +5 -6
  60. package/src/registrar.ts +29 -2
  61. package/src/transport-manager.ts +1 -2
  62. package/src/upgrader.ts +51 -64
  63. package/src/version.ts +1 -1
  64. package/dist/src/metrics/index.d.ts +0 -93
  65. package/dist/src/metrics/index.d.ts.map +0 -1
  66. package/dist/src/metrics/index.js +0 -234
  67. package/dist/src/metrics/index.js.map +0 -1
  68. package/dist/src/metrics/moving-average.d.ts +0 -14
  69. package/dist/src/metrics/moving-average.d.ts.map +0 -1
  70. package/dist/src/metrics/moving-average.js +0 -40
  71. package/dist/src/metrics/moving-average.js.map +0 -1
  72. package/dist/src/metrics/stats.d.ts +0 -87
  73. package/dist/src/metrics/stats.d.ts.map +0 -1
  74. package/dist/src/metrics/stats.js +0 -183
  75. package/dist/src/metrics/stats.js.map +0 -1
  76. package/src/metrics/index.ts +0 -311
  77. package/src/metrics/moving-average.ts +0 -53
  78. package/src/metrics/stats.ts +0 -238
@@ -1,87 +0,0 @@
1
- import { EventEmitter } from '@libp2p/interfaces/events';
2
- import type { MovingAverages, Stats, TransferStats } from '@libp2p/interface-metrics';
3
- export interface StatsEvents {
4
- 'update': CustomEvent<TransferStats>;
5
- }
6
- export interface StatsInit {
7
- enabled: boolean;
8
- initialCounters: ['dataReceived', 'dataSent'];
9
- movingAverageIntervals: number[];
10
- computeThrottleMaxQueueSize: number;
11
- computeThrottleTimeout: number;
12
- }
13
- export declare class DefaultStats extends EventEmitter<StatsEvents> implements Stats {
14
- private readonly enabled;
15
- queue: Array<[string, number, number]>;
16
- private stats;
17
- private frequencyLastTime;
18
- private frequencyAccumulators;
19
- private movingAverages;
20
- private timeout?;
21
- private readonly computeThrottleMaxQueueSize;
22
- private readonly computeThrottleTimeout;
23
- private readonly movingAverageIntervals;
24
- /**
25
- * A queue based manager for stat processing
26
- */
27
- constructor(init: StatsInit);
28
- /**
29
- * Initializes the internal timer if there are items in the queue. This
30
- * should only need to be called if `Stats.stop` was previously called, as
31
- * `Stats.push` will also start the processing
32
- */
33
- start(): void;
34
- /**
35
- * Stops processing and computing of stats by clearing the internal
36
- * timer
37
- */
38
- stop(): void;
39
- /**
40
- * Returns a clone of the current stats.
41
- */
42
- getSnapshot(): TransferStats;
43
- /**
44
- * Returns a clone of the internal movingAverages
45
- */
46
- getMovingAverages(): MovingAverages;
47
- /**
48
- * Pushes the given operation data to the queue, along with the
49
- * current Timestamp, then resets the update timer.
50
- */
51
- push(counter: string, inc: number): void;
52
- /**
53
- * Resets the timeout for triggering updates.
54
- */
55
- _resetComputeTimeout(): void;
56
- /**
57
- * Calculates and returns the timeout for the next update based on
58
- * the urgency of the update.
59
- */
60
- _nextTimeout(): number;
61
- /**
62
- * If there are items in the queue, they will will be processed and
63
- * the frequency for all items will be updated based on the Timestamp
64
- * of the last item in the queue. The `update` event will also be emitted
65
- * with the latest stats.
66
- *
67
- * If there are no items in the queue, no action is taken.
68
- */
69
- _update(): void;
70
- /**
71
- * For each key in the stats, the frequency and moving averages
72
- * will be updated via Stats._updateFrequencyFor based on the time
73
- * difference between calls to this method.
74
- */
75
- _updateFrequency(latestTime: number): void;
76
- /**
77
- * Updates the `movingAverages` for the given `key` and also
78
- * resets the `frequencyAccumulator` for the `key`.
79
- */
80
- _updateFrequencyFor(key: 'dataReceived' | 'dataSent', timeDiffMS: number, latestTime: number): void;
81
- /**
82
- * For the given operation, `op`, the stats and `frequencyAccumulator`
83
- * will be updated or initialized if they don't already exist.
84
- */
85
- _applyOp(op: [string, number, number]): void;
86
- }
87
- //# sourceMappingURL=stats.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/metrics/stats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAIrE,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAErF,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,WAAW,CAAC,aAAa,CAAC,CAAA;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,eAAe,EAAE,CAAC,cAAc,EAAE,UAAU,CAAC,CAAA;IAC7C,sBAAsB,EAAE,MAAM,EAAE,CAAA;IAChC,2BAA2B,EAAE,MAAM,CAAA;IACnC,sBAAsB,EAAE,MAAM,CAAA;CAC/B;AAED,qBAAa,YAAa,SAAQ,YAAY,CAAC,WAAW,CAAE,YAAW,KAAK;IAC1E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAC1B,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC7C,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,iBAAiB,CAAQ;IACjC,OAAO,CAAC,qBAAqB,CAAwB;IACrD,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,OAAO,CAAC,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAQ;IACpD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAQ;IAC/C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAU;IAEjD;;OAEG;gBACU,IAAI,EAAE,SAAS;IAmC5B;;;;OAIG;IACH,KAAK;IAUL;;;OAGG;IACH,IAAI;IAOJ;;OAEG;IACH,WAAW;IAIX;;OAEG;IACH,iBAAiB,IAAK,cAAc;IAIpC;;;OAGG;IACH,IAAI,CAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;IAKlC;;OAEG;IACH,oBAAoB;IAIpB;;;OAGG;IACH,YAAY;IAOZ;;;;;;;OAOG;IACH,OAAO;IAqBP;;;;OAIG;IACH,gBAAgB,CAAE,UAAU,EAAE,MAAM;IASpC;;;OAGG;IACH,mBAAmB,CAAE,GAAG,EAAE,cAAc,GAAG,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAwB7F;;;OAGG;IACH,QAAQ,CAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;CA2BvC"}
@@ -1,183 +0,0 @@
1
- import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events';
2
- import { createMovingAverage } from './moving-average.js';
3
- // @ts-expect-error no types
4
- import retimer from 'retimer';
5
- export class DefaultStats extends EventEmitter {
6
- /**
7
- * A queue based manager for stat processing
8
- */
9
- constructor(init) {
10
- super();
11
- this.enabled = init.enabled;
12
- this.queue = [];
13
- this.stats = {
14
- dataReceived: 0n,
15
- dataSent: 0n
16
- };
17
- this.frequencyLastTime = Date.now();
18
- this.frequencyAccumulators = {};
19
- this.movingAverages = {
20
- dataReceived: [],
21
- dataSent: []
22
- };
23
- this.computeThrottleMaxQueueSize = init.computeThrottleMaxQueueSize;
24
- this.computeThrottleTimeout = init.computeThrottleTimeout;
25
- this._update = this._update.bind(this);
26
- this.movingAverageIntervals = init.movingAverageIntervals;
27
- for (let i = 0; i < init.initialCounters.length; i++) {
28
- const key = init.initialCounters[i];
29
- this.stats[key] = 0n;
30
- this.movingAverages[key] = [];
31
- for (let k = 0; k < this.movingAverageIntervals.length; k++) {
32
- const interval = this.movingAverageIntervals[k];
33
- const ma = this.movingAverages[key][interval] = createMovingAverage(interval);
34
- ma.push(this.frequencyLastTime, 0);
35
- }
36
- }
37
- }
38
- /**
39
- * Initializes the internal timer if there are items in the queue. This
40
- * should only need to be called if `Stats.stop` was previously called, as
41
- * `Stats.push` will also start the processing
42
- */
43
- start() {
44
- if (!this.enabled) {
45
- return;
46
- }
47
- if (this.queue.length > 0) {
48
- this._resetComputeTimeout();
49
- }
50
- }
51
- /**
52
- * Stops processing and computing of stats by clearing the internal
53
- * timer
54
- */
55
- stop() {
56
- if (this.timeout != null) {
57
- this.timeout.clear();
58
- this.timeout = null;
59
- }
60
- }
61
- /**
62
- * Returns a clone of the current stats.
63
- */
64
- getSnapshot() {
65
- return Object.assign({}, this.stats);
66
- }
67
- /**
68
- * Returns a clone of the internal movingAverages
69
- */
70
- getMovingAverages() {
71
- return Object.assign({}, this.movingAverages);
72
- }
73
- /**
74
- * Pushes the given operation data to the queue, along with the
75
- * current Timestamp, then resets the update timer.
76
- */
77
- push(counter, inc) {
78
- this.queue.push([counter, inc, Date.now()]);
79
- this._resetComputeTimeout();
80
- }
81
- /**
82
- * Resets the timeout for triggering updates.
83
- */
84
- _resetComputeTimeout() {
85
- this.timeout = retimer(this._update, this._nextTimeout());
86
- }
87
- /**
88
- * Calculates and returns the timeout for the next update based on
89
- * the urgency of the update.
90
- */
91
- _nextTimeout() {
92
- // calculate the need for an update, depending on the queue length
93
- const urgency = this.queue.length / this.computeThrottleMaxQueueSize;
94
- const timeout = Math.max(this.computeThrottleTimeout * (1 - urgency), 0);
95
- return timeout;
96
- }
97
- /**
98
- * If there are items in the queue, they will will be processed and
99
- * the frequency for all items will be updated based on the Timestamp
100
- * of the last item in the queue. The `update` event will also be emitted
101
- * with the latest stats.
102
- *
103
- * If there are no items in the queue, no action is taken.
104
- */
105
- _update() {
106
- this.timeout = null;
107
- if (this.queue.length > 0) {
108
- let last = ['', 0, 0];
109
- for (last of this.queue) {
110
- this._applyOp(last);
111
- }
112
- this.queue = [];
113
- if (last.length > 2 && last[0] !== '') {
114
- this._updateFrequency(last[2]); // contains timestamp of last op
115
- }
116
- this.dispatchEvent(new CustomEvent('update', {
117
- detail: this.stats
118
- }));
119
- }
120
- }
121
- /**
122
- * For each key in the stats, the frequency and moving averages
123
- * will be updated via Stats._updateFrequencyFor based on the time
124
- * difference between calls to this method.
125
- */
126
- _updateFrequency(latestTime) {
127
- const timeDiff = latestTime - this.frequencyLastTime;
128
- this._updateFrequencyFor('dataReceived', timeDiff, latestTime);
129
- this._updateFrequencyFor('dataSent', timeDiff, latestTime);
130
- this.frequencyLastTime = latestTime;
131
- }
132
- /**
133
- * Updates the `movingAverages` for the given `key` and also
134
- * resets the `frequencyAccumulator` for the `key`.
135
- */
136
- _updateFrequencyFor(key, timeDiffMS, latestTime) {
137
- const count = this.frequencyAccumulators[key] ?? 0;
138
- this.frequencyAccumulators[key] = 0;
139
- // if `timeDiff` is zero, `hz` becomes Infinity, so we fallback to 1ms
140
- const safeTimeDiff = timeDiffMS ?? 1;
141
- const hz = (count / safeTimeDiff) * 1000;
142
- let movingAverages = this.movingAverages[key];
143
- if (movingAverages == null) {
144
- movingAverages = this.movingAverages[key] = [];
145
- }
146
- const intervals = this.movingAverageIntervals;
147
- for (let i = 0; i < intervals.length; i++) {
148
- const movingAverageInterval = intervals[i];
149
- let movingAverage = movingAverages[movingAverageInterval];
150
- if (movingAverage == null) {
151
- movingAverage = movingAverages[movingAverageInterval] = createMovingAverage(movingAverageInterval);
152
- }
153
- movingAverage.push(latestTime, hz);
154
- }
155
- }
156
- /**
157
- * For the given operation, `op`, the stats and `frequencyAccumulator`
158
- * will be updated or initialized if they don't already exist.
159
- */
160
- _applyOp(op) {
161
- const key = op[0];
162
- const inc = op[1];
163
- if (typeof inc !== 'number') {
164
- throw new Error('invalid increment number');
165
- }
166
- let n;
167
- if (!Object.prototype.hasOwnProperty.call(this.stats, key)) {
168
- // @ts-expect-error cannot index type with key
169
- n = this.stats[key] = 0n;
170
- }
171
- else {
172
- // @ts-expect-error cannot index type with key
173
- n = this.stats[key];
174
- }
175
- // @ts-expect-error cannot index type with key
176
- this.stats[key] = n + BigInt(inc);
177
- if (this.frequencyAccumulators[key] == null) {
178
- this.frequencyAccumulators[key] = 0;
179
- }
180
- this.frequencyAccumulators[key] += inc;
181
- }
182
- }
183
- //# sourceMappingURL=stats.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/metrics/stats.ts"],"names":[],"mappings":"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"}
@@ -1,311 +0,0 @@
1
- import { pipe } from 'it-pipe'
2
- import each from 'it-foreach'
3
- import LRU from 'hashlru'
4
- import { METRICS as defaultOptions } from '../constants.js'
5
- import { DefaultStats, StatsInit } from './stats.js'
6
- import type { ComponentMetricsUpdate, Metrics, Stats, TrackedMetric, TrackStreamOptions } from '@libp2p/interface-metrics'
7
- import type { PeerId } from '@libp2p/interface-peer-id'
8
- import type { Startable } from '@libp2p/interfaces/startable'
9
-
10
- const initialCounters: ['dataReceived', 'dataSent'] = [
11
- 'dataReceived',
12
- 'dataSent'
13
- ]
14
-
15
- const directionToEvent = {
16
- in: 'dataReceived',
17
- out: 'dataSent'
18
- }
19
-
20
- export interface OnMessageOptions {
21
- remotePeer: PeerId
22
- protocol?: string
23
- direction: 'in' | 'out'
24
- dataLength: number
25
- }
26
-
27
- export interface MetricsInit {
28
- enabled: boolean
29
- computeThrottleMaxQueueSize: number
30
- computeThrottleTimeout: number
31
- movingAverageIntervals: number[]
32
- maxOldPeersRetention: number
33
- }
34
-
35
- export class DefaultMetrics implements Metrics, Startable {
36
- public globalStats: DefaultStats
37
-
38
- private readonly enabled: boolean
39
- private readonly peerStats: Map<string, DefaultStats>
40
- private readonly protocolStats: Map<string, DefaultStats>
41
- private readonly oldPeers: ReturnType<typeof LRU>
42
- private running: boolean
43
- private readonly systems: Map<string, Map<string, Map<string, TrackedMetric>>>
44
- private readonly statsInit: StatsInit
45
-
46
- constructor (init: MetricsInit) {
47
- this.enabled = init.enabled
48
- this.statsInit = {
49
- ...init,
50
- initialCounters
51
- }
52
- this.globalStats = new DefaultStats(this.statsInit)
53
- this.peerStats = new Map()
54
- this.protocolStats = new Map()
55
- this.oldPeers = LRU(init.maxOldPeersRetention ?? defaultOptions.maxOldPeersRetention)
56
- this.running = false
57
- this._onMessage = this._onMessage.bind(this)
58
- this.systems = new Map()
59
- }
60
-
61
- isStarted () {
62
- return this.running
63
- }
64
-
65
- /**
66
- * Must be called for stats to saved. Any data pushed for tracking
67
- * will be ignored.
68
- */
69
- async start () {
70
- if (!this.enabled) {
71
- return
72
- }
73
-
74
- this.running = true
75
- }
76
-
77
- /**
78
- * Stops all averages timers and prevents new data from being tracked.
79
- * Once `stop` is called, `start` must be called to resume stats tracking.
80
- */
81
- async stop () {
82
- if (!this.running) {
83
- return
84
- }
85
-
86
- this.running = false
87
- this.globalStats.stop()
88
-
89
- for (const stats of this.peerStats.values()) {
90
- stats.stop()
91
- }
92
-
93
- for (const stats of this.protocolStats.values()) {
94
- stats.stop()
95
- }
96
- }
97
-
98
- /**
99
- * Gets the global `Stats` object
100
- */
101
- getGlobal () {
102
- return this.globalStats
103
- }
104
-
105
- /**
106
- * Returns a list of `PeerId` strings currently being tracked
107
- */
108
- getPeers () {
109
- return Array.from(this.peerStats.keys())
110
- }
111
-
112
- getComponentMetrics () {
113
- return this.systems
114
- }
115
-
116
- updateComponentMetric (update: ComponentMetricsUpdate) {
117
- const { system = 'libp2p', component, metric, value, label, help } = update
118
-
119
- if (!this.systems.has(system)) {
120
- this.systems.set(system, new Map())
121
- }
122
-
123
- const systemMetrics = this.systems.get(system)
124
-
125
- if (systemMetrics == null) {
126
- throw new Error('Unknown metric system')
127
- }
128
-
129
- if (!systemMetrics.has(component)) {
130
- systemMetrics.set(component, new Map())
131
- }
132
-
133
- const componentMetrics = systemMetrics.get(component)
134
-
135
- if (componentMetrics == null) {
136
- throw new Error('Unknown metric component')
137
- }
138
-
139
- componentMetrics.set(metric, {
140
- label,
141
- help,
142
- calculate: typeof value !== 'function' ? () => value : value
143
- })
144
- }
145
-
146
- /**
147
- * Returns the `Stats` object for the given `PeerId` whether it
148
- * is a live peer, or in the disconnected peer LRU cache.
149
- */
150
- forPeer (peerId: PeerId): Stats | undefined {
151
- const idString = peerId.toString()
152
- return this.peerStats.get(idString) ?? this.oldPeers.get(idString)
153
- }
154
-
155
- /**
156
- * Returns a list of all protocol strings currently being tracked
157
- */
158
- getProtocols (): string[] {
159
- return Array.from(this.protocolStats.keys())
160
- }
161
-
162
- /**
163
- * Returns the `Stats` object for the given `protocol`
164
- */
165
- forProtocol (protocol: string): Stats | undefined {
166
- return this.protocolStats.get(protocol)
167
- }
168
-
169
- /**
170
- * Should be called when all connections to a given peer
171
- * have closed. The `Stats` collection for the peer will
172
- * be stopped and moved to an LRU for temporary retention.
173
- */
174
- onPeerDisconnected (peerId: PeerId) {
175
- const idString = peerId.toString()
176
- const peerStats = this.peerStats.get(idString)
177
-
178
- if (peerStats != null) {
179
- peerStats.stop()
180
-
181
- this.peerStats.delete(idString)
182
- this.oldPeers.set(idString, peerStats)
183
- }
184
- }
185
-
186
- /**
187
- * Takes the metadata for a message and tracks it in the
188
- * appropriate categories. If the protocol is present, protocol
189
- * stats will also be tracked.
190
- */
191
- _onMessage (opts: OnMessageOptions) {
192
- if (!this.running) {
193
- return
194
- }
195
-
196
- const { remotePeer, protocol, direction, dataLength } = opts
197
-
198
- const key = directionToEvent[direction]
199
-
200
- let peerStats = this.forPeer(remotePeer)
201
- if (peerStats == null) {
202
- const stats = new DefaultStats(this.statsInit)
203
- this.peerStats.set(remotePeer.toString(), stats)
204
- peerStats = stats
205
- }
206
-
207
- // Peer and global stats
208
- peerStats.push(key, dataLength)
209
- this.globalStats.push(key, dataLength)
210
-
211
- // Protocol specific stats
212
- if (protocol != null) {
213
- let protocolStats = this.forProtocol(protocol)
214
-
215
- if (protocolStats == null) {
216
- const stats = new DefaultStats(this.statsInit)
217
- this.protocolStats.set(protocol, stats)
218
- protocolStats = stats
219
- }
220
-
221
- protocolStats.push(key, dataLength)
222
- }
223
- }
224
-
225
- /**
226
- * Replaces the `PeerId` string with the given `peerId`.
227
- * If stats are already being tracked for the given `peerId`, the
228
- * placeholder stats will be merged with the existing stats.
229
- *
230
- * @param {PeerId} placeholder - A peerId string
231
- * @param {PeerId} peerId
232
- * @returns {void}
233
- */
234
- updatePlaceholder (placeholder: PeerId, peerId: PeerId) {
235
- if (!this.running) {
236
- return
237
- }
238
-
239
- const placeholderString = placeholder.toString()
240
- const placeholderStats = this.peerStats.get(placeholderString) ?? this.oldPeers.get(placeholderString)
241
- const peerIdString = peerId.toString()
242
- const existingStats = this.peerStats.get(peerIdString) ?? this.oldPeers.get(peerIdString)
243
- let mergedStats = placeholderStats
244
-
245
- // If we already have stats, merge the two
246
- if (existingStats != null) {
247
- // If existing, merge
248
- mergedStats = mergeStats(existingStats, mergedStats)
249
- // Attempt to delete from the old peers list just in case it was tracked there
250
- this.oldPeers.remove(peerIdString)
251
- }
252
-
253
- this.peerStats.delete(placeholder.toString())
254
- this.peerStats.set(peerIdString, mergedStats)
255
- mergedStats.start()
256
- }
257
-
258
- /**
259
- * Tracks data running through a given Duplex Iterable `stream`. If
260
- * the `peerId` is not provided, a placeholder string will be created and
261
- * returned. This allows lazy tracking of a peer when the peer is not yet known.
262
- * When the `PeerId` is known, `Metrics.updatePlaceholder` should be called
263
- * with the placeholder string returned from here, and the known `PeerId`.
264
- */
265
- trackStream (opts: TrackStreamOptions): void {
266
- const { stream, remotePeer, protocol } = opts
267
-
268
- if (!this.running) {
269
- return
270
- }
271
-
272
- const source = stream.source
273
- stream.source = each(source, chunk => this._onMessage({
274
- remotePeer,
275
- protocol,
276
- direction: 'in',
277
- dataLength: chunk.byteLength
278
- }))
279
-
280
- const sink = stream.sink
281
- stream.sink = async source => {
282
- return await pipe(
283
- source,
284
- (source) => each(source, chunk => {
285
- this._onMessage({
286
- remotePeer,
287
- protocol,
288
- direction: 'out',
289
- dataLength: chunk.byteLength
290
- })
291
- }),
292
- sink
293
- )
294
- }
295
- }
296
- }
297
-
298
- /**
299
- * Merges `other` into `target`. `target` will be modified
300
- * and returned
301
- */
302
- function mergeStats (target: DefaultStats, other: DefaultStats) {
303
- target.stop()
304
- other.stop()
305
-
306
- // Merge queues
307
- target.queue = [...target.queue, ...other.queue]
308
-
309
- // TODO: how to merge moving averages?
310
- return target
311
- }
@@ -1,53 +0,0 @@
1
- import type { MovingAverage } from '@libp2p/interface-metrics'
2
-
3
- export class DefaultMovingAverage {
4
- public movingAverage: number
5
- public variance: number
6
- public deviation: number
7
- public forecast: number
8
- private readonly timespan: number
9
- private previousTime?: number
10
-
11
- constructor (timespan: number) {
12
- if (typeof timespan !== 'number') {
13
- throw new Error('must provide a timespan to the moving average constructor')
14
- }
15
-
16
- if (timespan <= 0) {
17
- throw new Error('must provide a timespan > 0 to the moving average constructor')
18
- }
19
-
20
- this.timespan = timespan
21
- this.movingAverage = 0
22
- this.variance = 0
23
- this.deviation = 0
24
- this.forecast = 0
25
- }
26
-
27
- alpha (t: number, pt: number) {
28
- return 1 - (Math.exp(-(t - pt) / this.timespan))
29
- }
30
-
31
- push (time: number, value: number) {
32
- if (this.previousTime != null) {
33
- // calculate moving average
34
- const a = this.alpha(time, this.previousTime)
35
- const diff = value - this.movingAverage
36
- const incr = a * diff
37
- this.movingAverage = a * value + (1 - a) * this.movingAverage
38
- // calculate variance & deviation
39
- this.variance = (1 - a) * (this.variance + diff * incr)
40
- this.deviation = Math.sqrt(this.variance)
41
- // calculate forecast
42
- this.forecast = this.movingAverage + a * diff
43
- } else {
44
- this.movingAverage = value
45
- }
46
-
47
- this.previousTime = time
48
- }
49
- }
50
-
51
- export function createMovingAverage (timespan: number): MovingAverage {
52
- return new DefaultMovingAverage(timespan)
53
- }