98 lines
3.2 KiB
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
|
|
}
|