Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit a7fae64

Browse files
Xiangyang (Mark) Guobrianrob
authored andcommitted
Write EventSource events with metadata to EventPipe (#11577)
* Fix EventPipe initialization. * rebase code with master, add prototype of event source metadata * fix define event * add null ptr checking * move WriteEvent metadata serialization to managed side * Fix enabled keywords for COMPlus_PerformanceTracing=1. * put parameter name into metadata, use WriteToBuffer * Write event metadata to the file. * allocate buffer in EventPipeEvent ctor * prevent double free * refactor code * AddEvent params reorder
1 parent 37168ae commit a7fae64

File tree

16 files changed

+286
-43
lines changed

16 files changed

+286
-43
lines changed

src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ internal partial class EventProvider : IDisposable
5454
// subclasses of EventProvider use when creating efficient (but unsafe) version of
5555
// EventWrite. We do make it a nested type because we really don't expect anyone to use
5656
// it except subclasses (and then only rarely).
57+
[StructLayout(LayoutKind.Sequential)]
5758
public struct EventData
5859
{
5960
internal unsafe ulong Ptr;
@@ -78,7 +79,7 @@ internal SessionInfo(int sessionIdBit_, int etwSessionId_)
7879

7980
private static bool m_setInformationMissing;
8081

81-
private IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions.
82+
internal IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions.
8283
UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
8384
private long m_regHandle; // Trace Registration Handle
8485
private byte m_level; // Tracing Level
@@ -936,7 +937,7 @@ to fill the passed in ETW data descriptor.
936937
// </SecurityKernel>
937938
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
938939
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
939-
internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
940+
internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
940941
{
941942
int status = 0;
942943

@@ -1064,7 +1065,7 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activ
10641065
userDataPtr[refObjPosition[7]].Ptr = (ulong)v7;
10651066
}
10661067

1067-
status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
1068+
status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
10681069
}
10691070
}
10701071
else
@@ -1090,7 +1091,7 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activ
10901091
}
10911092
}
10921093

1093-
status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
1094+
status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
10941095

10951096
for (int i = 0; i < refObjIndex; ++i)
10961097
{
@@ -1132,7 +1133,7 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activ
11321133
// <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
11331134
// </SecurityKernel>
11341135
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
1135-
internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
1136+
internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
11361137
{
11371138
if (childActivityID != null)
11381139
{
@@ -1143,7 +1144,7 @@ internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, G
11431144
(EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
11441145
}
11451146

1146-
int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data);
1147+
int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data);
11471148

11481149
if (status != 0)
11491150
{
@@ -1166,6 +1167,7 @@ internal unsafe bool WriteEventRaw(
11661167
status = m_eventProvider.EventWriteTransferWrapper(
11671168
m_regHandle,
11681169
ref eventDescriptor,
1170+
IntPtr.Zero,
11691171
activityID,
11701172
relatedActivityID,
11711173
dataCount,
@@ -1241,6 +1243,7 @@ uint IEventProvider.EventUnregister(long registrationHandle)
12411243
unsafe int IEventProvider.EventWriteTransferWrapper(
12421244
long registrationHandle,
12431245
ref EventDescriptor eventDescriptor,
1246+
IntPtr eventHandle,
12441247
Guid* activityId,
12451248
Guid* relatedActivityId,
12461249
int userDataCount,
@@ -1262,6 +1265,12 @@ int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.Activi
12621265
ControlCode,
12631266
ref ActivityId);
12641267
}
1268+
1269+
// Define an EventPipeEvent handle.
1270+
unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
1271+
{
1272+
throw new System.NotSupportedException();
1273+
}
12651274
}
12661275

12671276
#elif !FEATURE_PERFTRACING
@@ -1285,6 +1294,7 @@ uint IEventProvider.EventUnregister(long registrationHandle)
12851294
unsafe int IEventProvider.EventWriteTransferWrapper(
12861295
long registrationHandle,
12871296
ref EventDescriptor eventDescriptor,
1297+
IntPtr eventHandle,
12881298
Guid* activityId,
12891299
Guid* relatedActivityId,
12901300
int userDataCount,
@@ -1297,6 +1307,12 @@ int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.Activi
12971307
{
12981308
return 0;
12991309
}
1310+
1311+
// Define an EventPipeEvent handle.
1312+
unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
1313+
{
1314+
throw new System.NotSupportedException();
1315+
}
13001316
}
13011317

13021318
#endif

src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs

Lines changed: 118 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,106 @@ protected EventSource(EventSourceSettings settings, params string[] traits)
686686
Initialize(eventSourceGuid, eventSourceName, traits);
687687
}
688688

689+
#if FEATURE_PERFTRACING
690+
// Generate the serialized blobs that describe events for all strongly typed events (that is events that define strongly
691+
// typed event methods. Dynamically defined events (that use Write) hare defined on the fly and are handled elsewhere.
692+
private unsafe void DefineEventPipeEvents()
693+
{
694+
Debug.Assert(m_eventData != null);
695+
Debug.Assert(m_provider != null);
696+
int cnt = m_eventData.Length;
697+
for (int i = 0; i < cnt; i++)
698+
{
699+
uint eventID = (uint)m_eventData[i].Descriptor.EventId;
700+
if (eventID == 0)
701+
continue;
702+
703+
string eventName = m_eventData[i].Name;
704+
Int64 keywords = m_eventData[i].Descriptor.Keywords;
705+
uint eventVersion = m_eventData[i].Descriptor.Version;
706+
uint level = m_eventData[i].Descriptor.Level;
707+
708+
// evnetID : 4 bytes
709+
// eventName : (eventName.Length + 1) * 2 bytes
710+
// keywords : 8 bytes
711+
// eventVersion : 4 bytes
712+
// level : 4 bytes
713+
// parameterCount : 4 bytes
714+
uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;
715+
716+
// Increase the metadataLength for the types of all parameters.
717+
metadataLength += (uint)m_eventData[i].Parameters.Length * 4;
718+
719+
// Increase the metadataLength for the names of all parameters.
720+
foreach (var parameter in m_eventData[i].Parameters)
721+
{
722+
string parameterName = parameter.Name;
723+
metadataLength = metadataLength + ((uint)parameterName.Length + 1) * 2;
724+
}
725+
726+
byte[] metadata = new byte[metadataLength];
727+
728+
// Write metadata: evnetID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
729+
fixed (byte *pMetadata = metadata)
730+
{
731+
uint offset = 0;
732+
WriteToBuffer(pMetadata, metadataLength, ref offset, eventID);
733+
fixed(char *pEventName = eventName)
734+
{
735+
WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pEventName, ((uint)eventName.Length + 1) * 2);
736+
}
737+
WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
738+
WriteToBuffer(pMetadata, metadataLength, ref offset, eventVersion);
739+
WriteToBuffer(pMetadata, metadataLength, ref offset, level);
740+
WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)m_eventData[i].Parameters.Length);
741+
foreach (var parameter in m_eventData[i].Parameters)
742+
{
743+
// Write parameter type.
744+
WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)Type.GetTypeCode(parameter.ParameterType));
745+
746+
// Write parameter name.
747+
string parameterName = parameter.Name;
748+
fixed (char *pParameterName = parameterName)
749+
{
750+
WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pParameterName, ((uint)parameterName.Length + 1) * 2);
751+
}
752+
}
753+
Debug.Assert(metadataLength == offset);
754+
IntPtr eventHandle = m_provider.m_eventProvider.DefineEventHandle(eventID, eventName, keywords, eventVersion, level, pMetadata, metadataLength);
755+
m_eventData[i].EventHandle = eventHandle;
756+
}
757+
}
758+
}
759+
760+
// Copy src to buffer and modify the offset.
761+
// Note: We know the buffer size ahead of time to make sure no buffer overflow.
762+
private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, byte *src, uint srcLength)
763+
{
764+
Debug.Assert(bufferLength >= (offset + srcLength));
765+
for (int i = 0; i < srcLength; i++)
766+
{
767+
*(byte *)(buffer + offset + i) = *(byte *)(src + i);
768+
}
769+
offset += srcLength;
770+
}
771+
772+
// Copy uint value to buffer.
773+
private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, uint value)
774+
{
775+
Debug.Assert(bufferLength >= (offset + 4));
776+
*(uint *)(buffer + offset) = value;
777+
offset += 4;
778+
}
779+
780+
// Copy long value to buffer.
781+
private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, long value)
782+
{
783+
Debug.Assert(bufferLength >= (offset + 8));
784+
*(long *)(buffer + offset) = value;
785+
offset += 8;
786+
}
787+
#endif
788+
689789
internal virtual void GetMetadata(out Guid eventSourceGuid, out string eventSourceName, out EventMetadata[] eventData, out byte[] manifestBytes)
690790
{
691791
//
@@ -1179,7 +1279,7 @@ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* rel
11791279
// by default the Descriptor.Keyword will have the perEventSourceSessionId bit
11801280
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
11811281
// synthesize a new one
1182-
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
1282+
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
11831283
ThrowEventSourceException(m_eventData[eventId].Name);
11841284
}
11851285
else
@@ -1199,7 +1299,7 @@ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* rel
11991299
m_eventData[eventId].Descriptor.Task,
12001300
unchecked((long)etwSessions.ToEventKeywords() | origKwd));
12011301

1202-
if (!m_provider.WriteEvent(ref desc, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
1302+
if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
12031303
ThrowEventSourceException(m_eventData[eventId].Name);
12041304
}
12051305
}
@@ -1229,7 +1329,7 @@ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* rel
12291329
#else
12301330
if (!SelfDescribingEvents)
12311331
{
1232-
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
1332+
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
12331333
ThrowEventSourceException(m_eventData[eventId].Name);
12341334
}
12351335
else
@@ -1489,7 +1589,6 @@ private unsafe void Initialize(Guid eventSourceGuid, string eventSourceName, str
14891589
}
14901590
#endif // PLATFORM_WINDOWS
14911591
#endif // FEATURE_MANAGED_ETW
1492-
14931592
Debug.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted.
14941593
// We are logically completely initialized at this point.
14951594
m_completelyInited = true;
@@ -1941,7 +2040,7 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object
19412040
// by default the Descriptor.Keyword will have the perEventSourceSessionId bit
19422041
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
19432042
// synthesize a new one
1944-
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
2043+
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
19452044
ThrowEventSourceException(m_eventData[eventId].Name);
19462045
}
19472046
else
@@ -1958,7 +2057,7 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object
19582057
m_eventData[eventId].Descriptor.Task,
19592058
unchecked((long)etwSessions.ToEventKeywords() | origKwd));
19602059

1961-
if (!m_provider.WriteEvent(ref desc, pActivityId, childActivityID, args))
2060+
if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
19622061
ThrowEventSourceException(m_eventData[eventId].Name);
19632062
}
19642063
}
@@ -1988,7 +2087,7 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object
19882087
#else
19892088
if (!SelfDescribingEvents)
19902089
{
1991-
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
2090+
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
19922091
ThrowEventSourceException(m_eventData[eventId].Name);
19932092
}
19942093
else
@@ -2232,7 +2331,7 @@ private unsafe void WriteEventString(EventLevel level, long keywords, string msg
22322331
data.Ptr = (ulong)msgStringPtr;
22332332
data.Size = (uint)(2 * (msgString.Length + 1));
22342333
data.Reserved = 0;
2235-
m_provider.WriteEvent(ref descr, null, null, 1, (IntPtr)((void*)&data));
2334+
m_provider.WriteEvent(ref descr, m_eventData[0].EventHandle, null, null, 1, (IntPtr)((void*)&data));
22362335
}
22372336
}
22382337
}
@@ -2517,6 +2616,7 @@ root them and modify shared library definition to force export them.
25172616
partial struct EventMetadata
25182617
{
25192618
public EventDescriptor Descriptor;
2619+
public IntPtr EventHandle; // EventPipeEvent handle.
25202620
public EventTags Tags;
25212621
public bool EnabledForAnyListener; // true if any dispatcher has this event turned on
25222622
public bool EnabledForETW; // is this event on for the OS ETW data dispatcher?
@@ -3065,6 +3165,10 @@ private void EnsureDescriptorsInitialized()
30653165
dispatcher.m_EventEnabled = new bool[m_eventData.Length];
30663166
dispatcher = dispatcher.m_Next;
30673167
}
3168+
#if FEATURE_PERFTRACING
3169+
// Initialize the EventPipe event handles.
3170+
DefineEventPipeEvents();
3171+
#endif
30683172
}
30693173
if (s_currentPid == 0)
30703174
{
@@ -3119,7 +3223,7 @@ private unsafe bool SendManifest(byte[] rawManifest)
31193223
dataDescrs[1].Size = (uint)Math.Min(dataLeft, chunkSize);
31203224
if (m_provider != null)
31213225
{
3122-
if (!m_provider.WriteEvent(ref manifestDescr, null, null, 2, (IntPtr)dataDescrs))
3226+
if (!m_provider.WriteEvent(ref manifestDescr, IntPtr.Zero, null, null, 2, (IntPtr)dataDescrs))
31233227
{
31243228
// Turns out that if users set the BufferSize to something less than 64K then WriteEvent
31253229
// can fail. If we get this failure on the first chunk try again with something smaller
@@ -3597,7 +3701,11 @@ private static byte[] CreateManifestAndDescriptors(Type eventSourceType, string
35973701
throw new ArgumentException(msg, exception);
35983702
}
35993703

3704+
#if FEATURE_PERFTRACING
3705+
return null;
3706+
#else
36003707
return bNeedsManifest ? res : null;
3708+
#endif
36013709
}
36023710

36033711
private static bool RemoveFirstArgIfRelatedActivityId(ref ParameterInfo[] args)
@@ -3686,6 +3794,7 @@ private static void AddEventDescriptor(ref EventMetadata[] eventData, string eve
36863794
eventData[eventAttribute.EventId].Message = eventAttribute.Message;
36873795
eventData[eventAttribute.EventId].ActivityOptions = eventAttribute.ActivityOptions;
36883796
eventData[eventAttribute.EventId].HasRelatedActivityID = hasRelatedActivityID;
3797+
eventData[eventAttribute.EventId].EventHandle = IntPtr.Zero;
36893798
}
36903799

36913800
// Helper used by code:CreateManifestAndDescriptors that trims the m_eventData array to the correct

0 commit comments

Comments
 (0)