1515using System ;
1616using System . Globalization ;
1717using System . IO ;
18+ using System . Text . RegularExpressions ;
1819using System . Threading . Tasks ;
1920using Newtonsoft . Json ;
2021using Newtonsoft . Json . Linq ;
2930
3031namespace SeqCli . Apps . Hosting ;
3132
32- class AppContainer : IAppHost , IDisposable
33+ partial class AppContainer : IAppHost , IDisposable
3334{
3435 readonly SeqApp _seqApp ;
3536 readonly AppLoader _loader ;
3637
38+ static readonly Regex HexDigits = HexDigitsRegex ( ) ;
39+
3740 readonly JsonSerializer _serializer = JsonSerializer . Create ( new JsonSerializerSettings
3841 {
3942 DateParseHandling = DateParseHandling . None ,
@@ -143,6 +146,8 @@ LogEvent ReadSerilogEvent(string clef, out string eventId, out uint eventType)
143146 jobject . Add ( "@l" , new JValue ( LevelMapping . ToSerilogLevel ( levelToken . Value < string > ( ) ! ) . ToString ( ) ) ) ;
144147 }
145148
149+ SanitizeTraceIdentifiers ( jobject ) ;
150+
146151 var raw = LogEventReader . ReadFromJObject ( jobject ) ;
147152
148153 eventId = "event-0" ;
@@ -158,6 +163,29 @@ LogEvent ReadSerilogEvent(string clef, out string eventId, out uint eventType)
158163 return raw ;
159164 }
160165
166+ internal static void SanitizeTraceIdentifiers ( JObject jobject )
167+ {
168+ // Serilog.Formatting.Compact.Reader constructs LogEvents which use the System.Diagnostics ActivityTraceId
169+ // and ActivitySpanId types; these throw when constructed with invalid inputs.
170+
171+ if ( jobject . TryGetValue ( "@tr" , out var traceIdToken ) && ! IsValidHexIdentifier ( traceIdToken , 32 ) )
172+ jobject . Remove ( "@tr" ) ;
173+
174+ if ( jobject . TryGetValue ( "@sp" , out var spanIdToken ) && ! IsValidHexIdentifier ( spanIdToken , 16 ) )
175+ jobject . Remove ( "@sp" ) ;
176+
177+ if ( jobject . TryGetValue ( "@ps" , out var parentSpanIdToken ) && ! IsValidHexIdentifier ( parentSpanIdToken , 16 ) )
178+ jobject . Remove ( "@ps" ) ;
179+ }
180+
181+ static bool IsValidHexIdentifier ( JToken ? value , int requiredChars )
182+ {
183+ if ( value ? . Value < string > ( ) is not { } id )
184+ return false ;
185+
186+ return id . Length == requiredChars && HexDigits . IsMatch ( id ) ;
187+ }
188+
161189 public void StartPublishing ( TextWriter inputWriter )
162190 {
163191 if ( _seqApp is IPublishJson pjson )
@@ -169,4 +197,8 @@ public void StopPublishing()
169197 if ( _seqApp is IPublishJson pjson )
170198 pjson . Stop ( ) ;
171199 }
200+
201+ // Technically,
202+ [ GeneratedRegex ( "^[0-9a-f]*$" ) ]
203+ private static partial Regex HexDigitsRegex ( ) ;
172204}
0 commit comments