@libp2p/devtools-metrics 0.0.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.
- package/LICENSE +4 -0
- package/README.md +68 -0
- package/dist/index.min.js +3 -0
- package/dist/src/index.d.ts +116 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +215 -0
- package/dist/src/index.js.map +1 -0
- package/dist/typedoc-urls.json +28 -0
- package/package.json +62 -0
- package/src/index.ts +360 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @libp2p/devtools-metrics
|
|
2
|
+
|
|
3
|
+
[](http://libp2p.io/)
|
|
4
|
+
[](https://discuss.libp2p.io)
|
|
5
|
+
[](https://codecov.io/gh/libp2p/js-libp2p)
|
|
6
|
+
[](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amain)
|
|
7
|
+
|
|
8
|
+
> Collect libp2p metrics and send them to browser DevTools
|
|
9
|
+
|
|
10
|
+
# About
|
|
11
|
+
|
|
12
|
+
<!--
|
|
13
|
+
|
|
14
|
+
!IMPORTANT!
|
|
15
|
+
|
|
16
|
+
Everything in this README between "# About" and "# Install" is automatically
|
|
17
|
+
generated and will be overwritten the next time the doc generator is run.
|
|
18
|
+
|
|
19
|
+
To make changes to this section, please update the @packageDocumentation section
|
|
20
|
+
of src/index.js or src/index.ts
|
|
21
|
+
|
|
22
|
+
To experiment with formatting, please run "npm run docs" from the root of this
|
|
23
|
+
repo and examine the changes made.
|
|
24
|
+
|
|
25
|
+
-->
|
|
26
|
+
|
|
27
|
+
Configure your browser-based libp2p node with DevTools metrics:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { createLibp2p } from 'libp2p'
|
|
31
|
+
import { devtoolsMetrics } from '@libp2p/devtools-metrics'
|
|
32
|
+
|
|
33
|
+
const node = await createLibp2p({
|
|
34
|
+
metrics: devToolsMetrics()
|
|
35
|
+
})
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then use the [DevTools plugin](https://github.com/ipfs-shipyard/js-libp2p-devtools)
|
|
39
|
+
for Chrome or Firefox to inspect the state of your running node.
|
|
40
|
+
|
|
41
|
+
# Install
|
|
42
|
+
|
|
43
|
+
```console
|
|
44
|
+
$ npm i @libp2p/devtools-metrics
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Browser `<script>` tag
|
|
48
|
+
|
|
49
|
+
Loading this module through a script tag will make it's exports available as `Libp2pDevtoolsMetrics` in the global namespace.
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<script src="https://unpkg.com/@libp2p/devtools-metrics/dist/index.min.js"></script>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
# API Docs
|
|
56
|
+
|
|
57
|
+
- <https://libp2p.github.io/js-libp2p/modules/_libp2p_devtools_metrics.html>
|
|
58
|
+
|
|
59
|
+
# License
|
|
60
|
+
|
|
61
|
+
Licensed under either of
|
|
62
|
+
|
|
63
|
+
- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p/blob/main/packages/metrics-devtools/LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
|
|
64
|
+
- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p/blob/main/packages/metrics-devtools/LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
|
|
65
|
+
|
|
66
|
+
# Contribution
|
|
67
|
+
|
|
68
|
+
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
(function (root, factory) {(typeof module === 'object' && module.exports) ? module.exports = factory() : root.Libp2PDevtoolsMetrics = factory()}(typeof self !== 'undefined' ? self : this, function () {
|
|
2
|
+
"use strict";var Libp2PDevtoolsMetrics=(()=>{var ge=Object.create;var j=Object.defineProperty;var be=Object.getOwnPropertyDescriptor;var Ce=Object.getOwnPropertyNames;var we=Object.getPrototypeOf,ve=Object.prototype.hasOwnProperty;var $=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ye=(r,e)=>{for(var t in e)j(r,t,{get:e[t],enumerable:!0})},Z=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Ce(e))!ve.call(r,s)&&s!==t&&j(r,s,{get:()=>e[s],enumerable:!(n=be(e,s))||n.enumerable});return r};var xe=(r,e,t)=>(t=r!=null?ge(we(r)):{},Z(e||!r||!r.__esModule?j(t,"default",{value:r,enumerable:!0}):t,r)),Fe=r=>Z(j({},"__esModule",{value:!0}),r);var H=$((He,Y)=>{var U=1e3,I=U*60,L=I*60,A=L*24,Me=A*7,Se=A*365.25;Y.exports=function(r,e){e=e||{};var t=typeof r;if(t==="string"&&r.length>0)return Ee(r);if(t==="number"&&isFinite(r))return e.long?Pe(r):Ae(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function Ee(r){if(r=String(r),!(r.length>100)){var e=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(r);if(e){var t=parseFloat(e[1]),n=(e[2]||"ms").toLowerCase();switch(n){case"years":case"year":case"yrs":case"yr":case"y":return t*Se;case"weeks":case"week":case"w":return t*Me;case"days":case"day":case"d":return t*A;case"hours":case"hour":case"hrs":case"hr":case"h":return t*L;case"minutes":case"minute":case"mins":case"min":case"m":return t*I;case"seconds":case"second":case"secs":case"sec":case"s":return t*U;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return t;default:return}}}}function Ae(r){var e=Math.abs(r);return e>=A?Math.round(r/A)+"d":e>=L?Math.round(r/L)+"h":e>=I?Math.round(r/I)+"m":e>=U?Math.round(r/U)+"s":r+"ms"}function Pe(r){var e=Math.abs(r);return e>=A?z(r,e,A,"day"):e>=L?z(r,e,L,"hour"):e>=I?z(r,e,I,"minute"):e>=U?z(r,e,U,"second"):r+" ms"}function z(r,e,t,n){var s=e>=t*1.5;return Math.round(r/t)+" "+n+(s?"s":"")}});var te=$((et,ee)=>{function ke(r){t.debug=t,t.default=t,t.coerce=f,t.disable=a,t.enable=s,t.enabled=c,t.humanize=H(),t.destroy=S,Object.keys(r).forEach(o=>{t[o]=r[o]}),t.names=[],t.skips=[],t.formatters={};function e(o){let i=0;for(let p=0;p<o.length;p++)i=(i<<5)-i+o.charCodeAt(p),i|=0;return t.colors[Math.abs(i)%t.colors.length]}t.selectColor=e;function t(o){let i,p=null,P,l;function d(...h){if(!d.enabled)return;let m=d,b=Number(new Date),x=b-(i||b);m.diff=x,m.prev=i,m.curr=b,i=b,h[0]=t.coerce(h[0]),typeof h[0]!="string"&&h.unshift("%O");let g=0;h[0]=h[0].replace(/%([a-zA-Z%])/g,(F,v)=>{if(F==="%%")return"%";g++;let M=t.formatters[v];if(typeof M=="function"){let k=h[g];F=M.call(m,k),h.splice(g,1),g--}return F}),t.formatArgs.call(m,h),(m.log||t.log).apply(m,h)}return d.namespace=o,d.useColors=t.useColors(),d.color=t.selectColor(o),d.extend=n,d.destroy=t.destroy,Object.defineProperty(d,"enabled",{enumerable:!0,configurable:!1,get:()=>p!==null?p:(P!==t.namespaces&&(P=t.namespaces,l=t.enabled(o)),l),set:h=>{p=h}}),typeof t.init=="function"&&t.init(d),d}function n(o,i){let p=t(this.namespace+(typeof i>"u"?":":i)+o);return p.log=this.log,p}function s(o){t.save(o),t.namespaces=o,t.names=[],t.skips=[];let i,p=(typeof o=="string"?o:"").split(/[\s,]+/),P=p.length;for(i=0;i<P;i++)p[i]&&(o=p[i].replace(/\*/g,".*?"),o[0]==="-"?t.skips.push(new RegExp("^"+o.slice(1)+"$")):t.names.push(new RegExp("^"+o+"$")))}function a(){let o=[...t.names.map(u),...t.skips.map(u).map(i=>"-"+i)].join(",");return t.enable(""),o}function c(o){if(o[o.length-1]==="*")return!0;let i,p;for(i=0,p=t.skips.length;i<p;i++)if(t.skips[i].test(o))return!1;for(i=0,p=t.names.length;i<p;i++)if(t.names[i].test(o))return!0;return!1}function u(o){return o.toString().substring(2,o.toString().length-2).replace(/\.\*\?$/,"*")}function f(o){return o instanceof Error?o.stack||o.message:o}function S(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return t.enable(t.load()),t}ee.exports=ke});var re=$((y,D)=>{y.formatArgs=Ie;y.save=Le;y.load=Oe;y.useColors=Ue;y.storage=Ne();y.destroy=(()=>{let r=!1;return()=>{r||(r=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})();y.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function Ue(){return typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs)?!0:typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)?!1:typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function Ie(r){if(r[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+r[0]+(this.useColors?"%c ":" ")+"+"+D.exports.humanize(this.diff),!this.useColors)return;let e="color: "+this.color;r.splice(1,0,e,"color: inherit");let t=0,n=0;r[0].replace(/%[a-zA-Z%]/g,s=>{s!=="%%"&&(t++,s==="%c"&&(n=t))}),r.splice(n,0,e)}y.log=console.debug||console.log||(()=>{});function Le(r){try{r?y.storage.setItem("debug",r):y.storage.removeItem("debug")}catch{}}function Oe(){let r;try{r=y.storage.getItem("debug")}catch{}return!r&&typeof process<"u"&&"env"in process&&(r=process.env.DEBUG),r}function Ne(){try{return localStorage}catch{}}D.exports=te()(y);var{formatters:je}=D.exports;je.j=function(r){try{return JSON.stringify(r)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}});var Qe={};ye(Qe,{SOURCE_APPLICATION:()=>Xe,SOURCE_DEVTOOLS:()=>Je,devToolsMetrics:()=>Ze});function K(r){return r!=null&&typeof r.start=="function"&&typeof r.stop=="function"}async function Q(...r){let e=[];for(let t of r)K(t)&&e.push(t);await Promise.all(e.map(async t=>{t.beforeStart!=null&&await t.beforeStart()})),await Promise.all(e.map(async t=>{await t.start()})),await Promise.all(e.map(async t=>{t.afterStart!=null&&await t.afterStart()}))}async function W(...r){let e=[];for(let t of r)K(t)&&e.push(t);await Promise.all(e.map(async t=>{t.beforeStop!=null&&await t.beforeStop()})),await Promise.all(e.map(async t=>{await t.stop()})),await Promise.all(e.map(async t=>{t.afterStop!=null&&await t.afterStop()}))}var w=xe(re(),1);var tt=new Uint8Array(0);function ne(r){if(r instanceof Uint8Array&&r.constructor.name==="Uint8Array")return r;if(r instanceof ArrayBuffer)return new Uint8Array(r);if(ArrayBuffer.isView(r))return new Uint8Array(r.buffer,r.byteOffset,r.byteLength);throw new Error("Unknown type, must be binary type")}function ze(r,e){if(r.length>=255)throw new TypeError("Alphabet too long");for(var t=new Uint8Array(256),n=0;n<t.length;n++)t[n]=255;for(var s=0;s<r.length;s++){var a=r.charAt(s),c=a.charCodeAt(0);if(t[c]!==255)throw new TypeError(a+" is ambiguous");t[c]=s}var u=r.length,f=r.charAt(0),S=Math.log(u)/Math.log(256),o=Math.log(256)/Math.log(u);function i(l){if(l instanceof Uint8Array||(ArrayBuffer.isView(l)?l=new Uint8Array(l.buffer,l.byteOffset,l.byteLength):Array.isArray(l)&&(l=Uint8Array.from(l))),!(l instanceof Uint8Array))throw new TypeError("Expected Uint8Array");if(l.length===0)return"";for(var d=0,h=0,m=0,b=l.length;m!==b&&l[m]===0;)m++,d++;for(var x=(b-m)*o+1>>>0,g=new Uint8Array(x);m!==b;){for(var E=l[m],F=0,v=x-1;(E!==0||F<h)&&v!==-1;v--,F++)E+=256*g[v]>>>0,g[v]=E%u>>>0,E=E/u>>>0;if(E!==0)throw new Error("Non-zero carry");h=F,m++}for(var M=x-h;M!==x&&g[M]===0;)M++;for(var k=f.repeat(d);M<x;++M)k+=r.charAt(g[M]);return k}function p(l){if(typeof l!="string")throw new TypeError("Expected String");if(l.length===0)return new Uint8Array;var d=0;if(l[d]!==" "){for(var h=0,m=0;l[d]===f;)h++,d++;for(var b=(l.length-d)*S+1>>>0,x=new Uint8Array(b);l[d];){var g=t[l.charCodeAt(d)];if(g===255)return;for(var E=0,F=b-1;(g!==0||E<m)&&F!==-1;F--,E++)g+=u*x[F]>>>0,x[F]=g%256>>>0,g=g/256>>>0;if(g!==0)throw new Error("Non-zero carry");m=E,d++}if(l[d]!==" "){for(var v=b-m;v!==b&&x[v]===0;)v++;for(var M=new Uint8Array(h+(b-v)),k=h;v!==b;)M[k++]=x[v++];return M}}}function P(l){var d=p(l);if(d)return d;throw new Error(`Non-${e} character`)}return{encode:i,decodeUnsafe:p,decode:P}}var De=ze,_e=De,se=_e;var T=class{name;prefix;baseEncode;constructor(e,t,n){this.name=e,this.prefix=t,this.baseEncode=n}encode(e){if(e instanceof Uint8Array)return`${this.prefix}${this.baseEncode(e)}`;throw Error("Unknown type, must be binary type")}},q=class{name;prefix;baseDecode;prefixCodePoint;constructor(e,t,n){if(this.name=e,this.prefix=t,t.codePointAt(0)===void 0)throw new Error("Invalid prefix character");this.prefixCodePoint=t.codePointAt(0),this.baseDecode=n}decode(e){if(typeof e=="string"){if(e.codePointAt(0)!==this.prefixCodePoint)throw Error(`Unable to decode multibase string ${JSON.stringify(e)}, ${this.name} decoder only supports inputs prefixed with ${this.prefix}`);return this.baseDecode(e.slice(this.prefix.length))}else throw Error("Can only multibase decode strings")}or(e){return oe(this,e)}},R=class{decoders;constructor(e){this.decoders=e}or(e){return oe(this,e)}decode(e){let t=e[0],n=this.decoders[t];if(n!=null)return n.decode(e);throw RangeError(`Unable to decode multibase string ${JSON.stringify(e)}, only inputs prefixed with ${Object.keys(this.decoders)} are supported`)}};function oe(r,e){return new R({...r.decoders??{[r.prefix]:r},...e.decoders??{[e.prefix]:e}})}var V=class{name;prefix;baseEncode;baseDecode;encoder;decoder;constructor(e,t,n,s){this.name=e,this.prefix=t,this.baseEncode=n,this.baseDecode=s,this.encoder=new T(e,t,n),this.decoder=new q(e,t,s)}encode(e){return this.encoder.encode(e)}decode(e){return this.decoder.decode(e)}};function ie({name:r,prefix:e,encode:t,decode:n}){return new V(r,e,t,n)}function G({name:r,prefix:e,alphabet:t}){let{encode:n,decode:s}=se(t,r);return ie({prefix:e,name:r,encode:n,decode:a=>ne(s(a))})}function $e(r,e,t,n){let s={};for(let o=0;o<e.length;++o)s[e[o]]=o;let a=r.length;for(;r[a-1]==="=";)--a;let c=new Uint8Array(a*t/8|0),u=0,f=0,S=0;for(let o=0;o<a;++o){let i=s[r[o]];if(i===void 0)throw new SyntaxError(`Non-${n} character`);f=f<<t|i,u+=t,u>=8&&(u-=8,c[S++]=255&f>>u)}if(u>=t||255&f<<8-u)throw new SyntaxError("Unexpected end of data");return c}function Te(r,e,t){let n=e[e.length-1]==="=",s=(1<<t)-1,a="",c=0,u=0;for(let f=0;f<r.length;++f)for(u=u<<8|r[f],c+=8;c>t;)c-=t,a+=e[s&u>>c];if(c!==0&&(a+=e[s&u<<t-c]),n)for(;a.length*t&7;)a+="=";return a}function C({name:r,prefix:e,bitsPerChar:t,alphabet:n}){return ie({prefix:e,name:r,encode(s){return Te(s,n,t)},decode(s){return $e(s,n,t,r)}})}var ae=C({prefix:"b",name:"base32",alphabet:"abcdefghijklmnopqrstuvwxyz234567",bitsPerChar:5}),ct=C({prefix:"B",name:"base32upper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",bitsPerChar:5}),lt=C({prefix:"c",name:"base32pad",alphabet:"abcdefghijklmnopqrstuvwxyz234567=",bitsPerChar:5}),ut=C({prefix:"C",name:"base32padupper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",bitsPerChar:5}),dt=C({prefix:"v",name:"base32hex",alphabet:"0123456789abcdefghijklmnopqrstuv",bitsPerChar:5}),ft=C({prefix:"V",name:"base32hexupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV",bitsPerChar:5}),pt=C({prefix:"t",name:"base32hexpad",alphabet:"0123456789abcdefghijklmnopqrstuv=",bitsPerChar:5}),ht=C({prefix:"T",name:"base32hexpadupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV=",bitsPerChar:5}),mt=C({prefix:"h",name:"base32z",alphabet:"ybndrfg8ejkmcpqxot1uwisza345h769",bitsPerChar:5});var ce=G({name:"base58btc",prefix:"z",alphabet:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"}),Ct=G({name:"base58flickr",prefix:"Z",alphabet:"123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"});var _=C({prefix:"m",name:"base64",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",bitsPerChar:6}),yt=C({prefix:"M",name:"base64pad",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",bitsPerChar:6}),xt=C({prefix:"u",name:"base64url",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",bitsPerChar:6}),Ft=C({prefix:"U",name:"base64urlpad",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",bitsPerChar:6});w.default.formatters.b=r=>r==null?"undefined":ce.baseEncode(r);w.default.formatters.t=r=>r==null?"undefined":ae.baseEncode(r);w.default.formatters.m=r=>r==null?"undefined":_.baseEncode(r);w.default.formatters.p=r=>r==null?"undefined":r.toString();w.default.formatters.c=r=>r==null?"undefined":r.toString();w.default.formatters.k=r=>r==null?"undefined":r.toString();w.default.formatters.a=r=>r==null?"undefined":r.toString();function qe(r){let e=()=>{};return e.enabled=!1,e.color="",e.diff=0,e.log=()=>{},e.namespace=r,e.destroy=()=>!0,e.extend=()=>e,e}function le(r){let e=qe(`${r}:trace`);return w.default.enabled(`${r}:trace`)&&w.default.names.map(t=>t.toString()).find(t=>t.includes(":trace"))!=null&&(e=(0,w.default)(`${r}:trace`)),Object.assign((0,w.default)(r),{error:(0,w.default)(`${r}:error`),trace:e})}function ue(){w.default.disable()}function de(r){w.default.enable(r)}function Re(r){let[e,t]=r[Symbol.asyncIterator]!=null?[r[Symbol.asyncIterator](),Symbol.asyncIterator]:[r[Symbol.iterator](),Symbol.iterator],n=[];return{peek:()=>e.next(),push:s=>{n.push(s)},next:()=>n.length>0?{done:!1,value:n.shift()}:e.next(),[t](){return this}}}var fe=Re;function Ve(r){return r[Symbol.asyncIterator]!=null}function pe(r){return r?.then!=null}function Ge(r,e){let t=0;if(Ve(r))return async function*(){for await(let f of r){let S=e(f,t++);pe(S)&&await S,yield f}}();let n=fe(r),{value:s,done:a}=n.next();if(a===!0)return function*(){}();if(typeof e(s,t++)?.then=="function")return async function*(){yield s;for await(let f of n){let S=e(f,t++);pe(S)&&await S,yield f}}();let u=e;return function*(){yield s;for(let f of n)u(f,t++),yield f}()}var B=Ge;var Be=le("libp2p:simple-metrics"),O=class{value=0;update(e){this.value=e}increment(e=1){this.value+=e}decrement(e=1){this.value-=e}reset(){this.value=0}timer(){let e=Date.now();return()=>{this.value=Date.now()-e}}},N=class{values={};update(e){Object.entries(e).forEach(([t,n])=>{this.values[t]=n})}increment(e){Object.entries(e).forEach(([t,n])=>{this.values[t]=this.values[t]??0;let s=typeof n=="number"?n:1;this.values[t]+=Number(s)})}decrement(e){Object.entries(e).forEach(([t,n])=>{this.values[t]=this.values[t]??0;let s=typeof n=="number"?n:1;this.values[t]-=Number(s)})}reset(){this.values={}}timer(e){let t=Date.now();return()=>{this.values[e]=Date.now()-t}}},J=class{metrics=new Map;transferStats;started;interval;intervalMs;onMetrics;constructor(e,t){this.started=!1,this._emitMetrics=this._emitMetrics.bind(this),this.intervalMs=t.intervalMs??1e3,this.onMetrics=t.onMetrics,this.transferStats=new Map}isStarted(){return this.started}start(){this.started=!0,this.interval=setInterval(this._emitMetrics,this.intervalMs)}stop(){this.started=!1,clearInterval(this.interval)}_emitMetrics(){Promise.resolve().then(async()=>{let e={};for(let[t,n]of this.metrics.entries())n instanceof O?e[t]=n.value:n instanceof N?e[t]=n.values:e[t]=await n();this.onMetrics(structuredClone(e))}).catch(e=>{Be.error("could not invoke onMetrics callback",e)})}_incrementValue(e,t){let n=this.transferStats.get(e)??0;this.transferStats.set(e,n+t)}_track(e,t){let n=this,s=e.sink;e.sink=async function(u){await s(B(u,f=>{n._incrementValue(`${t} sent`,f.byteLength)}))};let a=e.source;e.source=B(a,c=>{n._incrementValue(`${t} received`,c.byteLength)})}trackMultiaddrConnection(e){this._track(e,"global")}trackProtocolStream(e,t){e.protocol!=null&&this._track(e,e.protocol)}registerMetric(e,t={}){if(e==null||e.trim()==="")throw new Error("Metric name is required");if(t?.calculate!=null){this.metrics.set(e,t.calculate);return}let n=new O;return this.metrics.set(e,n),n}registerMetricGroup(e,t={}){if(e==null||e.trim()==="")throw new Error("Metric name is required");if(t?.calculate!=null){this.metrics.set(e,t.calculate);return}let n=new N;return this.metrics.set(e,n),n}registerCounter(e,t={}){if(e==null||e.trim()==="")throw new Error("Metric name is required");if(t?.calculate!=null){this.metrics.set(e,t.calculate);return}let n=new O;return this.metrics.set(e,n),n}registerCounterGroup(e,t={}){if(e==null||e.trim()==="")throw new Error("Metric name is required");if(t?.calculate!=null){this.metrics.set(e,t.calculate);return}let n=new N;return this.metrics.set(e,n),n}};function he(r){return e=>new J(e,r)}var Je="@libp2p/devtools-metrics:devtools",Xe="@libp2p/devtools-metrics:node",X=class{log;events;peerId;transportManager;registrar;connectionManager;peerStore;simpleMetrics;intervalMs;constructor(e,t){this.log=e.logger.forComponent("libp2p:devtools-metrics"),this.events=e.events,this.peerId=e.peerId,this.transportManager=e.transportManager,this.registrar=e.registrar,this.connectionManager=e.connectionManager,this.peerStore=e.peerStore,this.intervalMs=t?.intervalMs,this.sendPeers=Ke(this.sendPeers.bind(this),1e3),this.sendSelfUpdate=this.sendSelfUpdate.bind(this),this.processIncomingMessage=this.processIncomingMessage.bind(this)}trackMultiaddrConnection(e){this.simpleMetrics?.trackMultiaddrConnection(e)}trackProtocolStream(e,t){this.simpleMetrics?.trackProtocolStream(e,t)}registerMetric(e,t){return this.simpleMetrics?.registerMetric(e,t)}registerMetricGroup(e,t){return this.simpleMetrics?.registerMetricGroup(e,t)}registerCounter(e,t){return this.simpleMetrics?.registerCounter(e,t)}registerCounterGroup(e,t){return this.simpleMetrics?.registerCounterGroup(e,t)}async start(){this.events.addEventListener("peer:connect",this.sendPeers),this.events.addEventListener("peer:disconnect",this.sendPeers),this.events.addEventListener("peer:identify",this.sendPeers),this.events.addEventListener("peer:update",this.sendPeers),this.events.addEventListener("self:peer:update",this.sendSelfUpdate),window.addEventListener("message",this.processIncomingMessage),this.simpleMetrics=he({intervalMs:this.intervalMs,onMetrics:e=>{let t={source:"@libp2p/devtools-metrics:node",type:"metrics",metrics:e};this.log("post metrics message"),window.postMessage(t,"*")}})({}),await Q(this.simpleMetrics)}async stop(){window.removeEventListener("message",this.processIncomingMessage),this.events.removeEventListener("self:peer:update",this.sendSelfUpdate),this.events.removeEventListener("peer:connect",this.sendPeers),this.events.removeEventListener("peer:disconnect",this.sendPeers),this.events.removeEventListener("peer:identify",this.sendPeers),this.events.removeEventListener("peer:update",this.sendPeers),await W(this.simpleMetrics)}sendPeers(){Promise.resolve().then(async()=>{let e={source:"@libp2p/devtools-metrics:node",type:"peers",peers:[]},t=this.connectionManager.getConnectionsMap();for(let[n,s]of t.entries())try{let a=await this.peerStore.get(n);e.peers.push({peerId:n.toString(),addresses:s.map(c=>c.remoteAddr.toString()),multiaddrs:a.addresses.map(({isCertified:c,multiaddr:u})=>({isCertified:c,multiaddr:u.toString()})),protocols:[...a.protocols],tags:me(a.tags,c=>c.value),metadata:me(a.metadata,c=>_.encode(c))})}catch(a){this.log.error("could not load peer data from peer store",a),e.peers.push({peerId:n.toString(),addresses:s.map(c=>c.remoteAddr.toString()),multiaddrs:[],protocols:[],tags:{},metadata:{}})}window.postMessage(e,"*")}).catch(e=>{this.log.error("error sending peers message",e)})}sendSelfUpdate(e){let t={source:"@libp2p/devtools-metrics:node",type:"self",peerId:e.detail.peer.id.toString(),multiaddrs:e.detail.peer.addresses.map(({multiaddr:n})=>n.toString()),protocols:[...e.detail.peer.protocols]};this.log("post node update message"),window.postMessage(t,"*")}processIncomingMessage(e){if(e.source!==window)return;let t=e.data;if(t?.source==="@libp2p/devtools-metrics:devtools"){if(t.type==="identify"){let n={source:"@libp2p/devtools-metrics:node",type:"self",peerId:this.peerId.toString(),multiaddrs:this.transportManager.getListeners().flatMap(s=>s.getAddrs()).map(s=>s.toString()),protocols:this.registrar.getProtocols()};window.postMessage(n,"*"),this.sendPeers()}t.type==="debug"&&(t.namespace.length>0?de(t.namespace):ue())}}};function Ze(r){return e=>new X(e,r)}function me(r,e){let t={};for(let[n,s]of r.entries())t[n]=e(s);return t}function Ke(r,e=100){let t,n;return()=>{if(n==null&&(n=Date.now()),t!=null&&Date.now()-n>e){clearTimeout(t),n=void 0,r();return}clearTimeout(t),t=setTimeout(()=>{n=void 0,r()},e)}}return Fe(Qe);})();
|
|
3
|
+
return Libp2PDevtoolsMetrics}));
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Configure your browser-based libp2p node with DevTools metrics:
|
|
5
|
+
*
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { createLibp2p } from 'libp2p'
|
|
8
|
+
* import { devtoolsMetrics } from '@libp2p/devtools-metrics'
|
|
9
|
+
*
|
|
10
|
+
* const node = await createLibp2p({
|
|
11
|
+
* metrics: devToolsMetrics()
|
|
12
|
+
* })
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Then use the [DevTools plugin](https://github.com/ipfs-shipyard/js-libp2p-devtools)
|
|
16
|
+
* for Chrome or Firefox to inspect the state of your running node.
|
|
17
|
+
*/
|
|
18
|
+
import type { ComponentLogger, Libp2pEvents, Metrics, PeerId, PeerStore, TypedEventEmitter } from '@libp2p/interface';
|
|
19
|
+
import type { TransportManager, Registrar, ConnectionManager } from '@libp2p/interface-internal';
|
|
20
|
+
export declare const SOURCE_DEVTOOLS = "@libp2p/devtools-metrics:devtools";
|
|
21
|
+
export declare const SOURCE_APPLICATION = "@libp2p/devtools-metrics:node";
|
|
22
|
+
/**
|
|
23
|
+
* Sent when new metrics are available
|
|
24
|
+
*/
|
|
25
|
+
export interface MetricsMessage {
|
|
26
|
+
source: '@libp2p/devtools-metrics:node';
|
|
27
|
+
type: 'metrics';
|
|
28
|
+
metrics: Record<string, any>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* This message represents the current state of the libp2p node
|
|
32
|
+
*/
|
|
33
|
+
export interface SelfMessage {
|
|
34
|
+
source: '@libp2p/devtools-metrics:node';
|
|
35
|
+
type: 'self';
|
|
36
|
+
peerId: string;
|
|
37
|
+
multiaddrs: string[];
|
|
38
|
+
protocols: string[];
|
|
39
|
+
}
|
|
40
|
+
export interface Peer {
|
|
41
|
+
/**
|
|
42
|
+
* The identifier of the remote peer
|
|
43
|
+
*/
|
|
44
|
+
peerId: string;
|
|
45
|
+
/**
|
|
46
|
+
* The addresses we are connected to the peer via
|
|
47
|
+
*/
|
|
48
|
+
addresses: string[];
|
|
49
|
+
/**
|
|
50
|
+
* The complete list of addresses the peer has, if known
|
|
51
|
+
*/
|
|
52
|
+
multiaddrs: Array<{
|
|
53
|
+
isCertified?: boolean;
|
|
54
|
+
multiaddr: string;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Any peer store tags the peer has
|
|
58
|
+
*/
|
|
59
|
+
tags: Record<string, number>;
|
|
60
|
+
/**
|
|
61
|
+
* Any peer store tags the peer has
|
|
62
|
+
*/
|
|
63
|
+
metadata: Record<string, string>;
|
|
64
|
+
/**
|
|
65
|
+
* The protocols the peer supports, if known
|
|
66
|
+
*/
|
|
67
|
+
protocols: string[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* This message represents the current state of the libp2p node
|
|
71
|
+
*/
|
|
72
|
+
export interface PeersMessage {
|
|
73
|
+
source: '@libp2p/devtools-metrics:node';
|
|
74
|
+
type: 'peers';
|
|
75
|
+
peers: Peer[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* This message is sent by DevTools when no `self` message has been received
|
|
79
|
+
*/
|
|
80
|
+
export interface IdentifyMessage {
|
|
81
|
+
source: '@libp2p/devtools-metrics:devtools';
|
|
82
|
+
type: 'identify';
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* This message is sent by DevTools when no `self` message has been received
|
|
86
|
+
*/
|
|
87
|
+
export interface EnableDebugMessage {
|
|
88
|
+
source: '@libp2p/devtools-metrics:devtools';
|
|
89
|
+
type: 'debug';
|
|
90
|
+
namespace: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Messages that are sent from the application page to the DevTools panel
|
|
94
|
+
*/
|
|
95
|
+
export type BrowserMessage = MetricsMessage | SelfMessage | PeersMessage;
|
|
96
|
+
/**
|
|
97
|
+
* Messages that are sent from the DevTools panel page to the application page
|
|
98
|
+
*/
|
|
99
|
+
export type DevToolsMessage = IdentifyMessage | EnableDebugMessage;
|
|
100
|
+
export interface DevToolsMetricsInit {
|
|
101
|
+
/**
|
|
102
|
+
* How often to pass metrics to the DevTools panel
|
|
103
|
+
*/
|
|
104
|
+
intervalMs?: number;
|
|
105
|
+
}
|
|
106
|
+
export interface DevToolsMetricsComponents {
|
|
107
|
+
logger: ComponentLogger;
|
|
108
|
+
events: TypedEventEmitter<Libp2pEvents>;
|
|
109
|
+
peerId: PeerId;
|
|
110
|
+
transportManager: TransportManager;
|
|
111
|
+
registrar: Registrar;
|
|
112
|
+
connectionManager: ConnectionManager;
|
|
113
|
+
peerStore: PeerStore;
|
|
114
|
+
}
|
|
115
|
+
export declare function devToolsMetrics(init?: Partial<DevToolsMetricsInit>): (components: DevToolsMetricsComponents) => Metrics;
|
|
116
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAc,YAAY,EAAU,OAAO,EAAuB,MAAM,EAAE,SAAS,EAAsB,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAClL,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAEhG,eAAO,MAAM,eAAe,sCAAsC,CAAA;AAClE,eAAO,MAAM,kBAAkB,kCAAkC,CAAA;AAEjE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,+BAA+B,CAAA;IACvC,IAAI,EAAE,SAAS,CAAA;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,+BAA+B,CAAA;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,MAAM,WAAW,IAAI;IACnB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,SAAS,EAAE,MAAM,EAAE,CAAA;IAEnB;;OAEG;IACH,UAAU,EAAE,KAAK,CAAC;QAAE,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAE/D;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE5B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC;;OAEG;IACH,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,+BAA+B,CAAA;IACvC,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,IAAI,EAAE,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,mCAAmC,CAAA;IAC3C,IAAI,EAAE,UAAU,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,mCAAmC,CAAA;IAC3C,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,WAAW,GAAG,YAAY,CAAA;AAExE;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG,kBAAkB,CAAA;AAElE,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,eAAe,CAAA;IACvB,MAAM,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAA;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,SAAS,EAAE,SAAS,CAAA;IACpB,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,SAAS,EAAE,SAAS,CAAA;CACrB;AA8LD,wBAAgB,eAAe,CAAE,IAAI,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,UAAU,EAAE,yBAAyB,KAAK,OAAO,CAIxH"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Configure your browser-based libp2p node with DevTools metrics:
|
|
5
|
+
*
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { createLibp2p } from 'libp2p'
|
|
8
|
+
* import { devtoolsMetrics } from '@libp2p/devtools-metrics'
|
|
9
|
+
*
|
|
10
|
+
* const node = await createLibp2p({
|
|
11
|
+
* metrics: devToolsMetrics()
|
|
12
|
+
* })
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Then use the [DevTools plugin](https://github.com/ipfs-shipyard/js-libp2p-devtools)
|
|
16
|
+
* for Chrome or Firefox to inspect the state of your running node.
|
|
17
|
+
*/
|
|
18
|
+
import { start, stop } from '@libp2p/interface';
|
|
19
|
+
import { enable, disable } from '@libp2p/logger';
|
|
20
|
+
import { simpleMetrics } from '@libp2p/simple-metrics';
|
|
21
|
+
import { base64 } from 'multiformats/bases/base64';
|
|
22
|
+
export const SOURCE_DEVTOOLS = '@libp2p/devtools-metrics:devtools';
|
|
23
|
+
export const SOURCE_APPLICATION = '@libp2p/devtools-metrics:node';
|
|
24
|
+
class DevToolsMetrics {
|
|
25
|
+
log;
|
|
26
|
+
events;
|
|
27
|
+
peerId;
|
|
28
|
+
transportManager;
|
|
29
|
+
registrar;
|
|
30
|
+
connectionManager;
|
|
31
|
+
peerStore;
|
|
32
|
+
simpleMetrics;
|
|
33
|
+
intervalMs;
|
|
34
|
+
constructor(components, init) {
|
|
35
|
+
this.log = components.logger.forComponent('libp2p:devtools-metrics');
|
|
36
|
+
this.events = components.events;
|
|
37
|
+
this.peerId = components.peerId;
|
|
38
|
+
this.transportManager = components.transportManager;
|
|
39
|
+
this.registrar = components.registrar;
|
|
40
|
+
this.connectionManager = components.connectionManager;
|
|
41
|
+
this.peerStore = components.peerStore;
|
|
42
|
+
this.intervalMs = init?.intervalMs;
|
|
43
|
+
// collect information on current peers and sent it to the dev tools panel
|
|
44
|
+
this.sendPeers = debounce(this.sendPeers.bind(this), 1000);
|
|
45
|
+
this.sendSelfUpdate = this.sendSelfUpdate.bind(this);
|
|
46
|
+
this.processIncomingMessage = this.processIncomingMessage.bind(this);
|
|
47
|
+
}
|
|
48
|
+
trackMultiaddrConnection(maConn) {
|
|
49
|
+
this.simpleMetrics?.trackMultiaddrConnection(maConn);
|
|
50
|
+
}
|
|
51
|
+
trackProtocolStream(stream, connection) {
|
|
52
|
+
this.simpleMetrics?.trackProtocolStream(stream, connection);
|
|
53
|
+
}
|
|
54
|
+
registerMetric(name, options) {
|
|
55
|
+
return this.simpleMetrics?.registerMetric(name, options);
|
|
56
|
+
}
|
|
57
|
+
registerMetricGroup(name, options) {
|
|
58
|
+
return this.simpleMetrics?.registerMetricGroup(name, options);
|
|
59
|
+
}
|
|
60
|
+
registerCounter(name, options) {
|
|
61
|
+
return this.simpleMetrics?.registerCounter(name, options);
|
|
62
|
+
}
|
|
63
|
+
registerCounterGroup(name, options) {
|
|
64
|
+
return this.simpleMetrics?.registerCounterGroup(name, options);
|
|
65
|
+
}
|
|
66
|
+
async start() {
|
|
67
|
+
// send peer updates
|
|
68
|
+
this.events.addEventListener('peer:connect', this.sendPeers);
|
|
69
|
+
this.events.addEventListener('peer:disconnect', this.sendPeers);
|
|
70
|
+
this.events.addEventListener('peer:identify', this.sendPeers);
|
|
71
|
+
this.events.addEventListener('peer:update', this.sendPeers);
|
|
72
|
+
// send node status updates
|
|
73
|
+
this.events.addEventListener('self:peer:update', this.sendSelfUpdate);
|
|
74
|
+
// process incoming messages from devtools
|
|
75
|
+
window.addEventListener('message', this.processIncomingMessage);
|
|
76
|
+
// send metrics
|
|
77
|
+
this.simpleMetrics = simpleMetrics({
|
|
78
|
+
intervalMs: this.intervalMs,
|
|
79
|
+
onMetrics: (metrics) => {
|
|
80
|
+
const message = {
|
|
81
|
+
source: '@libp2p/devtools-metrics:node',
|
|
82
|
+
type: 'metrics',
|
|
83
|
+
metrics
|
|
84
|
+
};
|
|
85
|
+
this.log('post metrics message');
|
|
86
|
+
window.postMessage(message, '*');
|
|
87
|
+
}
|
|
88
|
+
})({});
|
|
89
|
+
await start(this.simpleMetrics);
|
|
90
|
+
}
|
|
91
|
+
async stop() {
|
|
92
|
+
window.removeEventListener('message', this.processIncomingMessage);
|
|
93
|
+
this.events.removeEventListener('self:peer:update', this.sendSelfUpdate);
|
|
94
|
+
this.events.removeEventListener('peer:connect', this.sendPeers);
|
|
95
|
+
this.events.removeEventListener('peer:disconnect', this.sendPeers);
|
|
96
|
+
this.events.removeEventListener('peer:identify', this.sendPeers);
|
|
97
|
+
this.events.removeEventListener('peer:update', this.sendPeers);
|
|
98
|
+
await stop(this.simpleMetrics);
|
|
99
|
+
}
|
|
100
|
+
sendPeers() {
|
|
101
|
+
Promise.resolve().then(async () => {
|
|
102
|
+
const message = {
|
|
103
|
+
source: '@libp2p/devtools-metrics:node',
|
|
104
|
+
type: 'peers',
|
|
105
|
+
peers: []
|
|
106
|
+
};
|
|
107
|
+
const connections = this.connectionManager.getConnectionsMap();
|
|
108
|
+
for (const [peerId, conns] of connections.entries()) {
|
|
109
|
+
try {
|
|
110
|
+
const peer = await this.peerStore.get(peerId);
|
|
111
|
+
message.peers.push({
|
|
112
|
+
peerId: peerId.toString(),
|
|
113
|
+
addresses: conns.map(conn => conn.remoteAddr.toString()),
|
|
114
|
+
multiaddrs: peer.addresses.map(({ isCertified, multiaddr }) => ({ isCertified, multiaddr: multiaddr.toString() })),
|
|
115
|
+
protocols: [...peer.protocols],
|
|
116
|
+
tags: toObject(peer.tags, (t) => t.value),
|
|
117
|
+
metadata: toObject(peer.metadata, (buf) => base64.encode(buf))
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
this.log.error('could not load peer data from peer store', err);
|
|
122
|
+
message.peers.push({
|
|
123
|
+
peerId: peerId.toString(),
|
|
124
|
+
addresses: conns.map(conn => conn.remoteAddr.toString()),
|
|
125
|
+
multiaddrs: [],
|
|
126
|
+
protocols: [],
|
|
127
|
+
tags: {},
|
|
128
|
+
metadata: {}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
window.postMessage(message, '*');
|
|
133
|
+
})
|
|
134
|
+
.catch(err => {
|
|
135
|
+
this.log.error('error sending peers message', err);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
sendSelfUpdate(evt) {
|
|
139
|
+
const message = {
|
|
140
|
+
source: '@libp2p/devtools-metrics:node',
|
|
141
|
+
type: 'self',
|
|
142
|
+
peerId: evt.detail.peer.id.toString(),
|
|
143
|
+
multiaddrs: evt.detail.peer.addresses.map(({ multiaddr }) => multiaddr.toString()),
|
|
144
|
+
protocols: [...evt.detail.peer.protocols]
|
|
145
|
+
};
|
|
146
|
+
this.log('post node update message');
|
|
147
|
+
window.postMessage(message, '*');
|
|
148
|
+
}
|
|
149
|
+
processIncomingMessage(event) {
|
|
150
|
+
// Only accept messages from same frame
|
|
151
|
+
if (event.source !== window) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const message = event.data;
|
|
155
|
+
// Only accept messages of correct format (our messages)
|
|
156
|
+
if (message?.source !== '@libp2p/devtools-metrics:devtools') {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// respond to identify request
|
|
160
|
+
if (message.type === 'identify') {
|
|
161
|
+
const message = {
|
|
162
|
+
source: '@libp2p/devtools-metrics:node',
|
|
163
|
+
type: 'self',
|
|
164
|
+
peerId: this.peerId.toString(),
|
|
165
|
+
multiaddrs: this.transportManager.getListeners().flatMap(listener => listener.getAddrs()).map(ma => ma.toString()),
|
|
166
|
+
protocols: this.registrar.getProtocols()
|
|
167
|
+
};
|
|
168
|
+
window.postMessage(message, '*');
|
|
169
|
+
// also send our current peer list
|
|
170
|
+
this.sendPeers();
|
|
171
|
+
}
|
|
172
|
+
// handle enabling/disabling debug namespaces
|
|
173
|
+
if (message.type === 'debug') {
|
|
174
|
+
if (message.namespace.length > 0) {
|
|
175
|
+
enable(message.namespace);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
disable();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
export function devToolsMetrics(init) {
|
|
184
|
+
return (components) => {
|
|
185
|
+
return new DevToolsMetrics(components, init);
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function toObject(map, transform) {
|
|
189
|
+
const output = {};
|
|
190
|
+
for (const [key, value] of map.entries()) {
|
|
191
|
+
output[key] = transform(value);
|
|
192
|
+
}
|
|
193
|
+
return output;
|
|
194
|
+
}
|
|
195
|
+
function debounce(callback, wait = 100) {
|
|
196
|
+
let timeout;
|
|
197
|
+
let start;
|
|
198
|
+
return () => {
|
|
199
|
+
if (start == null) {
|
|
200
|
+
start = Date.now();
|
|
201
|
+
}
|
|
202
|
+
if (timeout != null && Date.now() - start > wait) {
|
|
203
|
+
clearTimeout(timeout);
|
|
204
|
+
start = undefined;
|
|
205
|
+
callback();
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
clearTimeout(timeout);
|
|
209
|
+
timeout = setTimeout(() => {
|
|
210
|
+
start = undefined;
|
|
211
|
+
callback();
|
|
212
|
+
}, wait);
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"DevToolsMetricsComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.DevToolsMetricsComponents.html",
|
|
3
|
+
".:DevToolsMetricsComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.DevToolsMetricsComponents.html",
|
|
4
|
+
"DevToolsMetricsInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.DevToolsMetricsInit.html",
|
|
5
|
+
".:DevToolsMetricsInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.DevToolsMetricsInit.html",
|
|
6
|
+
"EnableDebugMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.EnableDebugMessage.html",
|
|
7
|
+
".:EnableDebugMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.EnableDebugMessage.html",
|
|
8
|
+
"IdentifyMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.IdentifyMessage.html",
|
|
9
|
+
".:IdentifyMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.IdentifyMessage.html",
|
|
10
|
+
"MetricsMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.MetricsMessage.html",
|
|
11
|
+
".:MetricsMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.MetricsMessage.html",
|
|
12
|
+
"Peer": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.Peer.html",
|
|
13
|
+
".:Peer": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.Peer.html",
|
|
14
|
+
"PeersMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.PeersMessage.html",
|
|
15
|
+
".:PeersMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.PeersMessage.html",
|
|
16
|
+
"SelfMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.SelfMessage.html",
|
|
17
|
+
".:SelfMessage": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_devtools_metrics.SelfMessage.html",
|
|
18
|
+
"BrowserMessage": "https://libp2p.github.io/js-libp2p/types/_libp2p_devtools_metrics.BrowserMessage.html",
|
|
19
|
+
".:BrowserMessage": "https://libp2p.github.io/js-libp2p/types/_libp2p_devtools_metrics.BrowserMessage.html",
|
|
20
|
+
"DevToolsMessage": "https://libp2p.github.io/js-libp2p/types/_libp2p_devtools_metrics.DevToolsMessage.html",
|
|
21
|
+
".:DevToolsMessage": "https://libp2p.github.io/js-libp2p/types/_libp2p_devtools_metrics.DevToolsMessage.html",
|
|
22
|
+
"SOURCE_APPLICATION": "https://libp2p.github.io/js-libp2p/variables/_libp2p_devtools_metrics.SOURCE_APPLICATION.html",
|
|
23
|
+
".:SOURCE_APPLICATION": "https://libp2p.github.io/js-libp2p/variables/_libp2p_devtools_metrics.SOURCE_APPLICATION.html",
|
|
24
|
+
"SOURCE_DEVTOOLS": "https://libp2p.github.io/js-libp2p/variables/_libp2p_devtools_metrics.SOURCE_DEVTOOLS.html",
|
|
25
|
+
".:SOURCE_DEVTOOLS": "https://libp2p.github.io/js-libp2p/variables/_libp2p_devtools_metrics.SOURCE_DEVTOOLS.html",
|
|
26
|
+
"devToolsMetrics": "https://libp2p.github.io/js-libp2p/functions/_libp2p_devtools_metrics.devToolsMetrics.html",
|
|
27
|
+
".:devToolsMetrics": "https://libp2p.github.io/js-libp2p/functions/_libp2p_devtools_metrics.devToolsMetrics.html"
|
|
28
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@libp2p/devtools-metrics",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Collect libp2p metrics and send them to browser DevTools",
|
|
5
|
+
"author": "",
|
|
6
|
+
"license": "Apache-2.0 OR MIT",
|
|
7
|
+
"homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/metrics-devtools#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/libp2p/js-libp2p.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/libp2p/js-libp2p/issues"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"types": "./dist/src/index.d.ts",
|
|
20
|
+
"files": [
|
|
21
|
+
"src",
|
|
22
|
+
"dist",
|
|
23
|
+
"!dist/test",
|
|
24
|
+
"!**/*.tsbuildinfo"
|
|
25
|
+
],
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/src/index.d.ts",
|
|
29
|
+
"import": "./dist/src/index.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"eslintConfig": {
|
|
33
|
+
"extends": "ipfs",
|
|
34
|
+
"parserOptions": {
|
|
35
|
+
"project": true,
|
|
36
|
+
"sourceType": "module"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"clean": "aegir clean",
|
|
41
|
+
"lint": "aegir lint",
|
|
42
|
+
"dep-check": "aegir dep-check",
|
|
43
|
+
"doc-check": "aegir doc-check",
|
|
44
|
+
"build": "aegir build",
|
|
45
|
+
"test": "aegir test -t browser",
|
|
46
|
+
"test:chrome": "aegir test -t browser --cov"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@libp2p/interface": "^1.3.1",
|
|
50
|
+
"@libp2p/interface-internal": "^1.2.1",
|
|
51
|
+
"@libp2p/logger": "^4.0.12",
|
|
52
|
+
"@libp2p/simple-metrics": "^1.0.1",
|
|
53
|
+
"multiformats": "^13.1.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@libp2p/peer-id-factory": "^4.1.1",
|
|
57
|
+
"aegir": "^42.2.5",
|
|
58
|
+
"race-event": "^1.3.0",
|
|
59
|
+
"sinon-ts": "^2.0.0"
|
|
60
|
+
},
|
|
61
|
+
"sideEffects": false
|
|
62
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Configure your browser-based libp2p node with DevTools metrics:
|
|
5
|
+
*
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { createLibp2p } from 'libp2p'
|
|
8
|
+
* import { devtoolsMetrics } from '@libp2p/devtools-metrics'
|
|
9
|
+
*
|
|
10
|
+
* const node = await createLibp2p({
|
|
11
|
+
* metrics: devToolsMetrics()
|
|
12
|
+
* })
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Then use the [DevTools plugin](https://github.com/ipfs-shipyard/js-libp2p-devtools)
|
|
16
|
+
* for Chrome or Firefox to inspect the state of your running node.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { start, stop } from '@libp2p/interface'
|
|
20
|
+
import { enable, disable } from '@libp2p/logger'
|
|
21
|
+
import { simpleMetrics } from '@libp2p/simple-metrics'
|
|
22
|
+
import { base64 } from 'multiformats/bases/base64'
|
|
23
|
+
import type { ComponentLogger, Connection, Libp2pEvents, Logger, Metrics, MultiaddrConnection, PeerId, PeerStore, PeerUpdate, Stream, TypedEventEmitter } from '@libp2p/interface'
|
|
24
|
+
import type { TransportManager, Registrar, ConnectionManager } from '@libp2p/interface-internal'
|
|
25
|
+
|
|
26
|
+
export const SOURCE_DEVTOOLS = '@libp2p/devtools-metrics:devtools'
|
|
27
|
+
export const SOURCE_APPLICATION = '@libp2p/devtools-metrics:node'
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Sent when new metrics are available
|
|
31
|
+
*/
|
|
32
|
+
export interface MetricsMessage {
|
|
33
|
+
source: '@libp2p/devtools-metrics:node'
|
|
34
|
+
type: 'metrics'
|
|
35
|
+
metrics: Record<string, any>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* This message represents the current state of the libp2p node
|
|
40
|
+
*/
|
|
41
|
+
export interface SelfMessage {
|
|
42
|
+
source: '@libp2p/devtools-metrics:node'
|
|
43
|
+
type: 'self'
|
|
44
|
+
peerId: string
|
|
45
|
+
multiaddrs: string[]
|
|
46
|
+
protocols: string[]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface Peer {
|
|
50
|
+
/**
|
|
51
|
+
* The identifier of the remote peer
|
|
52
|
+
*/
|
|
53
|
+
peerId: string
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The addresses we are connected to the peer via
|
|
57
|
+
*/
|
|
58
|
+
addresses: string[]
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The complete list of addresses the peer has, if known
|
|
62
|
+
*/
|
|
63
|
+
multiaddrs: Array<{ isCertified?: boolean, multiaddr: string }>
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Any peer store tags the peer has
|
|
67
|
+
*/
|
|
68
|
+
tags: Record<string, number>
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Any peer store tags the peer has
|
|
72
|
+
*/
|
|
73
|
+
metadata: Record<string, string>
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The protocols the peer supports, if known
|
|
77
|
+
*/
|
|
78
|
+
protocols: string[]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* This message represents the current state of the libp2p node
|
|
83
|
+
*/
|
|
84
|
+
export interface PeersMessage {
|
|
85
|
+
source: '@libp2p/devtools-metrics:node'
|
|
86
|
+
type: 'peers'
|
|
87
|
+
peers: Peer[]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* This message is sent by DevTools when no `self` message has been received
|
|
92
|
+
*/
|
|
93
|
+
export interface IdentifyMessage {
|
|
94
|
+
source: '@libp2p/devtools-metrics:devtools'
|
|
95
|
+
type: 'identify'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* This message is sent by DevTools when no `self` message has been received
|
|
100
|
+
*/
|
|
101
|
+
export interface EnableDebugMessage {
|
|
102
|
+
source: '@libp2p/devtools-metrics:devtools'
|
|
103
|
+
type: 'debug'
|
|
104
|
+
namespace: string
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Messages that are sent from the application page to the DevTools panel
|
|
109
|
+
*/
|
|
110
|
+
export type BrowserMessage = MetricsMessage | SelfMessage | PeersMessage
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Messages that are sent from the DevTools panel page to the application page
|
|
114
|
+
*/
|
|
115
|
+
export type DevToolsMessage = IdentifyMessage | EnableDebugMessage
|
|
116
|
+
|
|
117
|
+
export interface DevToolsMetricsInit {
|
|
118
|
+
/**
|
|
119
|
+
* How often to pass metrics to the DevTools panel
|
|
120
|
+
*/
|
|
121
|
+
intervalMs?: number
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface DevToolsMetricsComponents {
|
|
125
|
+
logger: ComponentLogger
|
|
126
|
+
events: TypedEventEmitter<Libp2pEvents>
|
|
127
|
+
peerId: PeerId
|
|
128
|
+
transportManager: TransportManager
|
|
129
|
+
registrar: Registrar
|
|
130
|
+
connectionManager: ConnectionManager
|
|
131
|
+
peerStore: PeerStore
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
class DevToolsMetrics implements Metrics {
|
|
135
|
+
private readonly log: Logger
|
|
136
|
+
private readonly events: TypedEventEmitter<Libp2pEvents>
|
|
137
|
+
private readonly peerId: PeerId
|
|
138
|
+
private readonly transportManager: TransportManager
|
|
139
|
+
private readonly registrar: Registrar
|
|
140
|
+
private readonly connectionManager: ConnectionManager
|
|
141
|
+
private readonly peerStore: PeerStore
|
|
142
|
+
private simpleMetrics?: Metrics
|
|
143
|
+
private readonly intervalMs?: number
|
|
144
|
+
|
|
145
|
+
constructor (components: DevToolsMetricsComponents, init?: Partial<DevToolsMetricsInit>) {
|
|
146
|
+
this.log = components.logger.forComponent('libp2p:devtools-metrics')
|
|
147
|
+
this.events = components.events
|
|
148
|
+
this.peerId = components.peerId
|
|
149
|
+
this.transportManager = components.transportManager
|
|
150
|
+
this.registrar = components.registrar
|
|
151
|
+
this.connectionManager = components.connectionManager
|
|
152
|
+
this.peerStore = components.peerStore
|
|
153
|
+
this.intervalMs = init?.intervalMs
|
|
154
|
+
|
|
155
|
+
// collect information on current peers and sent it to the dev tools panel
|
|
156
|
+
this.sendPeers = debounce(this.sendPeers.bind(this), 1000)
|
|
157
|
+
|
|
158
|
+
this.sendSelfUpdate = this.sendSelfUpdate.bind(this)
|
|
159
|
+
this.processIncomingMessage = this.processIncomingMessage.bind(this)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
trackMultiaddrConnection (maConn: MultiaddrConnection): void {
|
|
163
|
+
this.simpleMetrics?.trackMultiaddrConnection(maConn)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
trackProtocolStream (stream: Stream, connection: Connection): void {
|
|
167
|
+
this.simpleMetrics?.trackProtocolStream(stream, connection)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
registerMetric (name: any, options: any): any {
|
|
171
|
+
return this.simpleMetrics?.registerMetric(name, options)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
registerMetricGroup (name: any, options: any): any {
|
|
175
|
+
return this.simpleMetrics?.registerMetricGroup(name, options)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
registerCounter (name: any, options: any): any {
|
|
179
|
+
return this.simpleMetrics?.registerCounter(name, options)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
registerCounterGroup (name: any, options: any): any {
|
|
183
|
+
return this.simpleMetrics?.registerCounterGroup(name, options)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async start (): Promise<void> {
|
|
187
|
+
// send peer updates
|
|
188
|
+
this.events.addEventListener('peer:connect', this.sendPeers)
|
|
189
|
+
this.events.addEventListener('peer:disconnect', this.sendPeers)
|
|
190
|
+
this.events.addEventListener('peer:identify', this.sendPeers)
|
|
191
|
+
this.events.addEventListener('peer:update', this.sendPeers)
|
|
192
|
+
|
|
193
|
+
// send node status updates
|
|
194
|
+
this.events.addEventListener('self:peer:update', this.sendSelfUpdate)
|
|
195
|
+
|
|
196
|
+
// process incoming messages from devtools
|
|
197
|
+
window.addEventListener('message', this.processIncomingMessage)
|
|
198
|
+
|
|
199
|
+
// send metrics
|
|
200
|
+
this.simpleMetrics = simpleMetrics({
|
|
201
|
+
intervalMs: this.intervalMs,
|
|
202
|
+
onMetrics: (metrics) => {
|
|
203
|
+
const message: MetricsMessage = {
|
|
204
|
+
source: '@libp2p/devtools-metrics:node',
|
|
205
|
+
type: 'metrics',
|
|
206
|
+
metrics
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
this.log('post metrics message')
|
|
210
|
+
window.postMessage(message, '*')
|
|
211
|
+
}
|
|
212
|
+
})({})
|
|
213
|
+
await start(this.simpleMetrics)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async stop (): Promise<void> {
|
|
217
|
+
window.removeEventListener('message', this.processIncomingMessage)
|
|
218
|
+
this.events.removeEventListener('self:peer:update', this.sendSelfUpdate)
|
|
219
|
+
this.events.removeEventListener('peer:connect', this.sendPeers)
|
|
220
|
+
this.events.removeEventListener('peer:disconnect', this.sendPeers)
|
|
221
|
+
this.events.removeEventListener('peer:identify', this.sendPeers)
|
|
222
|
+
this.events.removeEventListener('peer:update', this.sendPeers)
|
|
223
|
+
await stop(this.simpleMetrics)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private sendPeers (): void {
|
|
227
|
+
Promise.resolve().then(async () => {
|
|
228
|
+
const message: PeersMessage = {
|
|
229
|
+
source: '@libp2p/devtools-metrics:node',
|
|
230
|
+
type: 'peers',
|
|
231
|
+
peers: []
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const connections = this.connectionManager.getConnectionsMap()
|
|
235
|
+
|
|
236
|
+
for (const [peerId, conns] of connections.entries()) {
|
|
237
|
+
try {
|
|
238
|
+
const peer = await this.peerStore.get(peerId)
|
|
239
|
+
|
|
240
|
+
message.peers.push({
|
|
241
|
+
peerId: peerId.toString(),
|
|
242
|
+
addresses: conns.map(conn => conn.remoteAddr.toString()),
|
|
243
|
+
multiaddrs: peer.addresses.map(({ isCertified, multiaddr }) => ({ isCertified, multiaddr: multiaddr.toString() })),
|
|
244
|
+
protocols: [...peer.protocols],
|
|
245
|
+
tags: toObject(peer.tags, (t) => t.value),
|
|
246
|
+
metadata: toObject(peer.metadata, (buf) => base64.encode(buf))
|
|
247
|
+
})
|
|
248
|
+
} catch (err) {
|
|
249
|
+
this.log.error('could not load peer data from peer store', err)
|
|
250
|
+
|
|
251
|
+
message.peers.push({
|
|
252
|
+
peerId: peerId.toString(),
|
|
253
|
+
addresses: conns.map(conn => conn.remoteAddr.toString()),
|
|
254
|
+
multiaddrs: [],
|
|
255
|
+
protocols: [],
|
|
256
|
+
tags: {},
|
|
257
|
+
metadata: {}
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
window.postMessage(message, '*')
|
|
263
|
+
})
|
|
264
|
+
.catch(err => {
|
|
265
|
+
this.log.error('error sending peers message', err)
|
|
266
|
+
})
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private sendSelfUpdate (evt: CustomEvent<PeerUpdate>): void {
|
|
270
|
+
const message: SelfMessage = {
|
|
271
|
+
source: '@libp2p/devtools-metrics:node',
|
|
272
|
+
type: 'self',
|
|
273
|
+
peerId: evt.detail.peer.id.toString(),
|
|
274
|
+
multiaddrs: evt.detail.peer.addresses.map(({ multiaddr }) => multiaddr.toString()),
|
|
275
|
+
protocols: [...evt.detail.peer.protocols]
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
this.log('post node update message')
|
|
279
|
+
window.postMessage(message, '*')
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private processIncomingMessage (event: MessageEvent<DevToolsMessage>): void {
|
|
283
|
+
// Only accept messages from same frame
|
|
284
|
+
if (event.source !== window) {
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const message = event.data
|
|
289
|
+
|
|
290
|
+
// Only accept messages of correct format (our messages)
|
|
291
|
+
if (message?.source !== '@libp2p/devtools-metrics:devtools') {
|
|
292
|
+
return
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// respond to identify request
|
|
296
|
+
if (message.type === 'identify') {
|
|
297
|
+
const message: SelfMessage = {
|
|
298
|
+
source: '@libp2p/devtools-metrics:node',
|
|
299
|
+
type: 'self',
|
|
300
|
+
peerId: this.peerId.toString(),
|
|
301
|
+
multiaddrs: this.transportManager.getListeners().flatMap(listener => listener.getAddrs()).map(ma => ma.toString()),
|
|
302
|
+
protocols: this.registrar.getProtocols()
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
window.postMessage(message, '*')
|
|
306
|
+
|
|
307
|
+
// also send our current peer list
|
|
308
|
+
this.sendPeers()
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// handle enabling/disabling debug namespaces
|
|
312
|
+
if (message.type === 'debug') {
|
|
313
|
+
if (message.namespace.length > 0) {
|
|
314
|
+
enable(message.namespace)
|
|
315
|
+
} else {
|
|
316
|
+
disable()
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function devToolsMetrics (init?: Partial<DevToolsMetricsInit>): (components: DevToolsMetricsComponents) => Metrics {
|
|
323
|
+
return (components) => {
|
|
324
|
+
return new DevToolsMetrics(components, init)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function toObject <T, R> (map: Map<string, T>, transform: (value: T) => R): Record<string, R> {
|
|
329
|
+
const output: Record<string, any> = {}
|
|
330
|
+
|
|
331
|
+
for (const [key, value] of map.entries()) {
|
|
332
|
+
output[key] = transform(value)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return output
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function debounce (callback: () => void, wait: number = 100): () => void {
|
|
339
|
+
let timeout: ReturnType<typeof setTimeout>
|
|
340
|
+
let start: number | undefined
|
|
341
|
+
|
|
342
|
+
return (): void => {
|
|
343
|
+
if (start == null) {
|
|
344
|
+
start = Date.now()
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (timeout != null && Date.now() - start > wait) {
|
|
348
|
+
clearTimeout(timeout)
|
|
349
|
+
start = undefined
|
|
350
|
+
callback()
|
|
351
|
+
return
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
clearTimeout(timeout)
|
|
355
|
+
timeout = setTimeout(() => {
|
|
356
|
+
start = undefined
|
|
357
|
+
callback()
|
|
358
|
+
}, wait)
|
|
359
|
+
}
|
|
360
|
+
}
|