105 lines
2.3 KiB
Go
105 lines
2.3 KiB
Go
package frpLogger
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func (s *InstanceLogStreamer) streamLogFile(logFilePath string) {
|
|
s.streamLogFileSince(logFilePath, time.Time{})
|
|
}
|
|
|
|
func (s *InstanceLogStreamer) streamLogFileSince(logFilePath string, sinceTime time.Time) {
|
|
s.sendInfo(fmt.Sprintf("Streaming log file: %s", logFilePath))
|
|
|
|
if _, err := os.Stat(logFilePath); os.IsNotExist(err) {
|
|
s.sendError(fmt.Sprintf("Log file not found: %s", logFilePath))
|
|
return
|
|
}
|
|
|
|
file, err := os.Open(logFilePath)
|
|
if err != nil {
|
|
s.sendError(fmt.Sprintf("Failed to open log file: %v", err))
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
if !sinceTime.IsZero() {
|
|
s.sendInfo(fmt.Sprintf("Filtering logs since: %s", sinceTime.Format("2006-01-02 15:04:05")))
|
|
}
|
|
s.streamLogFileFromBeginning(file, sinceTime)
|
|
}
|
|
|
|
func (s *InstanceLogStreamer) streamLogFileFromBeginning(file *os.File, sinceTime time.Time) {
|
|
reader := bufio.NewReader(file)
|
|
|
|
for {
|
|
select {
|
|
case <-s.stopChan:
|
|
s.sendInfo("Log streaming stopped")
|
|
return
|
|
default:
|
|
line, err := reader.ReadString('\n')
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
s.sendError(fmt.Sprintf("Error reading log file: %v", err))
|
|
return
|
|
}
|
|
|
|
line = strings.TrimSpace(line)
|
|
if line != "" {
|
|
lineTime := s.parseLogLineTime(line)
|
|
if lineTime.IsZero() || lineTime.After(sinceTime) || lineTime.Equal(sinceTime) {
|
|
s.sendLog(s.parseLogLevel(line), line)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *InstanceLogStreamer) parseLogLineTime(line string) time.Time {
|
|
layouts := []string{
|
|
"2006/01/02 15:04:05",
|
|
"2006-01-02 15:04:05",
|
|
"2006-01-02T15:04:05",
|
|
time.RFC3339,
|
|
time.RFC3339Nano,
|
|
}
|
|
|
|
for _, layout := range layouts {
|
|
minLen := len(layout)
|
|
if len(line) >= minLen {
|
|
t, err := time.Parse(layout, strings.TrimSpace(line[:minLen]))
|
|
if err == nil {
|
|
return t
|
|
}
|
|
}
|
|
}
|
|
|
|
return time.Time{}
|
|
}
|
|
|
|
func (s *InstanceLogStreamer) parseLogLevel(line string) string {
|
|
lowerLine := strings.ToLower(line)
|
|
if strings.Contains(lowerLine, "error") || strings.Contains(lowerLine, "err") {
|
|
return "ERROR"
|
|
}
|
|
if strings.Contains(lowerLine, "warn") || strings.Contains(lowerLine, "warning") {
|
|
return "WARN"
|
|
}
|
|
if strings.Contains(lowerLine, "debug") {
|
|
return "DEBUG"
|
|
}
|
|
if strings.Contains(lowerLine, "info") {
|
|
return "INFO"
|
|
}
|
|
return "INFO"
|
|
}
|