Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
47231e1
[UserEvents] Add end-to-end runtime test
mdh1418 Nov 3, 2025
963efe1
Merge remote-tracking branch 'upstream/main' into user_events_functio…
mdh1418 Nov 3, 2025
e712df6
Cleanup test props
mdh1418 Nov 3, 2025
2b246be
Add ProcessStartInfo and using keyword
mdh1418 Nov 3, 2025
a7afeb9
Fix process exit detection
mdh1418 Nov 3, 2025
c41916a
Retain nettrace test asset
mdh1418 Nov 3, 2025
963af3f
Address feedback
mdh1418 Nov 7, 2025
005cc94
Fix RecordTrace package resolving
mdh1418 Nov 7, 2025
5d09bd2
Alternative user_events_data access check
mdh1418 Nov 7, 2025
146b348
Fix record-trace startup
mdh1418 Nov 10, 2025
a8d5d97
Detect record-trace unexpected exit and flush output
mdh1418 Nov 10, 2025
f9531d2
Fix record-trace output
mdh1418 Nov 10, 2025
ffc0c16
Reduce enabled keywords
mdh1418 Nov 10, 2025
04f072c
Switch to AllocationSampled Event
mdh1418 Nov 10, 2025
98496bc
Attempt to copy userevents assets for CI
mdh1418 Nov 11, 2025
96efe8e
Enable Helix tests to run record-trace
mdh1418 Nov 12, 2025
fe00510
Add requirements check and upload trace
mdh1418 Nov 18, 2025
368b499
Configure DiagnosticPort creation for RecordTrace
mdh1418 Nov 26, 2025
50b29aa
[Test] Extend UserEvents to reusable TestRunner
mdh1418 Dec 2, 2025
2811831
[Test] Remove eventpipe embedded userevents tests
mdh1418 Dec 2, 2025
23474bb
[TEMP] disable all other pipelines
mdh1418 Nov 26, 2025
4e2febb
Merge remote-tracking branch 'upstream/main' into user_events_functio…
mdh1418 Dec 2, 2025
0acfb99
Include userevents_common in helix payload
mdh1418 Dec 2, 2025
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
3 changes: 2 additions & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
<!-- Not auto-updated. -->
<MicrosoftDiaSymReaderVersion>2.0.0</MicrosoftDiaSymReaderVersion>
<MicrosoftDiaSymReaderNativeVersion>17.10.0-beta1.24272.1</MicrosoftDiaSymReaderNativeVersion>
<TraceEventVersion>3.1.16</TraceEventVersion>
<TraceEventVersion>3.1.28</TraceEventVersion>
<MicrosoftDiagnosticsNetCoreClientVersion>0.2.621003</MicrosoftDiagnosticsNetCoreClientVersion>
<NETStandardLibraryRefVersion>2.1.0</NETStandardLibraryRefVersion>
<NetStandardLibraryVersion>2.0.3</NetStandardLibraryVersion>
Expand All @@ -124,6 +124,7 @@
<!-- Testing -->
<MicrosoftNETCoreCoreDisToolsVersion>1.6.0</MicrosoftNETCoreCoreDisToolsVersion>
<MicrosoftNETTestSdkVersion>17.4.0-preview-20220707-01</MicrosoftNETTestSdkVersion>
<MicrosoftOneCollectRecordTraceVersion>0.1.32221</MicrosoftOneCollectRecordTraceVersion>
<NUnitVersion>3.12.0</NUnitVersion>
<NUnit3TestAdapterVersion>4.5.0</NUnit3TestAdapterVersion>
<CoverletCollectorVersion>6.0.4</CoverletCollectorVersion>
Expand Down
2 changes: 2 additions & 0 deletions src/tests/tracing/eventpipe/userevents/dotnet-common.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
let Microsoft_Windows_DotNETRuntime_flags = new_dotnet_provider_flags();
record_dotnet_provider("Microsoft-Windows-DotNETRuntime", 0x100003801D, 4, Microsoft_Windows_DotNETRuntime_flags);
120 changes: 120 additions & 0 deletions src/tests/tracing/eventpipe/userevents/userevents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Etlx;

namespace Tracing.Tests.UserEvents
{
public class UserEventsTest
{
private static readonly string trace = "trace.nettrace";
private const int SIGINT = 2;

[DllImport("libc", SetLastError = true)]
private static extern int kill(int pid, int sig);

public static int Main(string[] args)
{
if (args.Length > 0 && args[0] == "tracee")
{
UserEventsTracee.Run();
return 0;
}

return TestEntryPoint();
}

public static int TestEntryPoint()
{
string appBaseDir = AppContext.BaseDirectory;
string recordTracePath = Path.Combine(appBaseDir, "record-trace");
string scriptFilePath = Path.Combine(appBaseDir, "dotnet-common.script");
string traceFilePath = Path.Combine(appBaseDir, trace);

if (!File.Exists(recordTracePath) || !File.Exists(scriptFilePath))
{
Console.WriteLine("record-trace or dotnet-common.script not found. Test cannot run.");
return -1;
}

ProcessStartInfo traceeStartInfo = new();
traceeStartInfo.FileName = Process.GetCurrentProcess().MainModule.FileName;
traceeStartInfo.Arguments = $"{typeof(UserEventsTest).Assembly.Location} tracee";
traceeStartInfo.WorkingDirectory = appBaseDir;

ProcessStartInfo recordTraceStartInfo = new();
recordTraceStartInfo.FileName = recordTracePath;
recordTraceStartInfo.Arguments = $"--script-file {scriptFilePath}";
recordTraceStartInfo.WorkingDirectory = appBaseDir;
recordTraceStartInfo.RedirectStandardOutput = true;
recordTraceStartInfo.RedirectStandardError = true;

using Process traceeProcess = Process.Start(traceeStartInfo);
using Process recordTraceProcess = Process.Start(recordTraceStartInfo);
recordTraceProcess.OutputDataReceived += (_, args) => Console.WriteLine($"[record-trace] {args.Data}");
recordTraceProcess.BeginOutputReadLine();
recordTraceProcess.ErrorDataReceived += (_, args) => Console.Error.WriteLine($"[record-trace] {args.Data}");
recordTraceProcess.BeginErrorReadLine();

if (!traceeProcess.HasExited && !traceeProcess.WaitForExit(15000))
{
traceeProcess.Kill();
}

// Until record-trace supports duration, the only way to stop it is to send SIGINT (ctrl+c)
kill(recordTraceProcess.Id, SIGINT);
if (!recordTraceProcess.HasExited && !recordTraceProcess.WaitForExit(20000))
{
// record-trace needs to stop gracefully to generate the trace file
recordTraceProcess.Kill();
}

if (!File.Exists(traceFilePath))
{
Console.Error.WriteLine($"Expected trace file not found at `{traceFilePath}`");
return -1;
}

if (!ValidateTraceeEvents(traceFilePath))
{
Console.Error.WriteLine($"Trace file `{traceFilePath}` does not contain expected events.");
return -1;
}

return 100;
}

private static bool ValidateTraceeEvents(string traceFilePath)
{
string etlxPath = TraceLog.CreateFromEventPipeDataFile(traceFilePath);
using TraceLog log = new(etlxPath);
using TraceLogEventSource source = log.Events.GetSource();
bool startEventFound = false;
bool stopEventFound = false;

source.AllEvents += (TraceEvent e) =>
{
if (e.ProviderName == "Microsoft-Windows-DotNETRuntime")
{
if (e.EventName == "GC/Start")
{
startEventFound = true;
}
else if (e.EventName == "GC/Stop")
{
stopEventFound = true;
}
}
};

source.Process();
return startEventFound && stopEventFound;
}
}
}
34 changes: 34 additions & 0 deletions src/tests/tracing/eventpipe/userevents/userevents.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<CLRTestTargetUnsupported Condition="'$(TargetOS)' != 'linux' or ('$(TargetArchitecture)' != 'x64' and '$(TargetArchitecture)' != 'arm64')">true</CLRTestTargetUnsupported>
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
<IlasmRoundTripIncompatible>true</IlasmRoundTripIncompatible>
</PropertyGroup>

<PropertyGroup>
<RestoreAdditionalProjectSources>$(RestoreAdditionalProjectSources);https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-diagnostics-tests/nuget/v3/index.json</RestoreAdditionalProjectSources>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.OneCollect.RecordTrace" Version="$(MicrosoftOneCollectRecordTraceVersion)" PrivateAssets="All" Condition="'$(TargetOS)' == 'linux'" />
</ItemGroup>

<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
<Compile Include="usereventstracee.cs" />
</ItemGroup>

<ItemGroup>
<None Include="dotnet-common.script" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

<Target Name="CopyRecordTraceBinary" AfterTargets="Build" Condition="'$(TargetOS)' == 'linux'">
<PropertyGroup>
<RecordTracePath>$(NuGetPackageRoot)microsoft.onecollect.recordtrace/$(MicrosoftOneCollectRecordTraceVersion)/runtimes/$(TargetOS)-$(TargetArchitecture)/native/record-trace</RecordTracePath>
</PropertyGroup>

<Copy SourceFiles="$(RecordTracePath)" DestinationFolder="$(OutputPath)" Condition="Exists('$(RecordTracePath)')" />
<Error Text="record-trace not found at $(RecordTracePath)" Condition="!Exists('$(RecordTracePath)')" />

Check failure on line 32 in src/tests/tracing/eventpipe/userevents/userevents.csproj

View check run for this annotation

Azure Pipelines / runtime (Build linux-x64 Release AllSubsets_Mono_LLVMAot_RuntimeTests llvmaot)

src/tests/tracing/eventpipe/userevents/userevents.csproj#L32

src/tests/tracing/eventpipe/userevents/userevents.csproj(32,5): error : record-trace not found at /__w/1/s/.packages/microsoft.onecollect.recordtrace/0.1.32221/runtimes/linux-x64/native/record-trace

Check failure on line 32 in src/tests/tracing/eventpipe/userevents/userevents.csproj

View check run for this annotation

Azure Pipelines / runtime (Build linux-arm64 Release AllSubsets_Mono_Minijit_RuntimeTests minijit)

src/tests/tracing/eventpipe/userevents/userevents.csproj#L32

src/tests/tracing/eventpipe/userevents/userevents.csproj(32,5): error : record-trace not found at /__w/1/s/.packages/microsoft.onecollect.recordtrace/0.1.32221/runtimes/linux-arm64/native/record-trace

Check failure on line 32 in src/tests/tracing/eventpipe/userevents/userevents.csproj

View check run for this annotation

Azure Pipelines / runtime

src/tests/tracing/eventpipe/userevents/userevents.csproj#L32

src/tests/tracing/eventpipe/userevents/userevents.csproj(32,5): error : record-trace not found at /__w/1/s/.packages/microsoft.onecollect.recordtrace/0.1.32221/runtimes/linux-arm64/native/record-trace

Check failure on line 32 in src/tests/tracing/eventpipe/userevents/userevents.csproj

View check run for this annotation

Azure Pipelines / runtime

src/tests/tracing/eventpipe/userevents/userevents.csproj#L32

src/tests/tracing/eventpipe/userevents/userevents.csproj(32,5): error : record-trace not found at /__w/1/s/.packages/microsoft.onecollect.recordtrace/0.1.32221/runtimes/linux-x64/native/record-trace
</Target>
</Project>
31 changes: 31 additions & 0 deletions src/tests/tracing/eventpipe/userevents/usereventstracee.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.Threading;

namespace Tracing.Tests.UserEvents
{
public class UserEventsTracee
{
private static byte[] s_array;

public static void Run()
{
long startTimestamp = Stopwatch.GetTimestamp();
long targetTicks = Stopwatch.Frequency * 10; // 10s

while (Stopwatch.GetTimestamp() - startTimestamp < targetTicks)
{
for (int i = 0; i < 100; i++)
{
s_array = new byte[1024 * 10];
}

GC.Collect();
Thread.Sleep(100);
}
}
}
}
Loading