@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 ADDED
@@ -0,0 +1,4 @@
1
+ This project is dual licensed under MIT and Apache-2.0.
2
+
3
+ MIT: https://www.opensource.org/licenses/mit
4
+ Apache-2.0: https://www.apache.org/licenses/license-2.0
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # @libp2p/devtools-metrics
2
+
3
+ [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/)
4
+ [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io)
5
+ [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p)
6
+ [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p/main.yml?branch=main\&style=flat-square)](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
+ }