Skip to content

Commit b13ded4

Browse files
Handle SQL Server 2022+ histogram without CDATA (#145)
* In SQL Server 2022 XE histogram output, the internal frame XML elements are not surrounded by a CDATA element; this case is now handled correctly. * In an unrelated change, "format" the GUI app config's settings section to the normal form; for some reason local builds were not handling the compact XML form without newlines correctly.
1 parent 554390b commit b13ded4

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

Engine/StackResolver.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,10 @@ public async Task<List<StackDetails>> GetListofCallStacksAsync(string inputCalls
440440
inputCallstackText = Regex.Replace(inputCallstackText, @"(?<prefix>.*?)(?<starttag>\<HistogramTarget)(?<trailing>.+?\<\/HistogramTarget\>)",
441441
(Match m) => { return $"{m.Groups["starttag"].Value} annotation=\"{System.Net.WebUtility.HtmlEncode(m.Groups["prefix"].Value.Replace("\r", string.Empty).Replace("\n", string.Empty).Trim())}\" {m.Groups["trailing"].Value}"; }
442442
, RegexOptions.Singleline);
443+
444+
// handle the case seen in SQL Server 2022+ where there is no CDATA section in the HistogramTarget XML
445+
if (!inputCallstackText.Contains("<![CDATA[")) inputCallstackText = inputCallstackText.Replace("<value><frame", "<value><![CDATA[<frame").Replace(" /></value>", " />]]></value>");
446+
443447
inputCallstackText = $"<Histograms>{inputCallstackText}</Histograms>";
444448
}
445449
}

GUI/App.config

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,14 @@
2323
<dependentAssembly><assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /><bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" /></dependentAssembly>
2424
</assemblyBinding>
2525
</runtime>
26-
<userSettings><Microsoft.SqlServer.Utils.Misc.SQLCallStackResolver.Properties.Settings>
27-
<setting name="promptForClipboardPaste" serializeAs="String"><value>True</value></setting>
28-
<setting name="choiceForClipboardPaste" serializeAs="String"><value>False</value></setting>
29-
</Microsoft.SqlServer.Utils.Misc.SQLCallStackResolver.Properties.Settings></userSettings>
30-
</configuration>
26+
<userSettings>
27+
<Microsoft.SqlServer.Utils.Misc.SQLCallStackResolver.Properties.Settings>
28+
<setting name="promptForClipboardPaste" serializeAs="String">
29+
<value>True</value>
30+
</setting>
31+
<setting name="choiceForClipboardPaste" serializeAs="String">
32+
<value>False</value>
33+
</setting>
34+
</Microsoft.SqlServer.Utils.Misc.SQLCallStackResolver.Properties.Settings>
35+
</userSettings>
36+
</configuration>

Tests/Tests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,24 @@ private string PrepareLargeXEventInput() {
665665
Assert.AreEqual(expected.Trim(), ret.Trim());
666666
}
667667

668+
/// End-to-end test with XE histogram target and XML frames with no CDATA section and the <frame> elements directly inside.
669+
[TestMethod][TestCategory("Unit")]
670+
public async Task E2ESymSrvXMLFramesHistogramNoCDATA() {
671+
using var csr = new StackResolver();
672+
using var cts = new CancellationTokenSource();
673+
var pdbPath = @"srv*https://msdl.microsoft.com/download/symbols";
674+
var input = "<HistogramTarget truncated=\"0\" buckets=\"256\"><Slot count=\"5\"><value><frame id=\"00\" pdb=\"ntdll.pdb\" age=\"1\" guid=\"C374E059-5793-9B92-6525-386A66A2D3F5\" module=\"ntdll.dll\" rva=\"0x9F7E4\" />" +
675+
"<frame id=\"01\" pdb=\"kernelbase.pdb\" age=\"1\" guid=\"E77E26E7-D1C4-72BB-2C05-DD17624A9E58\" module=\"KERNELBASE.dll\" rva=\"0x38973\" />" +
676+
"<frame id=\"02\" pdb=\"SqlDK.pdb\" age=\"2\" guid=\"6a193443-3512-464b-8b8e-d905ad930ee6\" module=\"sqldk.dll\" rva=\"0x40609\" />" +
677+
"</value></Slot><Slot count=\"3\"><value><frame id=\"00\" pdb=\"vcruntime140.amd64.pdb\" age=\"1\" guid=\"AF138C3F-2933-4097-8883-C1071B13375E\" module=\"VCRUNTIME140.dll\" rva=\"0xB8F0\" />" +
678+
"<frame id=\"01\" pdb=\"SqlDK.pdb\" age=\"2\" guid=\"6a193443-3512-464b-8b8e-d905ad930ee6\" module=\"sqldk.dll\" rva=\"0x2249f\" />" +
679+
"</value></Slot></HistogramTarget>";
680+
681+
var ret = await csr.ResolveCallstacksAsync(await csr.GetListofCallStacksAsync(input, false, cts), pdbPath, false, null, false, true, false, true, false, false, null, cts);
682+
var expected = "Slot_0 [count:5]:\r\n\r\n00 ntdll!NtWaitForSingleObject+20\r\n01 KERNELBASE!WaitForSingleObjectEx+147\r\n02 sqldk!MemoryClerkInternal::AllocatePagesWithFailureMode+644\r\n\r\nSlot_1 [count:3]:\r\n\r\n00 VCRUNTIME140!__C_specific_handler+160 (d:\\agent\\_work\\2\\s\\src\\vctools\\crt\\vcruntime\\src\\eh\\riscchandler.cpp:290)\r\n01 sqldk!Spinlock<244,2,1>::SpinToAcquireWithExponentialBackoff+349";
683+
Assert.AreEqual(expected.Trim(), ret.Trim());
684+
}
685+
668686
/// End-to-end test with XE histogram target and module+offset frames.
669687
[TestMethod][TestCategory("Unit")] public async Task E2EHistogramAddresses() {
670688
using var csr = new StackResolver();

0 commit comments

Comments
 (0)