UNPKG

hyperdht-stats

Version:
451 lines (402 loc) 14.6 kB
class HyperDhtStats { constructor (dht) { this.dht = dht } get isFirewalled () { return this.dht.firewalled } get punches () { return this.dht.stats.punches } get queries () { return this.dht.stats.queries } get pingCmds () { return this.dht.stats.commands.ping } get pingNatCmds () { return this.dht.stats.commands.pingNat } get downHintCmds () { return this.dht.stats.commands.downHint } get findNodeCmds () { return this.dht.stats.commands.findNode } get clientSocketBytesTransmitted () { return this.dht.io.clientSocket?.bytesTransmitted || 0 } get clientSocketPacketsTransmitted () { return this.dht.io.clientSocket?.packetsTransmitted || 0 } get clientSocketBytesReceived () { return this.dht.io.clientSocket?.bytesReceived || 0 } get clientSocketPacketsReceived () { return this.dht.io.clientSocket?.packetsReceived || 0 } get serverSocketBytesTransmitted () { return this.dht.io.serverSocket?.bytesTransmitted || 0 } get serverSocketPacketsTransmitted () { return this.dht.io.serverSocket?.packetsTransmitted || 0 } get serverSocketBytesReceived () { return this.dht.io.serverSocket?.bytesReceived || 0 } get serverSocketPacketsReceived () { return this.dht.io.serverSocket?.packetsReceived || 0 } get udxBytesTransmitted () { return this.dht.udx.bytesTransmitted } get udxPacketsTransmitted () { return this.dht.udx.packetsTransmitted } get udxBytesReceived () { return this.dht.udx.bytesReceived } get udxPacketsReceived () { return this.dht.udx.packetsReceived } get udxPacketsDropped () { if (this.dht.udx.packetsDroppedByKernel == null) return null if (this.dht.udx.packetsDroppedByKernel >= 2 ** 64) return 0 // not yet initialised (2**64 value normally) return this.dht.udx.packetsDroppedByKernel } get nrNodes () { return this.dht.nodes.length } getRemoteAddress () { const address = this.dht.firewalled ? { host: this.dht.host, port: this.dht.port } : this.dht.remoteAddress() if (!address?.port) return null return `${address.host}:${address.port}` } getLocalAddress () { const address = this.dht.localAddress() if (!address) return null return `${address.host}:${address.port}` } // Linear I.F.O. nodes length (could be constant by // listening to dht-rpc's node-added and node-removed events // and managing the state here) get nrUniqueNodeIPs () { const ips = new Set() for (const node of this.dht.nodes.toArray()) { ips.add(node.host) } return ips.size } get nrRecords () { // TODO: use a public API return this.dht._persistent?.records.size || null } // TODO: nrMutables, nrImmutables toJson () { return { isFirewalled: this.isFirewalled, localAddress: this.getLocalAddress(), remoteAddress: this.getRemoteAddress(), clientSocketBytesTransmitted: this.clientSocketBytesTransmitted, clientSocketPacketsTransmitted: this.clientSocketPacketsTransmitted, clientSocketBytesReceived: this.clientSocketBytesReceived, clientSocketPacketsReceived: this.clientSocketPacketsReceived, serverSocketBytesTransmitted: this.serverSocketBytesTransmitted, serverSocketPacketsTransmitted: this.serverSocketPacketsTransmitted, serverSocketBytesReceived: this.serverSocketBytesReceived, serverSocketPacketsReceived: this.serverSocketPacketsReceived, nrNodes: this.nrNodes, nrUniqueNodeIPs: this.nrUniqueNodeIPs, nrRecords: this.nrRecords || 0, punches: { ...this.punches }, queries: { ...this.queries }, pingCmds: { ...this.pingCmds }, pingNatCmds: { ...this.pingNatCmds }, findNodeCmds: { ...this.findNodeCmds }, downHintCmds: { ...this.downHintCmds }, udxBytesTransmitted: this.udxBytesTransmitted, udxPacketsTransmitted: this.udxPacketsTransmitted, udxBytesReceived: this.udxBytesReceived, udxPacketsReceived: this.udxPacketsReceived, udxPacketsDropped: this.udxPacketsDropped } } toString () { // Note: we do not include our remote address in the toString // because then sharing these stats could leak the IP return `DHT Stats - dht_remote_address: ${this.getRemoteAddress()} - dht_local_address: ${this.getLocalAddress()} - dht_is_firewalled: ${this.isFirewalled} - dht_client_socket_bytes_transmitted: ${this.clientSocketBytesTransmitted} - dht_client_socket_packets_transmitted: ${this.clientSocketPacketsTransmitted} - dht_client_socket_bytes_received: ${this.clientSocketBytesReceived} - dht_client_socket_packets_received: ${this.clientSocketPacketsReceived} - dht_server_socket_bytes_transmitted: ${this.serverSocketBytesTransmitted} - dht_server_socket_packets_transmitted: ${this.serverSocketPacketsTransmitted} - dht_server_socket_bytes_received: ${this.serverSocketBytesReceived} - dht_server_socket_packets_received: ${this.serverSocketPacketsReceived} - dht_nr_nodes: ${this.nrNodes} - dht_nr_unique_node_ips: ${this.nrUniqueNodeIPs} - dht_nr_records: ${this.nrRecords || 0} - dht_consistent_punches: ${this.punches.consistent} - dht_random_punches: ${this.punches.random} - dht_open_punches: ${this.punches.open} - dht_active_queries: ${this.queries.active} - dht_total_queries: ${this.queries.total} - dht_ping_received: ${this.pingCmds.rx} - dht_ping_transmitted: ${this.pingCmds.tx} - dht_ping_nat_received: ${this.pingNatCmds.rx} - dht_ping_nat_transmitted: ${this.pingNatCmds.tx} - dht_find_node_received: ${this.findNodeCmds.rx} - dht_find_node_transmitted: ${this.findNodeCmds.tx} - dht_down_hint_received: ${this.downHintCmds.rx} - dht_down_hint_transmitted: ${this.downHintCmds.tx} UDX Stats - udx_total_bytes_transmitted: ${this.udxBytesTransmitted} - udx_total_packets_transmitted: ${this.udxPacketsTransmitted} - udx_total_bytes_received: ${this.udxBytesReceived} - udx_total_packets_received: ${this.udxPacketsReceived} - udx_packets_dropped_total: ${this.udxPacketsDropped}` } registerPrometheusMetrics (promClient) { const self = this new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_consistent_punches', help: 'Total number of consistent holepunches performed by the hyperdht instance', collect () { this.set(self.punches.consistent) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_random_punches', help: 'Total number of random holepunches performed by the hyperdht instance', collect () { this.set(self.punches.random) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_open_punches', help: 'Total number of open holepunches performed by the hyperdht instance', collect () { this.set(self.punches.open) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_active_queries', help: 'Number of currently active queries in the dht-rpc instance', collect () { this.set(self.queries.active) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_total_queries', help: 'Total number of queries in the dht-rpc instance', collect () { this.set(self.queries.total) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_ping_received', help: 'Total number of PING commands received', collect () { this.set(self.pingCmds.rx) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_ping_transmitted', help: 'Total number of PING commands transmitted', collect () { this.set(self.pingCmds.tx) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_ping_nat_received', help: 'Total number of PING_NAT commands received', collect () { this.set(self.pingNatCmds.rx) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_ping_nat_transmitted', help: 'Total number of PING_NAT commands transmitted', collect () { this.set(self.pingNatCmds.tx) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_find_node_received', help: 'Total number of FIND_NODE commands received', collect () { this.set(self.findNodeCmds.rx) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_find_node_transmitted', help: 'Total number of FIND_NODE commands transmitted', collect () { this.set(self.findNodeCmds.tx) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_down_hint_received', help: 'Total number of DOWN_HINT commands received', collect () { this.set(self.downHintCmds.rx) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_down_hint_transmitted', help: 'Total number of DOWN_HINT commands transmitted', collect () { this.set(self.downHintCmds.tx) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'udx_total_bytes_transmitted', help: 'Total bytes transmitted overall (by the UDX instance of the DHT)', collect () { this.set(self.udxBytesTransmitted) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'udx_total_packets_transmitted', help: 'Total packets transmitted overall (by the UDX instance of the DHT)', collect () { this.set(self.udxPacketsTransmitted) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'udx_total_bytes_received', help: 'Total bytes received overall (by the UDX instance of the DHT)', collect () { this.set(self.udxBytesReceived) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'udx_total_packets_received', help: 'Total packets received overall (by the UDX instance of the DHT)', collect () { this.set(self.udxPacketsReceived) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'udx_packets_dropped_total', help: 'Total packets dropped (by the UDX instance of the DHT). Only defined on Linux.', collect () { if (self.udxPacketsDropped !== null) this.set(self.udxPacketsDropped) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_client_socket_bytes_transmitted', help: 'Total bytes transmitted by the client socket of the DHT', collect () { this.set(self.clientSocketBytesTransmitted) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_client_socket_packets_transmitted', help: 'Total packets transmitted by the client socket of the DHT', collect () { this.set(self.clientSocketPacketsTransmitted) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_client_socket_bytes_received', help: 'Total bytes received by the client socket of the DHT', collect () { this.set(self.clientSocketBytesReceived) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_client_socket_packets_received', help: 'Total packets received by the client socket of the DHT', collect () { this.set(self.clientSocketPacketsReceived) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_server_socket_bytes_transmitted', help: 'Total bytes transmitted by the server socket of the DHT', collect () { this.set(self.serverSocketBytesTransmitted) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_server_socket_packets_transmitted', help: 'Total packets transmitted by the server socket of the DHT', collect () { this.set(self.serverSocketPacketsTransmitted) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_server_socket_bytes_received', help: 'Total bytes received by the server socket of the DHT', collect () { this.set(self.serverSocketBytesReceived) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_server_socket_packets_received', help: 'Total packets received by the server socket of the DHT', collect () { this.set(self.serverSocketPacketsReceived) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_nr_nodes', help: 'Total nodes in the Kademlia DHT table of this node', collect () { this.set(self.nrNodes) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_nr_unique_node_ips', help: 'Total unique ip addresses in the Kademlia DHT table of this node', collect () { this.set(self.nrUniqueNodeIPs) } }) new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_is_firewalled', help: 'Whether the DHT server thinks it is behind a firewall (1) or not (0)', collect () { this.set(self.isFirewalled ? 1 : 0) } }) new promClient.Gauge({ // eslint-disable-line no-new // Gauges expect a number, so we set the address as label instead name: 'dht_remote_address', help: 'The remote address of the DHT (set only if not firewalled)', labelNames: ['address'], collect () { const address = self.getRemoteAddress() if (address) this.labels(address).set(1) } }) new promClient.Gauge({ // eslint-disable-line no-new // Gauges expect a number, so we set the address as label instead name: 'dht_local_address', help: 'The local address of the DHT (set only if not firewalled)', labelNames: ['address'], collect () { const address = self.getLocalAddress() if (address) this.labels(address).set(1) } }) // Only if the DHT is persistent (returns 0 values if it was // persistent for a while but now no longer) self.dht.once('persistent', () => { new promClient.Gauge({ // eslint-disable-line no-new name: 'dht_nr_records', help: 'Total nr of records stored by this (persistent) node', collect () { this.set(self.nrRecords || 0) } }) }) } } module.exports = HyperDhtStats