Files
OmniSocketGo/cmd/internal/transport/kcp_packet_debug.go
nnbcccscdscdsc be013b701b feat:KCP协议
2026-03-24 21:09:06 +08:00

77 lines
2.1 KiB
Go

package transport
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"sync"
)
// KCPPacketDebugRecord 是 KCP 底层 UDP packet kernel timestamp 的一条 JSONL 调试记录。
type KCPPacketDebugRecord struct {
Event string `json:"event"`
NodeRole string `json:"node_role,omitempty"`
NodeID string `json:"node_id,omitempty"`
LocalAddr string `json:"local_addr,omitempty"`
RemoteAddr string `json:"remote_addr,omitempty"`
PacketBytes int `json:"packet_bytes"`
UDPTXID *uint32 `json:"udp_tx_id,omitempty"`
KCPConv *uint32 `json:"kcp_conv,omitempty"`
TSUnixNano int64 `json:"ts_unix_nano"`
}
// KCPPacketDebugLogger 接收 KCP packet 级调试记录。
type KCPPacketDebugLogger interface {
LogKCPPacketDebugRecord(record KCPPacketDebugRecord) error
}
// JSONLKCPPacketDebugLogger 以 JSONL 形式追加写 KCP packet 调试日志。
type JSONLKCPPacketDebugLogger struct {
mu sync.Mutex
closeOnce sync.Once
closeErr error
file *os.File
}
// NewJSONLKCPPacketDebugLogger 创建一个线程安全的 KCP packet JSONL 日志器。
func NewJSONLKCPPacketDebugLogger(path string) (*JSONLKCPPacketDebugLogger, error) {
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, fmt.Errorf("transport: create kcp packet debug log dir %s: %w", dir, err)
}
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
if err != nil {
return nil, fmt.Errorf("transport: open kcp packet debug log %s: %w", path, err)
}
return &JSONLKCPPacketDebugLogger{file: file}, nil
}
// LogKCPPacketDebugRecord 以单行 JSON 的形式追加一条 KCP packet 调试记录。
func (l *JSONLKCPPacketDebugLogger) LogKCPPacketDebugRecord(record KCPPacketDebugRecord) error {
line, err := json.Marshal(record)
if err != nil {
return err
}
l.mu.Lock()
defer l.mu.Unlock()
if _, err := l.file.Write(append(line, '\n')); err != nil {
return err
}
return nil
}
// Close 关闭底层文件;重复调用是安全的。
func (l *JSONLKCPPacketDebugLogger) Close() error {
l.closeOnce.Do(func() {
l.closeErr = l.file.Close()
})
return l.closeErr
}