package main
import (
"bufio"
"context"
"fmt"
"os"
"strings"
"time"
)
type Severity string
const (
SeverityInfo Severity = "INFO"
SeverityWarning Severity = "WARNING"
SeverityCritical Severity = "CRITICAL"
SeverityUnknown Severity = "UNKNOWN"
)
type Classifier interface {
Classify(ctx context.Context, line string) (Severity, error)
}
// Mock classifier.
// Replace this with a real LLM-backed implementation later.
type mockLLMClassifier struct{}
func (mockLLMClassifier) Classify(ctx context.Context, line string) (Severity, error) {
select {
case <-ctx.Done():
return SeverityUnknown, ctx.Err()
default:
}
lower := strings.ToLower(line)
switch {
case strings.Contains(lower, "panic"),
strings.Contains(lower, "fatal"),
strings.Contains(lower, "critical"),
strings.Contains(lower, "out of memory"):
return SeverityCritical, nil
case strings.Contains(lower, "warn"),
strings.Contains(lower, "deprecated"),
strings.Contains(lower, "retry"):
return SeverityWarning, nil
default:
return SeverityInfo, nil
}
}
func colorize(sev Severity) string {
switch sev {
case SeverityInfo:
return "\033[32mINFO\033[0m" // green
case SeverityWarning:
return "\033[33mWARNING\033[0m" // yellow
case SeverityCritical:
return "\033[31mCRITICAL\033[0m" // red
default:
return "\033[37mUNKNOWN\033[0m" // white
}
}
func main() {
var clf Classifier = mockLLMClassifier{}
counts := map[Severity]int{
SeverityInfo: 0,
SeverityWarning: 0,
SeverityCritical: 0,
SeverityUnknown: 0,
}
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" {
continue
}
ctx, cancel := context.WithTimeout(
context.Background(),
5*time.Second,
)
sev, err := clf.Classify(ctx, line)
cancel()
if err != nil {
fmt.Fprintf(os.Stderr, "classify error: %v\n", err)
sev = SeverityUnknown
}
counts[sev]++
fmt.Printf("%-18s | %s\n", colorize(sev), line)
}
if err := scanner.Err(); err != nil {
fmt.Fprintf(os.Stderr, "read error: %v\n", err)
os.Exit(2)
}
fmt.Printf(
"\nsummary: info=%d warning=%d critical=%d unknown=%d\n",
counts[SeverityInfo],
counts[SeverityWarning],
counts[SeverityCritical],
counts[SeverityUnknown],
)
// Fail CI/CD if any critical log was seen.
if counts[SeverityCritical] > 0 {
os.Exit(1)
}
}