package logweb import ( "regexp" "strings" ) var ( logLineRE = regexp.MustCompile(`^\[(app|pull|push)\]\s+(\d{4}/\d{2}/\d{2}\s+\d{2}:\d{2}:\d{2})\s+(.*)$`) sepRE = regexp.MustCompile(`^=+\s*.+\s*=+$`) ) // LogLine 解析后的日志行。 type LogLine struct { LineNo int `json:"lineNo"` Tag string `json:"tag,omitempty"` Time string `json:"time,omitempty"` Message string `json:"message"` Level string `json:"level"` IsSeparator bool `json:"isSeparator"` Raw string `json:"raw"` } // ParseLogLines 解析原始行。 func ParseLogLines(raw []string) []LogLine { out := make([]LogLine, 0, len(raw)) for i, line := range raw { l := LogLine{LineNo: i + 1, Raw: line, Level: "info"} if sepRE.MatchString(line) { l.IsSeparator = true l.Level = "sep" l.Message = line out = append(out, l) continue } if m := logLineRE.FindStringSubmatch(line); len(m) == 4 { l.Tag = m[1] l.Time = m[2] l.Message = m[3] l.Level = classifyLevel(l.Message) } else { l.Message = line l.Level = classifyLevel(line) } out = append(out, l) } return out } func classifyLevel(msg string) string { low := strings.ToLower(msg) switch { case strings.Contains(low, "fail") || strings.Contains(low, "err") || strings.Contains(low, "error"): return "error" case strings.Contains(low, "warning") || strings.Contains(low, "warn"): return "warn" case strings.Contains(low, " ok ") || strings.HasPrefix(low, "ok ") || strings.Contains(low, "ok=true"): return "ok" default: return "info" } }