Skip to content

Commit

Permalink
Properly handle self-describing events. (#1999)
Browse files Browse the repository at this point in the history
  • Loading branch information
cincuranet authored Mar 2, 2024
1 parent c1c7266 commit 541dfc2
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/TraceEvent/DynamicTraceEventParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,8 @@ protected internal override Delegate Target
get { return m_target; }
set
{
Debug.Assert(m_target == null);
// value can be set to null when cloning and converting to a template for live session dispatch
Debug.Assert(m_target == null || value == null);
m_target = (Action<TraceEvent>)value;
}
}
Expand Down
14 changes: 12 additions & 2 deletions src/TraceEvent/TraceEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,7 @@ public virtual unsafe TraceEvent Clone()
}
return ret;
}

/// <summary>
/// Pretty print the event. It uses XML syntax..
/// </summary>
Expand Down Expand Up @@ -2012,6 +2013,15 @@ internal int ThreadIDforStacks()
/// </summary>
protected internal virtual void SetState(object state) { }

protected internal TraceEvent CloneToTemplate()
{
TraceEvent ret = Clone();
ret.traceEventSource = null;
ret.eventRecord = null;
ret.Target = null;
return ret;
}

#endregion
#region Private
private static char HexDigit(int digit)
Expand Down Expand Up @@ -3647,7 +3657,6 @@ internal TraceEvent Lookup(TraceEventNativeMethods.EVENT_RECORD* eventRecord)
curTemplate.eventRecord = eventRecord;
curTemplate.userData = eventRecord->UserData;
curTemplate.eventIndex = currentID;
currentID = currentID + 1; // TODO overflow.

if ((((int)currentID) & 0xFFFF) == 0) // Every 64K events allow Thread.Interrupt.
{
Expand Down Expand Up @@ -3685,6 +3694,7 @@ internal TraceEvent Lookup(TraceEventNativeMethods.EVENT_RECORD* eventRecord)
(curTemplate.ProviderGuid == GCDynamicTraceEventParser.ProviderGuid && gcDynamicTemplateEventHeaderMatch));
}
#endif
currentID = currentID + 1; // TODO overflow.
return curTemplate;
}
else
Expand All @@ -3704,7 +3714,6 @@ internal TraceEvent Lookup(TraceEventNativeMethods.EVENT_RECORD* eventRecord)
unhandledEventTemplate.userData = eventRecord->UserData;
unhandledEventTemplate.eventIndex = currentID;
unhandledEventTemplate.lookupAsClassic = unhandledEventTemplate.IsClassicProvider;
currentID = currentID + 1; // TODO overflow.
if ((((int)currentID) & 0xFFFF) == 0) // Every 64K events allow Thread.Interrupt.
{
System.Threading.Thread.Sleep(0);
Expand Down Expand Up @@ -3739,6 +3748,7 @@ internal TraceEvent Lookup(TraceEventNativeMethods.EVENT_RECORD* eventRecord)
}
while (lastChanceHandlerChecked < lastChanceHandlers.Length);
}
currentID = currentID + 1; // TODO overflow.
return unhandledEventTemplate;
}
internal unsafe TraceEvent LookupTemplate(Guid guid, TraceEventID eventID_)
Expand Down
19 changes: 19 additions & 0 deletions src/TraceEvent/TraceLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,19 @@ private static void RemoveAllButLastEntries<T>(ref GrowableArray<T> growableArra
/// </summary>
private unsafe void DispatchClonedEvent(TraceEvent toSend)
{
// Self describing metadata doesn't make it to realTimeSource because TraceLog overwrites the event's extended data.
// To address this, we use the event from the raw source, which contains the metadata,
// and convert it to a template that can be registered with realTimeSource.
realTimeSource.RegisterUnhandledEventImpl(te =>
{
if (toSend.containsSelfDescribingMetadata)
{
var template = toSend.CloneToTemplate();
realTimeSource.Dynamic.OnNewEventDefintion(template, true);
return true;
}
return false;
});
TraceEvent eventInRealTimeSource = realTimeSource.Lookup(toSend.eventRecord);
eventInRealTimeSource.userData = toSend.userData;
eventInRealTimeSource.eventIndex = toSend.eventIndex; // Lookup assigns the EventIndex, but we want to keep the original.
Expand Down Expand Up @@ -1115,6 +1128,12 @@ private unsafe void SetupCallbacks(TraceEventDispatcher rawEvents)
rawEvents.Clr.GCFinalizeObject += doNothing;
rawEvents.Clr.MethodJittingStarted += doNothing;

// This is required to ensure that self-describing metadata gets ingested before the event's extended data gets overwritten by the TraceLog.
if (IsRealTime)
{
rawEvents.Dynamic.All += doNothing;
}

//kernelParser.AddCallbackForEvents<PageFaultTraceData>(doNothing); // Lots of page fault ones
//kernelParser.AddCallbackForEvents<PageAccessTraceData>(doNothing);
//kernelParser.PerfInfoSysClEnter += doNothing;
Expand Down

0 comments on commit 541dfc2

Please sign in to comment.