Skip to content

Commit 8446d41

Browse files
authored
Merge pull request #452 from nblumhardt/suppress-host-deserialization-errors
Santize trace and span ids to avoid deserialization errors when hosting plug-in apps
2 parents eb13448 + d02abf5 commit 8446d41

2 files changed

Lines changed: 76 additions & 1 deletion

File tree

src/SeqCli/Apps/Hosting/AppContainer.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using System;
1616
using System.Globalization;
1717
using System.IO;
18+
using System.Text.RegularExpressions;
1819
using System.Threading.Tasks;
1920
using Newtonsoft.Json;
2021
using Newtonsoft.Json.Linq;
@@ -29,11 +30,13 @@
2930

3031
namespace 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
}

test/SeqCli.Tests/Apps/AppContainerTests.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.IO;
3+
using Newtonsoft.Json.Linq;
34
using Seq.Apps;
45
using SeqCli.Apps.Hosting;
56
using SeqCli.Tests.Support;
@@ -37,4 +38,46 @@ public void CanLoadInputApp()
3738

3839
appContainer.Dispose();
3940
}
41+
42+
[Fact]
43+
public void RemovesInvalidTraceAndSpanIds()
44+
{
45+
var jo = new JObject
46+
{
47+
["@tr"] = "A234567890123456A234567890123456",
48+
["@sp"] = "A234567890123456",
49+
["@ps"] = "A234567890123456"
50+
};
51+
Assert.NotEmpty(jo);
52+
AppContainer.SanitizeTraceIdentifiers(jo);
53+
Assert.Empty(jo);
54+
}
55+
56+
[Fact]
57+
public void RemovesShortTraceAndSpanIds()
58+
{
59+
var jo = new JObject
60+
{
61+
["@tr"] = "234567890123456234567890123456",
62+
["@sp"] = "234567890123456",
63+
["@ps"] = "234567890123456"
64+
};
65+
Assert.NotEmpty(jo);
66+
AppContainer.SanitizeTraceIdentifiers(jo);
67+
Assert.Empty(jo);
68+
}
69+
70+
[Fact]
71+
public void PreservesValidTraceAndSpanIds()
72+
{
73+
var jo = new JObject
74+
{
75+
["@tr"] = "a234567890123456a234567890123456",
76+
["@sp"] = "a234567890123456",
77+
["@ps"] = "a234567890123456"
78+
};
79+
Assert.Equal(3, jo.Count);
80+
AppContainer.SanitizeTraceIdentifiers(jo);
81+
Assert.Equal(3, jo.Count);
82+
}
4083
}

0 commit comments

Comments
 (0)