Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Classic ETW providers in NetPerf #1259

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
65 changes: 63 additions & 2 deletions src/TraceEvent/EventPipe/EventPipeEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.Diagnostics.Tracing.EventPipe;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Parsers.Clr;
using Microsoft.Diagnostics.Tracing.Parsers.Kernel;
using Microsoft.Diagnostics.Tracing.Session;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -30,6 +31,39 @@ public unsafe class EventPipeEventSource : TraceEventDispatcher, IFastSerializab
{
public EventPipeEventSource(string fileName) : this(new PinnedStreamReader(fileName, 0x20000), fileName)
{
// NOTE: Copied from ETWTraceEventSource.cs

var kernelParser = new KernelTraceEventParser(this, KernelTraceEventParser.ParserTrackingOptions.None);

kernelParser.ProcessStartGroup += delegate (ProcessTraceData data)
{
// Get just the file name without the extension. Can't use the 'Path' class because
// it tests to make certain it does not have illegal chars etc. Since KernelImageFileName
// is not a true user mode path, we can get failures.
string path = data.KernelImageFileName;
int startIdx = path.LastIndexOf('\\');
if (0 <= startIdx)
{
startIdx++;
}
else
{
startIdx = 0;
}

int endIdx = path.LastIndexOf('.');
if (endIdx <= startIdx)
{
endIdx = path.Length;
}

_processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
};

kernelParser.ProcessEndGroup += delegate (ProcessTraceData data)
{
_processNameForID.Remove(data.ProcessID);
};
}

public EventPipeEventSource(Stream stream) : this(new PinnedStreamReader(stream), "stream")
Expand Down Expand Up @@ -162,7 +196,7 @@ public override bool Process()
internal EventCache EventCache { get; private set; }
internal StackCache StackCache { get; private set; }

internal override string ProcessName(int processID, long timeQPC) => string.Format("Process({0})", processID);
internal override string ProcessName(int processID, long timeQPC) => _processNameForID.TryGetValue(processID, out var retVal) ? retVal : $"Process({processID})";

internal void ReadAndDispatchEvent(PinnedStreamReader reader, bool useHeaderCompression)
{
Expand All @@ -179,6 +213,12 @@ internal void DispatchEventRecord(TraceEventNativeMethods.EVENT_RECORD* eventRec
Debug.Assert(sessionEndTimeQPC == 0 || eventRecord->EventHeader.TimeStamp - sessionEndTimeQPC < _QPCFreq * 24 * 3600);

var traceEvent = Lookup(eventRecord);

if (traceEvent.NeedsFixup)
{
traceEvent.FixupData();
}

Dispatch(traceEvent);
sessionEndTimeQPC = eventRecord->EventHeader.TimeStamp;
}
Expand Down Expand Up @@ -288,6 +328,12 @@ void ReadEventHeader(byte* headerPtr, bool useHeaderCompression, ref EventPipeEv
metaDataHeader.Opcode = reader.ReadByte();
SetOpcode(eventTemplate, metaDataHeader.Opcode);
}
else if (tag == EventPipeMetadataTag.WindowsClassicEventProviderGuid)
{
Debug.Assert(tagLength == 16);
metaDataHeader.SetClassicProviderGuid(reader.ReadGuid());
SetClassicProviderId(eventTemplate, metaDataHeader.ProviderId);
}

// Skip any remaining bytes or unknown tags
reader.Goto(tagEndLabel);
Expand Down Expand Up @@ -470,6 +516,12 @@ private void ParseEventParameters(DynamicTraceEventData template, EventPipeEvent
return;
}

private void SetClassicProviderId(DynamicTraceEventData template, in Guid guid)
{
template.taskGuid = guid;
template.lookupAsClassic = true;
}

private void SetOpcode(DynamicTraceEventData template, int opcode)
{
template.opcode = (TraceEventOpcode)opcode;
Expand Down Expand Up @@ -825,6 +877,7 @@ private static void GetOpcodeFromEventName(string eventName, out int opcode, out
#if SUPPORT_V1_V2
private StreamLabel _endOfEventStream;
#endif
private Dictionary<int, string> _processNameForID = new Dictionary<int, string>();
private Dictionary<int, EventPipeEventMetaDataHeader> _eventMetadataDictionary = new Dictionary<int, EventPipeEventMetaDataHeader>();
private Deserializer _deserializer;
private Dictionary<TraceEvent, DynamicTraceEventData> _metadataTemplates =
Expand Down Expand Up @@ -996,7 +1049,8 @@ internal enum NetTraceFieldLayoutVersion
internal enum EventPipeMetadataTag
{
Opcode = 1,
ParameterPayloadV2 = 2
ParameterPayloadV2 = 2,
WindowsClassicEventProviderGuid = 3
}

/// <summary>
Expand Down Expand Up @@ -1161,6 +1215,13 @@ public EventPipeEventMetaDataHeader(PinnedStreamReader reader, int length, Event
return _eventRecord;
}

internal void SetClassicProviderGuid(in Guid providerId)
{
_eventRecord->EventHeader.Flags |= TraceEventNativeMethods.EVENT_HEADER_FLAG_CLASSIC_HEADER;
_eventRecord->EventHeader.Id = 0;
_eventRecord->EventHeader.ProviderId = providerId;
}

/// <summary>
/// This is a number that is unique to this meta-data blob. It is expected to be a small integer
/// that starts at 1 (since 0 is reserved) and increases from there (thus an array can be used).
Expand Down