Fix log parser to match lol library format (v0.38.1)
Some checks failed
Go / build-and-release (push) Has been cancelled
Some checks failed
Go / build-and-release (push) Has been cancelled
The lol library outputs logs in format: 1703500000000000ℹ️ message /path/to/file.go:123 Where: - Timestamp is Unix microseconds - Level is emoji (☠️🚨⚠️ℹ️🔎👻) - Message text - File:line location Updated parser to correctly parse this format. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,12 +17,15 @@ type BufferedWriter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Log format regex patterns
|
// Log format regex patterns
|
||||||
// lol library format: "2024/01/15 10:30:45 file.go:123 [INF] message"
|
// lol library format: "1703500000000000ℹ️ message /path/to/file.go:123"
|
||||||
// or similar variations
|
// - Unix microseconds timestamp
|
||||||
var logPattern = regexp.MustCompile(`^(\d{4}/\d{2}/\d{2}\s+\d{2}:\d{2}:\d{2}(?:\.\d+)?)\s+([^\s:]+):(\d+)\s+\[([A-Z]{3})\]\s+(.*)$`)
|
// - Level emoji (☠️, 🚨, ⚠️, ℹ️, 🔎, 👻)
|
||||||
|
// - Message
|
||||||
|
// - File:line location
|
||||||
|
var lolPattern = regexp.MustCompile(`^(\d{16})([☠️🚨⚠️ℹ️🔎👻]+)\s*(.*?)\s+([^\s]+:\d+)$`)
|
||||||
|
|
||||||
// Simple format: "[level] message"
|
// Simpler pattern for when emoji detection fails - just capture timestamp and rest
|
||||||
var simplePattern = regexp.MustCompile(`^\[([A-Z]{3})\]\s+(.*)$`)
|
var simplePattern = regexp.MustCompile(`^(\d{13,16})\s*(.*)$`)
|
||||||
|
|
||||||
// NewBufferedWriter creates a new BufferedWriter
|
// NewBufferedWriter creates a new BufferedWriter
|
||||||
func NewBufferedWriter(original io.Writer, buffer *Buffer) *BufferedWriter {
|
func NewBufferedWriter(original io.Writer, buffer *Buffer) *BufferedWriter {
|
||||||
@@ -64,6 +67,16 @@ func (w *BufferedWriter) Write(p []byte) (n int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emojiToLevel maps lol library level emojis to level strings
|
||||||
|
var emojiToLevel = map[string]string{
|
||||||
|
"☠️": "FTL",
|
||||||
|
"🚨": "ERR",
|
||||||
|
"⚠️": "WRN",
|
||||||
|
"ℹ️": "INF",
|
||||||
|
"🔎": "DBG",
|
||||||
|
"👻": "TRC",
|
||||||
|
}
|
||||||
|
|
||||||
// parseLine parses a log line into a LogEntry
|
// parseLine parses a log line into a LogEntry
|
||||||
func (w *BufferedWriter) parseLine(line string) LogEntry {
|
func (w *BufferedWriter) parseLine(line string) LogEntry {
|
||||||
entry := LogEntry{
|
entry := LogEntry{
|
||||||
@@ -72,47 +85,64 @@ func (w *BufferedWriter) parseLine(line string) LogEntry {
|
|||||||
Level: "INF",
|
Level: "INF",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try full pattern first
|
line = strings.TrimSpace(line)
|
||||||
if matches := logPattern.FindStringSubmatch(line); matches != nil {
|
if line == "" {
|
||||||
// Parse timestamp
|
return entry
|
||||||
if t, err := time.Parse("2006/01/02 15:04:05", matches[1]); err == nil {
|
|
||||||
entry.Timestamp = t
|
|
||||||
} else if t, err := time.Parse("2006/01/02 15:04:05.000", matches[1]); err == nil {
|
|
||||||
entry.Timestamp = t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.File = matches[2]
|
// Try lol pattern first: "1703500000000000ℹ️ message /path/to/file.go:123"
|
||||||
if lineNum, err := strconv.Atoi(matches[3]); err == nil {
|
if matches := lolPattern.FindStringSubmatch(line); matches != nil {
|
||||||
|
// Parse Unix microseconds timestamp
|
||||||
|
if usec, err := strconv.ParseInt(matches[1], 10, 64); err == nil {
|
||||||
|
entry.Timestamp = time.UnixMicro(usec)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map emoji to level
|
||||||
|
if level, ok := emojiToLevel[matches[2]]; ok {
|
||||||
|
entry.Level = level
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.Message = strings.TrimSpace(matches[3])
|
||||||
|
|
||||||
|
// Parse file:line
|
||||||
|
loc := matches[4]
|
||||||
|
if idx := strings.LastIndex(loc, ":"); idx > 0 {
|
||||||
|
entry.File = loc[:idx]
|
||||||
|
if lineNum, err := strconv.Atoi(loc[idx+1:]); err == nil {
|
||||||
entry.Line = lineNum
|
entry.Line = lineNum
|
||||||
}
|
}
|
||||||
entry.Level = matches[4]
|
}
|
||||||
entry.Message = matches[5]
|
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try simple pattern
|
// Try simple pattern - just grab timestamp and rest as message
|
||||||
if matches := simplePattern.FindStringSubmatch(line); matches != nil {
|
if matches := simplePattern.FindStringSubmatch(line); matches != nil {
|
||||||
entry.Level = matches[1]
|
if usec, err := strconv.ParseInt(matches[1], 10, 64); err == nil {
|
||||||
entry.Message = matches[2]
|
// Could be microseconds or milliseconds
|
||||||
|
if len(matches[1]) >= 16 {
|
||||||
|
entry.Timestamp = time.UnixMicro(usec)
|
||||||
|
} else {
|
||||||
|
entry.Timestamp = time.UnixMilli(usec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rest := strings.TrimSpace(matches[2])
|
||||||
|
|
||||||
|
// Try to detect level from emoji in the rest
|
||||||
|
for emoji, level := range emojiToLevel {
|
||||||
|
if strings.HasPrefix(rest, emoji) {
|
||||||
|
entry.Level = level
|
||||||
|
rest = strings.TrimPrefix(rest, emoji)
|
||||||
|
rest = strings.TrimSpace(rest)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.Message = rest
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect level from common prefixes
|
// Fallback: just store the whole line as message
|
||||||
line = strings.TrimSpace(line)
|
entry.Message = line
|
||||||
if strings.HasPrefix(line, "TRC") || strings.HasPrefix(line, "[TRC]") {
|
|
||||||
entry.Level = "TRC"
|
|
||||||
} else if strings.HasPrefix(line, "DBG") || strings.HasPrefix(line, "[DBG]") {
|
|
||||||
entry.Level = "DBG"
|
|
||||||
} else if strings.HasPrefix(line, "INF") || strings.HasPrefix(line, "[INF]") {
|
|
||||||
entry.Level = "INF"
|
|
||||||
} else if strings.HasPrefix(line, "WRN") || strings.HasPrefix(line, "[WRN]") {
|
|
||||||
entry.Level = "WRN"
|
|
||||||
} else if strings.HasPrefix(line, "ERR") || strings.HasPrefix(line, "[ERR]") {
|
|
||||||
entry.Level = "ERR"
|
|
||||||
} else if strings.HasPrefix(line, "FTL") || strings.HasPrefix(line, "[FTL]") {
|
|
||||||
entry.Level = "FTL"
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v0.38.0
|
v0.38.1
|
||||||
|
|||||||
Reference in New Issue
Block a user