import {performance} from 'node:perf_hooks'; import type {Bot} from '@wp2508/mineflayer'; import {metadata, ResourceInfo} from '../resource_metrics.ts'; export interface NetworkInfo { available: boolean; received_bytes: number; sent_bytes: number; received_bytes_per_second: number | null; sent_bytes_per_second: number | null; interval_ms: number; } /** Totals include the first observed counters of every new socket. Unobserved old-socket tails are unknowable. */ export class NetworkCounter { private socket: object | undefined; private read = 0; private written = 0; private time: number | undefined; private received = 0; private sent = 0; sample(socket: {bytesRead?: number; bytesWritten?: number} | undefined, now: number): NetworkInfo { const read = socket?.bytesRead; const written = socket?.bytesWritten; const available = typeof read === 'number' && Number.isFinite(read) && read >= 0 && typeof written === 'number' && Number.isFinite(written) && written >= 0; const elapsed = this.time === undefined ? 0 : now - this.time; const continuous = available && socket === this.socket && this.time !== undefined && read >= this.read && written >= this.written && elapsed > 0; const dr = available ? (socket === this.socket && read >= this.read ? read - this.read : read) : 0; const dw = available ? (socket === this.socket && written >= this.written ? written - this.written : written) : 0; this.received += dr; this.sent += dw; if (available) { this.socket = socket; this.read = read; this.written = written; } this.time = available ? now : undefined; return {available, received_bytes: this.received, sent_bytes: this.sent, received_bytes_per_second: continuous ? dr * 1000 / elapsed : null, sent_bytes_per_second: continuous ? dw * 1000 / elapsed : null, interval_ms: continuous ? elapsed : 0}; } } export class init extends ResourceInfo { readonly name = 'used_network'; readonly i18n = metadata('机器人网络流量', '读取传输层套接字的字节计数,包含协议开销;' + '更换套接字后保留累计观察量,不包含旧套接字被替换前未观察到的尾部流量。', { available: ['计数是否可用', '套接字是否同时提供有效的接收和发送字节计数'], received_bytes: ['累计接收量', '累计观察到的接收流量,单位为字节'], sent_bytes: ['累计发送量', '累计观察到的发送流量,单位为字节'], received_bytes_per_second: ['接收速率', '接收流量速率,单位为字节每秒;缺少连续采样基线时为 null'], sent_bytes_per_second: ['发送速率', '发送流量速率,单位为字节每秒;缺少连续采样基线时为 null'], interval_ms: ['速率采样间隔', '通过单调时钟测得的实际速率采样间隔,单位为毫秒;缺少连续采样基线时为 0'], }); constructor(bot: Bot) { const counter = new NetworkCounter(); super(counter.sample(bot._client?.socket, performance.now())); this.start(1000, () => { this.publish(counter.sample(bot._client?.socket, performance.now())); }); } }