Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
41 changes: 41 additions & 0 deletions .github/workflows/repro.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
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:

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

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

- name: Run repro
run: dotnet run --no-restore
48 changes: 39 additions & 9 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -58,8 +59,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))
{
Expand All @@ -76,6 +78,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") ?? "<null>"}");
Console.WriteLine($" PayloadByName(\"ObjectSize\"): {data.PayloadByName("ObjectSize") ?? "<null>"}");
Expand Down Expand Up @@ -121,15 +124,42 @@
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();
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 empty, Clr.All: 0 hits for EventID 303\n" +
$" [2] Workaround confirmed — raw bytes decoded {pct}% of sampled events");
File.Delete(traceFile);
return 0;

Expand Down
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -37,24 +36,25 @@ The program runs in three phases:

```
══ Native TraceEvent API (broken) ═════════════════════════════════════
PayloadNames: <null>
PayloadNames: <empty array>
PayloadByName("TypeName"): <null>
PayloadByName("ObjectSize"): <null>
PayloadValue(0): <null>
PayloadValue(0): <<<EXCEPTION_DURING_VALUE_LOOKUP IndexOutOfRangeException>>>
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: 100% (N / N)

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 100% of sampled 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
Expand Down
Loading