From 7294a3fcb4fa12e4e2b9f19e857d18e3bcf04c1d Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Thu, 19 Mar 2026 13:17:55 -0400 Subject: [PATCH 1/5] Add GitHub Actions workflow with explicit CI exit codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Program.cs: add exit codes 3 (issue not confirmed) and 4 (workaround failed) alongside the existing 0 (both pass), 1 (wrong runtime), 2 (no events). Exit 0 only when PayloadNames is null AND raw byte parsing decoded all events. .github/workflows/repro.yml: run on every push/PR, ubuntu-latest + .NET 10, restore then dotnet run — green = issue confirmed + workaround confirmed. --- .github/workflows/repro.yml | 40 +++++++++++++++++++++++++++++++++++ Program.cs | 42 ++++++++++++++++++++++++++++++------- 2 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/repro.yml diff --git a/.github/workflows/repro.yml b/.github/workflows/repro.yml new file mode 100644 index 0000000..1e63721 --- /dev/null +++ b/.github/workflows/repro.yml @@ -0,0 +1,40 @@ +name: Repro + +# Runs on every push and every PR. +# The job passes (green) when BOTH conditions hold: +# [1] Issue confirmed — TraceEvent 3.1.30 still has no typed schema for +# AllocationSampled (EventID 303): PayloadNames is null, +# source.Clr.All fires 0 times for EventID 303. +# [2] Workaround confirmed — raw EventData() byte parsing decodes all events. +# +# Exit codes from Program.cs: +# 0 normal / expected state (both conditions above hold) +# 1 wrong runtime (< .NET 10) +# 2 zero events captured (allocation volume too low or wrong runtime) +# 3 UNEXPECTED: TraceEvent now provides PayloadNames → issue may be fixed +# 4 FAIL: workaround broken (TryParseAllocationSampled returned false for all events) + +on: + push: + pull_request: + +jobs: + confirm: + name: Confirm issue + workaround (.NET 10) + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up .NET 10 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '10.0.x' + + - name: Restore + run: dotnet restore + working-directory: AllocationSampledRepro + + - name: Run repro + run: dotnet run --no-restore + working-directory: AllocationSampledRepro diff --git a/Program.cs b/Program.cs index 7c820aa..8f145dc 100644 --- a/Program.cs +++ b/Program.cs @@ -58,8 +58,9 @@ // ── Step 2: Parse via native TraceEvent API (broken) ─────────────────────── Console.WriteLine("══ Native TraceEvent API (broken) ═════════════════════════════════════"); -int nativeSeen = 0; -int clrTypedSeen = 0; +int nativeSeen = 0; +int clrTypedSeen = 0; +bool nativeSchemaAbsent = true; // flipped to false if TraceEvent provides PayloadNames using (var source = new EventPipeEventSource(traceFile)) { @@ -76,6 +77,7 @@ if (nativeSeen++ > 0) return; // Print only the first event for brevity var names = data.PayloadNames; + nativeSchemaAbsent = names is null || names.Length == 0; Console.WriteLine($" PayloadNames: {FormatNames(names)}"); Console.WriteLine($" PayloadByName(\"TypeName\"): {data.PayloadByName("TypeName") ?? ""}"); Console.WriteLine($" PayloadByName(\"ObjectSize\"): {data.PayloadByName("ObjectSize") ?? ""}"); @@ -124,12 +126,38 @@ Console.WriteLine($" Total events decoded via raw bytes: {rawDecoded} / {nativeSeen}"); Console.WriteLine(); -if (rawDecoded > 0) - Console.WriteLine("RESULT: native API yields no payload data; raw byte parsing works.\n" + - " ClrTraceEventParser needs a typed schema for EventID 303."); -else - Console.WriteLine("RESULT: raw byte parser also failed — allocation volume may need to increase."); +// ── CI assertions ───────────────────────────────────────────────────────────── +// Exit 0 = issue confirmed (PayloadNames null, Clr.All 0 hits) +// + workaround confirmed (raw bytes decoded events) ← expected/normal +// Exit 3 = issue NOT confirmed — TraceEvent may now have a typed schema +// Exit 4 = workaround FAILED — raw byte parsing decoded 0 events +bool issueConfirmed = nativeSchemaAbsent && clrTypedSeen == 0; +bool workaroundConfirmed = rawDecoded > 0; + +if (!issueConfirmed) +{ + Console.Error.WriteLine( + "CI: UNEXPECTED — TraceEvent appears to provide PayloadNames for AllocationSampled " + + "(EventID 303). If ClrTraceEventParser gained a typed schema, migrate to native " + + "PayloadByName/PayloadValue and close this issue."); + File.Delete(traceFile); + return 3; +} + +if (!workaroundConfirmed) +{ + Console.Error.WriteLine( + "CI: FAIL — raw byte workaround decoded 0 events. " + + "Payload layout may have changed; check TryParseAllocationSampled."); + File.Delete(traceFile); + return 4; +} + +Console.WriteLine( + "CI: PASS\n" + + " [1] Issue confirmed — PayloadNames null, Clr.All: 0 hits for EventID 303\n" + + $" [2] Workaround confirmed — raw bytes decoded {rawDecoded}/{nativeSeen} events"); File.Delete(traceFile); return 0; From a13ba7575a5a791c21248f0148a29816ddd6c6b6 Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Thu, 19 Mar 2026 13:20:26 -0400 Subject: [PATCH 2/5] Fix workflow: remove wrong working-directory, opt into Node 24 --- .github/workflows/repro.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/repro.yml b/.github/workflows/repro.yml index 1e63721..84ff0ec 100644 --- a/.github/workflows/repro.yml +++ b/.github/workflows/repro.yml @@ -18,6 +18,9 @@ on: push: pull_request: +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + jobs: confirm: name: Confirm issue + workaround (.NET 10) @@ -33,8 +36,6 @@ jobs: - name: Restore run: dotnet restore - working-directory: AllocationSampledRepro - name: Run repro run: dotnet run --no-restore - working-directory: AllocationSampledRepro From e2725030ff1e59388314ac5eaaf32be55fb9b550 Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Thu, 19 Mar 2026 13:31:45 -0400 Subject: [PATCH 3/5] Correct output to match CI-verified results PayloadNames returns empty array (not null). PayloadValue(0) returns sentinel string not null. Update expected output with actual event count and types from CI run. --- Program.cs | 3 ++- README.md | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Program.cs b/Program.cs index 8f145dc..7c79cfd 100644 --- a/Program.cs +++ b/Program.cs @@ -5,7 +5,8 @@ // // What this shows: // 1. Generate a live .nettrace with AllocationSamplingKeyword on .NET 10. -// 2. Parse via the native TraceEvent API → PayloadNames is null, PayloadByName returns null. +// 2. Parse via the native TraceEvent API → PayloadNames is an empty array, PayloadByName +// returns null, PayloadValue(0) returns a sentinel error string. // 3. Parse via raw EventData() bytes → TypeName and ObjectSize decoded successfully. using System.Diagnostics.Tracing; diff --git a/README.md b/README.md index a97fbd1..3d00ed3 100644 --- a/README.md +++ b/README.md @@ -37,24 +37,25 @@ The program runs in three phases: ``` ══ Native TraceEvent API (broken) ═════════════════════════════════════ - PayloadNames: + PayloadNames: PayloadByName("TypeName"): PayloadByName("ObjectSize"): - PayloadValue(0): + PayloadValue(0): <<>> source.Clr.All hits for EventID 303: 0 (0 = not routed through ClrTraceEventParser) - source.Dynamic.All hits for EventID 303: 47 + source.Dynamic.All hits for EventID 303: 78 ══ Raw EventData() workaround (works) ══════════════════════════════════ - [1] TypeName=System.String ObjectSize=96 bytes - [2] TypeName=System.String ObjectSize=96 bytes - [3] TypeName=System.Byte[] ObjectSize=512 bytes + [1] TypeName=System.Reflection.RuntimeMethodInfo ObjectSize=104 bytes ... - Total events decoded via raw bytes: 47 / 47 + Total events decoded via raw bytes: 78 / 78 -RESULT: native API yields no payload data; raw byte parsing works. - ClrTraceEventParser needs a typed schema for EventID 303. +CI: PASS + [1] Issue confirmed — PayloadNames empty, Clr.All: 0 hits for EventID 303 + [2] Workaround confirmed — raw bytes decoded 78/78 events ``` +(Event count and types vary per run; the CI workflow verifies both assertions on every push.) + ## Binary payload layout Decoded from the dotnet/runtime reference consumer From 8f6933cc652f26f3e8660a37c889de4bd3dec6bc Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Thu, 19 Mar 2026 13:36:19 -0400 Subject: [PATCH 4/5] Show workaround decode rate as % instead of raw count Count varies per run (randomized sampler); 100% success rate is the stable signal. --- Program.cs | 7 ++++--- README.md | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Program.cs b/Program.cs index 7c79cfd..fcbfb4f 100644 --- a/Program.cs +++ b/Program.cs @@ -124,7 +124,8 @@ source.Process(); } -Console.WriteLine($" Total events decoded via raw bytes: {rawDecoded} / {nativeSeen}"); +int pct = nativeSeen > 0 ? rawDecoded * 100 / nativeSeen : 0; +Console.WriteLine($" Total events decoded via raw bytes: {pct}% ({rawDecoded} / {nativeSeen})"); Console.WriteLine(); @@ -157,8 +158,8 @@ Console.WriteLine( "CI: PASS\n" + - " [1] Issue confirmed — PayloadNames null, Clr.All: 0 hits for EventID 303\n" + - $" [2] Workaround confirmed — raw bytes decoded {rawDecoded}/{nativeSeen} events"); + " [1] Issue confirmed — PayloadNames empty, Clr.All: 0 hits for EventID 303\n" + + $" [2] Workaround confirmed — raw bytes decoded {pct}% of sampled events"); File.Delete(traceFile); return 0; diff --git a/README.md b/README.md index 3d00ed3..fe8bb8a 100644 --- a/README.md +++ b/README.md @@ -47,11 +47,11 @@ The program runs in three phases: ══ Raw EventData() workaround (works) ══════════════════════════════════ [1] TypeName=System.Reflection.RuntimeMethodInfo ObjectSize=104 bytes ... - Total events decoded via raw bytes: 78 / 78 + Total events decoded via raw bytes: 100% (N / N) CI: PASS [1] Issue confirmed — PayloadNames empty, Clr.All: 0 hits for EventID 303 - [2] Workaround confirmed — raw bytes decoded 78/78 events + [2] Workaround confirmed — raw bytes decoded 100% of sampled events ``` (Event count and types vary per run; the CI workflow verifies both assertions on every push.) From 8dd34c0afbc873b45bbaebc8344be0621aa82d3e Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Thu, 19 Mar 2026 13:57:41 -0400 Subject: [PATCH 5/5] Link perfview#2385 in README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index fe8bb8a..8b9aac1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # AllocationSampledRepro -Minimal self-contained repro for the missing `AllocationSampled` (EventID 303) typed schema in -`Microsoft.Diagnostics.Tracing.TraceEvent` 3.1.30. +Minimal self-contained repro for [microsoft/perfview#2385](https://github.com/microsoft/perfview/issues/2385) — missing `AllocationSampled` (EventID 303) typed schema in `Microsoft.Diagnostics.Tracing.TraceEvent` 3.1.30. ## Requirements