Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ebd4670
wip: tracelog support for streaming an eventpipe source
vaind May 3, 2023
a9433c5
tracelog streaming fixes
vaind May 4, 2023
392c9fa
TraceLog support for initial rundown session
vaind May 19, 2023
6286887
fix stacktrace resolution on system frames
vaind May 23, 2023
f714892
feat: realtime streaming without queue
vaind May 30, 2023
382b8fe
update CreateFromEventPipeEventSource to support providing preloaded…
vaind May 30, 2023
4db0a45
review changes
vaind Jun 7, 2023
f890e71
review changes
vaind Aug 3, 2023
dbd71ff
test: TraceLog StreamingSession
vaind Aug 4, 2023
f1fcf81
fix CI
vaind Aug 9, 2023
3c65579
test: fix not disposing
vaind Aug 9, 2023
f5b49e4
update test dependencies
vaind Aug 9, 2023
53024ea
wip: find crashing test
vaind Aug 9, 2023
bed3d38
Merge branch 'main' into feat/eventpipe-tracelog-streaming
vaind Mar 20, 2024
68c1081
use net8 in testutils
vaind Mar 20, 2024
b2bb4e5
roll back debug assert change in tracelog
vaind Mar 25, 2024
36d2e2c
fix: clean up termporary data structures for realtime eventpipe source
vaind May 23, 2024
69a09db
Merge remote-tracking branch 'origin/main' into feat/eventpipe-tracel…
vaind May 23, 2024
fee63f9
chore: roll back some changes
vaind May 23, 2024
5153769
docs
vaind May 23, 2024
44c8fee
Merge branch 'main' into feat/eventpipe-tracelog-streaming
vaind Jun 6, 2024
2270d69
set NuspecProperties
vaind Jun 27, 2024
d161492
Merge branch 'main' into feat/eventpipe-tracelog-streaming
vaind Jun 27, 2024
e21e9c7
fix traceevent.csproj
vaind Jun 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
test: TraceLog StreamingSession
  • Loading branch information
vaind committed Aug 9, 2023
commit dbd71ff94e998d19737795c366bc5cf2236b7cc7
2 changes: 1 addition & 1 deletion src/PerfView.TestUtilities/PerfView.TestUtilities.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net462</TargetFramework>
<TargetFrameworks>net462;net6.0</TargetFrameworks>
<Description>Unit test utility library.</Description>
<Copyright>Copyright © Microsoft 2017</Copyright>

Expand Down
137 changes: 78 additions & 59 deletions src/TraceEvent/TraceEvent.Tests/Parsing/EventPipeParsing.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FastSerialization;
using Microsoft.Diagnostics.NETCore.Client;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Etlx;
using Microsoft.Diagnostics.Tracing.EventPipe;
Expand All @@ -7,9 +8,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
using static Microsoft.Diagnostics.Tracing.Etlx.TraceLog;
Expand Down Expand Up @@ -45,14 +48,30 @@ public void Record(string eventName, TraceEvent data)
};
}
}

override
public string ToString()
{
StringBuilder sb = new StringBuilder(1024 * 1024);
foreach (var item in Records)
{
sb.AppendLine($"{item.Key}, {item.Value.TotalCount}, {item.Value.FirstSerializedSample}");
}

return sb.ToString();
}
}

public EventPipeParsing(ITestOutputHelper output)
: base(output)
{
}

[Theory()]
#if NETCOREAPP3_0_OR_GREATER
[Theory(Skip = "Snapshot difs due to increased float accuracy on newer .NET versions.")]
#else
[Theory]
#endif
[MemberData(nameof(TestEventPipeFiles))]
public void Basic(string eventPipeFileName)
{
Expand Down Expand Up @@ -101,7 +120,7 @@ public void Streaming(string eventPipeFileName)
// block to read the events
Assert.InRange(newStreamPosition, curStreamPosition, curStreamPosition + 103_000);
curStreamPosition = newStreamPosition;

string eventName = data.ProviderName + "/" + data.EventName;

// For whatever reason the parse filtering below produces a couple extra events
Expand Down Expand Up @@ -143,53 +162,59 @@ public void Streaming(string eventPipeFileName)
ValidateEventStatistics(eventStatistics, eventPipeFileName);
}

[Theory()]
[MemberData(nameof(StreamableTestEventPipeFiles))]
public void TraceLogStreaming(string eventPipeFileName)
#if NETCOREAPP3_0_OR_GREATER
[Theory]
#else
[Theory(Skip = "EventPipeSession connection is only available to target apps on .NET Core 3.0 or later")]
#endif
[InlineData(true)]
[InlineData(false)]
public async Task SessionStreaming(bool initialRundown)
{
// Initialize
PrepareTestData();

string eventPipeFilePath = Path.Combine(UnZippedDataDir, eventPipeFileName);
Output.WriteLine(string.Format("Processing the file {0}", Path.GetFullPath(eventPipeFilePath)));
var eventStatistics = new EventStatistics();

using (MockStreamingOnlyStream s = new MockStreamingOnlyStream(new FileStream(eventPipeFilePath, FileMode.Open, FileAccess.Read, FileShare.Read)))
var client = new DiagnosticsClient(Process.GetCurrentProcess().Id);
var rundownConfig = initialRundown ? EventPipeRundownConfiguration.Enable(client) : EventPipeRundownConfiguration.None();
var providers = new[]
{
new EventPipeProvider(SampleProfilerTraceEventParser.ProviderName, EventLevel.Informational),
};
using (var session = client.StartEventPipeSession(providers, requestRundown: false))
{
using (var eventPipeSource = new EventPipeEventSource(s))
using (var traceSource = CreateFromEventPipeSession(session, rundownConfig))
{
using (var traceSource = CreateFromEventPipeEventSource(eventPipeSource))
var sampleEventParser = new SampleProfilerTraceEventParser(traceSource);

// Signal that we have received the first event.
var eventReceived = new TaskCompletionSource<TraceEvent>();
sampleEventParser.ThreadSample += delegate (ClrThreadSampleTraceData e) {
eventReceived.TrySetResult(e);
};

// Process in the background (this is blocking).
var processingTask = Task.Run(traceSource.Process);

// Verify the event can be symbolicated on the fly if (initialRundown == true).
var ev = await eventReceived.Task;

var callStackIndex = ev.CallStackIndex();
Assert.NotEqual(CallStackIndex.Invalid, callStackIndex);
var codeAddressIndex = traceSource.TraceLog.CallStacks.CodeAddressIndex(callStackIndex);
Assert.NotEqual(CodeAddressIndex.Invalid, codeAddressIndex);
var methodIndex = traceSource.TraceLog.CodeAddresses.MethodIndex(codeAddressIndex);
if (initialRundown)
{
Assert.NotEqual(MethodIndex.Invalid, methodIndex);
var method = traceSource.TraceLog.CodeAddresses.Methods[methodIndex];
Assert.NotEmpty(method.FullMethodName);
} else
{
Action<TraceEvent> handler = eventStatistics.Record;

// this is somewhat arbitrary looking set of parser event callbacks empirically
// produces the same set of events as TraceLog.Events.GetSource().AllEvents so
// that the baseline files can be reused from the Basic test
var rundown = new ClrRundownTraceEventParser(traceSource);
rundown.LoaderAppDomainDCStop += handler;
rundown.LoaderAssemblyDCStop += handler;
rundown.LoaderDomainModuleDCStop += handler;
rundown.LoaderModuleDCStop += handler;
rundown.MethodDCStopComplete += handler;
rundown.MethodDCStopInit += handler;
var sampleProfiler = new SampleProfilerTraceEventParser(traceSource);
sampleProfiler.All += handler;
var privateClr = new ClrPrivateTraceEventParser(traceSource);
privateClr.All += handler;
traceSource.Clr.All += handler;
traceSource.Clr.MethodILToNativeMap -= handler;
// traceSource.Dynamic.All += handler;

// TODO Needed for custom events (eventpipe-dotnetcore2.1-linux-x64-tracelogging.net), but the event names are still missing...
// traceSource.UnhandledEvents += handler;

// Process
traceSource.Process();
Assert.Equal(MethodIndex.Invalid, methodIndex);
}

// Stop after receiving the first event.
session.Stop();
await processingTask;
}
}
// Validate
ValidateEventStatistics(eventStatistics, eventPipeFileName);
}

[Fact]
Expand Down Expand Up @@ -292,7 +317,7 @@ public void V4EventPipeFileHasProcNumbers()
// Process
traceSource.Process();

for(int i = 0; i < traceSource.NumberOfProcessors; i++)
for (int i = 0; i < traceSource.NumberOfProcessors; i++)
{
Assert.NotEqual(0, counts[i]);
}
Expand Down Expand Up @@ -616,13 +641,7 @@ private void Dynamic_All(TraceEvent obj)

private void ValidateEventStatistics(EventStatistics eventStatistics, string eventPipeFileName)
{
StringBuilder sb = new StringBuilder(1024 * 1024);
foreach (var item in eventStatistics.Records)
{
sb.AppendLine($"{item.Key}, {item.Value.TotalCount}, {item.Value.FirstSerializedSample}");
}

string actual = sb.ToString();
string actual = eventStatistics.ToString();
string baselineFile = Path.Combine(TestDataDir, eventPipeFileName + ".baseline.txt");
string expected = File.ReadAllText(baselineFile);

Expand All @@ -647,7 +666,7 @@ public MockStreamingOnlyStream(Stream innerStream)
{
_innerStream = innerStream;
}
public long TestOnlyPosition { get { return _innerStream.Position; } }
public long TestOnlyPosition { get { return _innerStream.Position; } }

public override bool CanRead => true;
public override bool CanSeek => false;
Expand Down Expand Up @@ -706,7 +725,7 @@ public void Write(string arg)
public void WriteArray<T>(T[] elements, Action<T> writeElement)
{
WriteArrayLength(elements.Length);
for(int i = 0; i < elements.Length; i++)
for (int i = 0; i < elements.Length; i++)
{
writeElement(elements[i]);
}
Expand Down Expand Up @@ -823,7 +842,7 @@ private static void Align(BinaryWriter writer, long previousBytesWritten)
}
}

public static void WriteBlock(BinaryWriter writer, string name, Action<BinaryWriter> writeBlockData,
public static void WriteBlock(BinaryWriter writer, string name, Action<BinaryWriter> writeBlockData,
long previousBytesWritten = 0)
{
Debug.WriteLine($"Starting block {name} position: {writer.BaseStream.Position + previousBytesWritten}");
Expand Down Expand Up @@ -975,7 +994,7 @@ MemoryStream GetFirstChunk()
EventPipeWriter.WriteNetTraceHeader(writer);
EventPipeWriter.WriteFastSerializationHeader(writer);
EventPipeWriter.WriteTraceObject(writer);
EventPipeWriter.WriteMetadataBlock(writer,
EventPipeWriter.WriteMetadataBlock(writer,
new EventMetadata(1, "Provider", "Event", 1));
ms.Position = 0;
return ms;
Expand All @@ -994,16 +1013,16 @@ MemoryStream GetNextChunk()
else
{
// 20 blocks, each with 20 events in them
for(int i = 0; i < 20; i++)
for (int i = 0; i < 20; i++)
{
EventPipeWriter.WriteEventBlock(writer,
EventPipeWriter.WriteEventBlock(writer,
w =>
{
for (int j = 0; j < 20; j++)
{
EventPipeWriter.WriteEventBlob(w, 1, _sequenceNumber++, payloadSize, WriteEventPayload);
}
},
},
_bytesWritten);
}
}
Expand Down Expand Up @@ -1031,7 +1050,7 @@ public override void Flush()
public override int Read(byte[] buffer, int offset, int count)
{
int ret = _currentChunk.Read(buffer, offset, count);
if(ret == 0)
if (ret == 0)
{
_currentChunk = GetNextChunk();
_bytesWritten += _currentChunk.Length;
Expand Down
4 changes: 4 additions & 0 deletions src/TraceEvent/TraceEvent.Tests/Parsing/GeneralParsing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ public GeneralParsing(ITestOutputHelper output)
/// and scans them (so you should get asserts if there is parsing problem)
/// and ensures that no more than .1% of the events are
/// </summary>
#if NETCOREAPP3_0_OR_GREATER
[Theory(Skip = "Snapshot difs due to increased float accuracy on newer .NET versions.")]
#else
[Theory]
#endif
[MemberData(nameof(TestEtlFiles))]
public void ETW_GeneralParsing_Basic(string etlFileName)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ public MultiFileMergeAll(ITestOutputHelper output)
/// This test unzips a zip file containing 4 etls files, open them as 1 trace
/// and asserts the correct TraceLog size and event count
/// </summary>
#if NETCOREAPP3_0_OR_GREATER
[Fact(Skip = "Snapshot difs due to increased float accuracy on newer .NET versions.")]
#else
[Fact]
#endif
public void ETW_MultiFileMergeAll_Basic()
{
PrepareTestData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

using static Microsoft.Diagnostics.Tracing.Stacks.StackSourceWriterHelper;

// For Debug.Listeners
#if NETCOREAPP3_0_OR_GREATER
using Debug = System.Diagnostics.Trace;
#else
using Debug = System.Diagnostics.Debug;
#endif

namespace TraceEventTests
{
public class SpeedScopeStackSourceWriterTests
Expand Down
3 changes: 2 additions & 1 deletion src/TraceEvent/TraceEvent.Tests/TraceEvent.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net462</TargetFrameworks>
<TargetFrameworks>net462;net6.0</TargetFrameworks>
<RootNamespace>TraceEventTests</RootNamespace>
<AssemblyName>TraceEventTests</AssemblyName>
<Description>Unit tests for TraceEvent.</Description>
Expand All @@ -18,6 +18,7 @@
<PackageReference Include="xunit" Version="$(XunitVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualstudioVersion)" PrivateAssets="all" />
<PackageReference Include="System.IO.Compression" Version="$(SystemIOCompressionVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
</ItemGroup>

<ItemGroup>
Expand Down