@@ -65,7 +65,7 @@ public static class LogParser
6565 public static LogLevel ParseLogLevel ( string line )
6666 {
6767 if ( string . IsNullOrWhiteSpace ( line ) )
68- return LogLevel . Information ;
68+ return LogLevel . Any ;
6969
7070 // Remove ANSI escape sequences first
7171 var cleanLine = RemoveANSIEscapeRegex . Replace ( line , string . Empty ) ;
@@ -76,51 +76,56 @@ public static LogLevel ParseLogLevel(string line)
7676 return GetLogLevel ( processedLine ) ;
7777 }
7878
79+ // Compiled regex patterns for efficient log level detection
80+ private static readonly Regex ErrorPattern = new ( @"\b(ERROR|ERR|FAIL)\b|ERROR:|FAIL:|\[ERROR\]" ,
81+ RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
82+ private static readonly Regex WarningPattern = new ( @"\b(WARN|WARNING|WRN)\b|WARN:|WARNING:|\[WARN\]|\[WARNING\]" ,
83+ RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
84+ private static readonly Regex InfoPattern = new ( @"\b(INFO|INFORMATION|INF)\b|INFO:|INFORMATION:|\[INFO\]|\[INFORMATION\]" ,
85+ RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
86+ private static readonly Regex DebugPattern = new ( @"\b(DEBUG|DBG|DBUG)\b|DEBUG:|DBUG:|\[DEBUG\]" ,
87+ RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
88+ private static readonly Regex TracePattern = new ( @"\b(TRACE|TRC)\b|TRACE:|\[TRACE\]" ,
89+ RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
90+
7991 private static LogLevel GetLogLevel ( string logLine )
8092 {
8193 if ( string . IsNullOrEmpty ( logLine ) )
82- return LogLevel . Information ;
94+ return LogLevel . Any ;
8395
84- // Check if line is JSON and try to parse level from it
85- if ( logLine . TrimStart ( ) . StartsWith ( '{' ) && logLine . TrimEnd ( ) . EndsWith ( '}' ) )
96+ // Quick check for JSON (avoid trim operations unless needed)
97+ int firstNonWhitespace = 0 ;
98+ while ( firstNonWhitespace < logLine . Length && char . IsWhiteSpace ( logLine [ firstNonWhitespace ] ) )
99+ firstNonWhitespace ++ ;
100+
101+ if ( firstNonWhitespace < logLine . Length && logLine [ firstNonWhitespace ] == '{' )
86102 {
87- var jsonLevel = ParseJsonLogLevel ( logLine ) ;
88- if ( jsonLevel != LogLevel . Information ) // If we found a specific level in JSON
89- return jsonLevel ;
103+ int lastNonWhitespace = logLine . Length - 1 ;
104+ while ( lastNonWhitespace >= 0 && char . IsWhiteSpace ( logLine [ lastNonWhitespace ] ) )
105+ lastNonWhitespace -- ;
106+
107+ if ( lastNonWhitespace >= 0 && logLine [ lastNonWhitespace ] == '}' )
108+ {
109+ var jsonLevel = ParseJsonLogLevel ( logLine ) ;
110+ if ( jsonLevel != LogLevel . Any )
111+ return jsonLevel ;
112+ }
90113 }
91114
92- var upperLine = logLine . ToUpperInvariant ( ) ;
93-
94- // Check for common log level patterns with boundaries
95- if ( ContainsLogLevel ( upperLine , "[ERROR]" , "ERROR:" , " ERR " , "ERROR " , "FAIL:" ) )
96- return LogLevel . Error ;
97- if ( ContainsLogLevel ( upperLine , "[WARN]" , "[WARNING]" , "WARNING:" , " WARN " , " WRN " , "WARN:" ) )
98- return LogLevel . Warning ;
99- if ( ContainsLogLevel ( upperLine , "[INFO]" , "[INFORMATION]" , "INFORMATION:" , " INFO " , " INF " , "INFO:" ) )
115+ // Use compiled regex patterns for efficient matching
116+ // Check in order of frequency (errors and warnings are typically less common)
117+ if ( InfoPattern . IsMatch ( logLine ) )
100118 return LogLevel . Information ;
101- if ( ContainsLogLevel ( upperLine , "[DEBUG]" , "DEBUG:" , " DBG " , "DBUG:" , " DEBUG " ) )
102- return LogLevel . Debug ;
103- if ( ContainsLogLevel ( upperLine , "[TRACE]" , "TRACE:" , " TRC " , " TRACE " ) )
104- return LogLevel . Trace ;
105-
106- // Check for log level at the beginning of the line
107- if ( upperLine . StartsWith ( "ERROR" ) || upperLine . StartsWith ( "ERR" ) )
119+ if ( ErrorPattern . IsMatch ( logLine ) )
108120 return LogLevel . Error ;
109- if ( upperLine . StartsWith ( "WARN" ) || upperLine . StartsWith ( "WARNING" ) )
121+ if ( WarningPattern . IsMatch ( logLine ) )
110122 return LogLevel . Warning ;
111- if ( upperLine . StartsWith ( "INFO" ) || upperLine . StartsWith ( "INFORMATION" ) )
112- return LogLevel . Information ;
113- if ( upperLine . StartsWith ( "DEBUG" ) || upperLine . StartsWith ( "DBG" ) )
123+ if ( DebugPattern . IsMatch ( logLine ) )
114124 return LogLevel . Debug ;
115- if ( upperLine . StartsWith ( "TRACE" ) || upperLine . StartsWith ( "TRC" ) )
125+ if ( TracePattern . IsMatch ( logLine ) )
116126 return LogLevel . Trace ;
117127
118- return LogLevel . Information ; // Default
119- }
120-
121- private static bool ContainsLogLevel ( string upperLine , params string [ ] patterns )
122- {
123- return patterns . Any ( pattern => upperLine . Contains ( pattern ) ) ;
128+ return LogLevel . Any ; // Default when no specific level detected
124129 }
125130
126131 public static string ParseContainerLogFormat ( string originalLine , string cleanLine )
@@ -283,7 +288,7 @@ private static LogLevel ParseJsonLogLevel(string line)
283288 "INFO" or "INFORMATION" => LogLevel . Information ,
284289 "DEBUG" or "DBG" => LogLevel . Debug ,
285290 "TRACE" or "TRC" or "VERBOSE" => LogLevel . Trace ,
286- _ => LogLevel . Information
291+ _ => LogLevel . Any
287292 } ;
288293 }
289294 }
@@ -294,6 +299,6 @@ private static LogLevel ParseJsonLogLevel(string line)
294299 // Not valid JSON or parsing error, ignore
295300 }
296301
297- return LogLevel . Information ;
302+ return LogLevel . Any ;
298303 }
299304}
0 commit comments