Files
OmniSocketGo/cmd/internal/transport/tx_timestamp_debug.go

98 lines
3.2 KiB
Go

package transport
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"sync"
"omnisocketgo/cmd/internal/protocol"
)
const (
txTimestampDebugRecordTypeSendChunk = "send_chunk"
txTimestampDebugRecordTypeErrqueueEvent = "errqueue_event"
)
// TXTimestampDebugRecord 是 TX errqueue 调试日志的一条 JSONL 记录。
type TXTimestampDebugRecord struct {
RecordType string `json:"record_type"`
NodeRole string `json:"node_role,omitempty"`
NodeID string `json:"node_id,omitempty"`
MessageType protocol.MessageType `json:"message_type"`
MessageID uint64 `json:"message_id"`
From string `json:"from"`
To string `json:"to"`
FileName string `json:"file_name,omitempty"`
BodySize int `json:"body_size"`
Phase string `json:"phase,omitempty"`
SendCallIndex *int `json:"send_call_index,omitempty"`
FrameOffsetStart *int `json:"frame_offset_start,omitempty"`
FrameOffsetEnd *int `json:"frame_offset_end,omitempty"`
BytesWritten *int `json:"bytes_written,omitempty"`
ExpectedTXID *uint32 `json:"expected_tx_id,omitempty"`
ReadIndex *int `json:"read_index,omitempty"`
EventName string `json:"event_name,omitempty"`
TSUnixNano *int64 `json:"ts_unix_nano,omitempty"`
EEInfo *uint32 `json:"ee_info,omitempty"`
EEData *uint32 `json:"ee_data,omitempty"`
MatchedSendCallIndex *int `json:"matched_send_call_index,omitempty"`
SelectedForLatency *bool `json:"selected_for_latency,omitempty"`
}
// TXTimestampDebugLogger 接收 TX errqueue 调试记录。
type TXTimestampDebugLogger interface {
LogTXTimestampDebugRecord(record TXTimestampDebugRecord) error
}
// JSONLTXTimestampDebugLogger 以 JSONL 形式追加写 TX errqueue 调试日志。
type JSONLTXTimestampDebugLogger struct {
mu sync.Mutex
closeOnce sync.Once
closeErr error
file *os.File
}
// NewJSONLTXTimestampDebugLogger 创建一个线程安全的 TX errqueue JSONL 日志器。
func NewJSONLTXTimestampDebugLogger(path string) (*JSONLTXTimestampDebugLogger, error) {
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, fmt.Errorf("transport: create tx timestamp 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 tx timestamp debug log %s: %w", path, err)
}
return &JSONLTXTimestampDebugLogger{file: file}, nil
}
// LogTXTimestampDebugRecord 以单行 JSON 的形式追加一条调试记录。
func (l *JSONLTXTimestampDebugLogger) LogTXTimestampDebugRecord(record TXTimestampDebugRecord) 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 *JSONLTXTimestampDebugLogger) Close() error {
l.closeOnce.Do(func() {
l.closeErr = l.file.Close()
})
return l.closeErr
}