Files
meshtastic_mqtt_server/internal/mqttforward/client_stats.go
T
kevinandClaude 49a287e6e7 feat: console_log.meshtastic 控制 packet 控制台输出;新增每客户端报文统计
- ConsoleLogConfig 增加 Meshtastic 字段(默认 true);旧配置自动补齐
- meshtasticFilterHook 增加 packetConsoleLog;OnPublish 中根据开关调用
  新的 printMeshtasticRecord 输出可读单行(key=value、按 type 着色),
  替代原来的 JSON dump;事件型 printJSON 调用保持不变
- 新增 internal/mqttforward/ClientStats,按 client_id 累计 in/out 报文计数
- meshtasticFilterHook 多挂 OnPacketRead / OnPacketSent / OnDisconnect
  事件,用于增减计数;Provides() 同步声明
- AdminMQTTClient JSON 视图删除 RemoteHost/RemotePort,新增
  packets_in / packets_out;前端 types.ts、AdminDashboard.vue 同步更新

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-19 17:09:00 +08:00

75 lines
1.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package mqttforward
import "sync"
// ClientStats 在内存中维护每个 MQTT 客户端的收/发包数量。
// key 取自 mqtt.Client.IDbroker 内部唯一标识),客户端断开时由调用方调用 Delete 清除,
// 重新连接同一 client_id 会拿到一份新的零值计数,符合"断链就清空"。
type ClientStats struct {
mu sync.RWMutex
all map[string]*clientCounter
}
type clientCounter struct {
In int64 // 客户端 → 服务器(broker 收到的报文数)
Out int64 // 服务器 → 客户端(broker 发出的报文数)
}
// NewClientStats 返回一个空的统计器。
func NewClientStats() *ClientStats {
return &ClientStats{all: make(map[string]*clientCounter)}
}
// IncIn 在 broker 收到客户端报文时调用。clientID 为空直接忽略。
func (s *ClientStats) IncIn(clientID string) {
if s == nil || clientID == "" {
return
}
s.mu.Lock()
c, ok := s.all[clientID]
if !ok {
c = &clientCounter{}
s.all[clientID] = c
}
c.In++
s.mu.Unlock()
}
// IncOut 在 broker 向客户端发出报文时调用。
func (s *ClientStats) IncOut(clientID string) {
if s == nil || clientID == "" {
return
}
s.mu.Lock()
c, ok := s.all[clientID]
if !ok {
c = &clientCounter{}
s.all[clientID] = c
}
c.Out++
s.mu.Unlock()
}
// Get 返回指定 clientID 当前的收/发包数量;不存在时返回 0,0。
func (s *ClientStats) Get(clientID string) (in, out int64) {
if s == nil || clientID == "" {
return 0, 0
}
s.mu.RLock()
defer s.mu.RUnlock()
if c, ok := s.all[clientID]; ok {
return c.In, c.Out
}
return 0, 0
}
// Delete 在客户端断开连接时清除其计数。重新连接同一 clientID 会从 0 重新计起。
func (s *ClientStats) Delete(clientID string) {
if s == nil || clientID == "" {
return
}
s.mu.Lock()
delete(s.all, clientID)
s.mu.Unlock()
}