CodexLogLine.cs
1 using System.Globalization; 2 3 namespace CodexClient 4 { 5 public class CodexLogLine 6 { 7 public static CodexLogLine? Parse(string line) 8 { 9 try 10 { 11 if (string.IsNullOrEmpty(line) || 12 line.Length < 34 || 13 line[3] != ' ' || 14 line[33] != ' ') return null; 15 16 line = line.Replace(Environment.NewLine, string.Empty); 17 18 var level = line.Substring(0, 3); 19 var dtLine = line.Substring(4, 23); 20 21 var firstEqualSign = line.IndexOf('='); 22 var msgStart = 34; 23 var msgEnd = line.Substring(0, firstEqualSign).LastIndexOf(' '); 24 var msg = line.Substring(msgStart, msgEnd - msgStart).Trim(); 25 var attrsLine = line.Substring(msgEnd); 26 27 var attrs = SplitAttrs(attrsLine); 28 29 var format = "yyyy-MM-dd HH:mm:ss.fff"; 30 var dt = DateTime.ParseExact(dtLine, format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToUniversalTime(); 31 32 return new CodexLogLine() 33 { 34 LogLevel = level, 35 TimestampUtc = dt, 36 Message = msg, 37 Attributes = attrs 38 }; 39 } 40 catch 41 { 42 return null; 43 } 44 } 45 46 public string LogLevel { get; set; } = string.Empty; 47 public DateTime TimestampUtc { get; set; } 48 public string Message { get; set; } = string.Empty; 49 public Dictionary<string, string> Attributes { get; private set; } = new Dictionary<string, string>(); 50 51 /// <summary> 52 /// After too much time spent cursing at regexes, here's what I got: 53 /// Parses input string into 'key=value' pair, considerate of quoted (") values. 54 /// </summary> 55 private static Dictionary<string, string> SplitAttrs(string input) 56 { 57 input += " "; 58 var result = new Dictionary<string, string>(); 59 60 var key = string.Empty; 61 var value = string.Empty; 62 var mode = 1; 63 var inQuote = false; 64 65 foreach (var c in input) 66 { 67 if (mode == 1) 68 { 69 if (c == '=') mode = 2; 70 else if (c == ' ') 71 { 72 if (string.IsNullOrEmpty(key)) continue; 73 else 74 { 75 result.Add(key, string.Empty); 76 key = string.Empty; 77 value = string.Empty; 78 } 79 } 80 else key += c; 81 } 82 else if (mode == 2) 83 { 84 if (c == ' ' && !inQuote) 85 { 86 result.Add(key, value); 87 key = string.Empty; 88 value = string.Empty; 89 mode = 1; 90 } 91 else if (c == '\"') 92 { 93 inQuote = !inQuote; 94 } 95 else 96 { 97 value += c; 98 } 99 } 100 } 101 102 return result; 103 } 104 } 105 }