diff --git a/pkg/utils/logs.go b/pkg/utils/logs.go new file mode 100644 index 00000000..00271113 --- /dev/null +++ b/pkg/utils/logs.go @@ -0,0 +1,41 @@ +package utils + +import ( + "regexp" + "strings" +) + +var ( + errRegex = regexp.MustCompile(`(?i)\b(error|err|critical|fatal)\b`) + warnRegex = regexp.MustCompile(`(?i)\b(warning|warn)\b`) + infoRegex = regexp.MustCompile(`(?i)\b(info)\b`) + debugRegex = regexp.MustCompile(`(?i)\b(debug)\b`) + + timestampRegex = regexp.MustCompile(`\b\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?\b`) +) + +// ColoriseLog applies basic ANSI syntax highlighting to typical log statements. +func ColoriseLog(line string) string { + if strings.Contains(line, "\x1b[") { + return line + } + + line = timestampRegex.ReplaceAllStringFunc(line, func(ts string) string { + return "\x1b[90m" + ts + "\x1b[0m" + }) + + line = errRegex.ReplaceAllStringFunc(line, func(match string) string { + return "\x1b[31;1m" + match + "\x1b[0m" + }) + line = warnRegex.ReplaceAllStringFunc(line, func(match string) string { + return "\x1b[33;1m" + match + "\x1b[0m" + }) + line = infoRegex.ReplaceAllStringFunc(line, func(match string) string { + return "\x1b[32m" + match + "\x1b[0m" + }) + line = debugRegex.ReplaceAllStringFunc(line, func(match string) string { + return "\x1b[34m" + match + "\x1b[0m" + }) + + return line +} diff --git a/pkg/utils/logs_test.go b/pkg/utils/logs_test.go new file mode 100644 index 00000000..ded6b218 --- /dev/null +++ b/pkg/utils/logs_test.go @@ -0,0 +1,41 @@ +package utils + +import ( + "strings" + "testing" +) + +func TestColoriseLog(t *testing.T) { + tests := []struct { + name string + input string + contains []string + }{ + { + name: "Highlight error log level", + input: "ERROR: database failed to connect", + contains: []string{"\x1b[31;1mERROR\x1b[0m"}, + }, + { + name: "Highlight warning log level", + input: "[WARN] deprecation warning", + contains: []string{"\x1b[33;1mWARN\x1b[0m"}, + }, + { + name: "Highlight timestamp", + input: "2026-06-04T12:00:00Z something happened", + contains: []string{"\x1b[90m2026-06-04T12:00:00Z\x1b[0m"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := ColoriseLog(tt.input) + for _, c := range tt.contains { + if !strings.Contains(got, c) { + t.Errorf("expected %q to contain %q, but it was %q", got, c, got) + } + } + }) + } +}