package tui import ( "fmt" "sync" "time" ) // LogEntry represents a single log entry with timestamp and level type LogEntry struct { Time time.Time Level string // INFO, CONN, TX, RX, ERR Message string } // LogBuffer is a thread-safe circular buffer for log entries type LogBuffer struct { mu sync.RWMutex entries []LogEntry maxSize int } // NewLogBuffer creates a new LogBuffer with the given max size func NewLogBuffer(maxSize int) *LogBuffer { return &LogBuffer{ entries: make([]LogEntry, 0, maxSize), maxSize: maxSize, } } // Log adds a new log entry func (l *LogBuffer) Log(level, message string) { l.mu.Lock() defer l.mu.Unlock() entry := LogEntry{ Time: time.Now(), Level: level, Message: message, } l.entries = append(l.entries, entry) if len(l.entries) > l.maxSize { l.entries = l.entries[1:] } // No p.Send() - TUI refreshes via tick } // Info logs an INFO level message func (l *LogBuffer) Info(format string, args ...any) { l.Log("INFO", fmt.Sprintf(format, args...)) } // Conn logs a CONN level message func (l *LogBuffer) Conn(format string, args ...any) { l.Log("CONN", fmt.Sprintf(format, args...)) } // TX logs a TX level message func (l *LogBuffer) TX(format string, args ...any) { l.Log("TX", fmt.Sprintf(format, args...)) } // RX logs an RX level message func (l *LogBuffer) RX(format string, args ...any) { l.Log("RX", fmt.Sprintf(format, args...)) } // Err logs an ERR level message func (l *LogBuffer) Err(format string, args ...any) { l.Log("ERR", fmt.Sprintf(format, args...)) } // Warn logs a WARN level message func (l *LogBuffer) Warn(format string, args ...any) { l.Log("WARN", fmt.Sprintf(format, args...)) } // Entries returns a copy of all log entries func (l *LogBuffer) Entries() []LogEntry { l.mu.RLock() defer l.mu.RUnlock() result := make([]LogEntry, len(l.entries)) copy(result, l.entries) return result } // Len returns the number of entries func (l *LogBuffer) Len() int { l.mu.RLock() defer l.mu.RUnlock() return len(l.entries) }