summaryrefslogtreecommitdiff
path: root/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs')
-rwxr-xr-x[-rw-r--r--]src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs172
1 files changed, 137 insertions, 35 deletions
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
index cf4901de6f..3349c069c6 100644..100755
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
@@ -4,16 +4,10 @@
// This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in.
// It is available from http://www.codeplex.com/hyperAddin
-#if PLATFORM_WINDOWS
-
-#define FEATURE_MANAGED_ETW
-
-#if !ES_BUILD_STANDALONE && !CORECLR && !ES_BUILD_PN
+#if PLATFORM_WINDOWS && !ES_BUILD_STANDALONE && !CORECLR && !ES_BUILD_PN
#define FEATURE_ACTIVITYSAMPLING
#endif // !ES_BUILD_STANDALONE
-#endif // PLATFORM_WINDOWS
-
#if ES_BUILD_STANDALONE
#define FEATURE_MANAGED_ETW_CHANNELS
// #define FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
@@ -692,6 +686,106 @@ namespace System.Diagnostics.Tracing
Initialize(eventSourceGuid, eventSourceName, traits);
}
+#if FEATURE_PERFTRACING
+ // Generate the serialized blobs that describe events for all strongly typed events (that is events that define strongly
+ // typed event methods. Dynamically defined events (that use Write) hare defined on the fly and are handled elsewhere.
+ private unsafe void DefineEventPipeEvents()
+ {
+ Debug.Assert(m_eventData != null);
+ Debug.Assert(m_provider != null);
+ int cnt = m_eventData.Length;
+ for (int i = 0; i < cnt; i++)
+ {
+ uint eventID = (uint)m_eventData[i].Descriptor.EventId;
+ if (eventID == 0)
+ continue;
+
+ string eventName = m_eventData[i].Name;
+ Int64 keywords = m_eventData[i].Descriptor.Keywords;
+ uint eventVersion = m_eventData[i].Descriptor.Version;
+ uint level = m_eventData[i].Descriptor.Level;
+
+ // evnetID : 4 bytes
+ // eventName : (eventName.Length + 1) * 2 bytes
+ // keywords : 8 bytes
+ // eventVersion : 4 bytes
+ // level : 4 bytes
+ // parameterCount : 4 bytes
+ uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;
+
+ // Increase the metadataLength for the types of all parameters.
+ metadataLength += (uint)m_eventData[i].Parameters.Length * 4;
+
+ // Increase the metadataLength for the names of all parameters.
+ foreach (var parameter in m_eventData[i].Parameters)
+ {
+ string parameterName = parameter.Name;
+ metadataLength = metadataLength + ((uint)parameterName.Length + 1) * 2;
+ }
+
+ byte[] metadata = new byte[metadataLength];
+
+ // Write metadata: evnetID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
+ fixed (byte *pMetadata = metadata)
+ {
+ uint offset = 0;
+ WriteToBuffer(pMetadata, metadataLength, ref offset, eventID);
+ fixed(char *pEventName = eventName)
+ {
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pEventName, ((uint)eventName.Length + 1) * 2);
+ }
+ WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, eventVersion);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, level);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)m_eventData[i].Parameters.Length);
+ foreach (var parameter in m_eventData[i].Parameters)
+ {
+ // Write parameter type.
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)Type.GetTypeCode(parameter.ParameterType));
+
+ // Write parameter name.
+ string parameterName = parameter.Name;
+ fixed (char *pParameterName = parameterName)
+ {
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pParameterName, ((uint)parameterName.Length + 1) * 2);
+ }
+ }
+ Debug.Assert(metadataLength == offset);
+ IntPtr eventHandle = m_provider.m_eventProvider.DefineEventHandle(eventID, eventName, keywords, eventVersion, level, pMetadata, metadataLength);
+ m_eventData[i].EventHandle = eventHandle;
+ }
+ }
+ }
+
+ // Copy src to buffer and modify the offset.
+ // Note: We know the buffer size ahead of time to make sure no buffer overflow.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, byte *src, uint srcLength)
+ {
+ Debug.Assert(bufferLength >= (offset + srcLength));
+ for (int i = 0; i < srcLength; i++)
+ {
+ *(byte *)(buffer + offset + i) = *(byte *)(src + i);
+ }
+ offset += srcLength;
+ }
+
+ // Copy uint value to buffer.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, uint value)
+ {
+ Debug.Assert(bufferLength >= (offset + 4));
+ *(uint *)(buffer + offset) = value;
+ offset += 4;
+ }
+
+ // Copy long value to buffer.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, long value)
+ {
+ Debug.Assert(bufferLength >= (offset + 8));
+ *(long *)(buffer + offset) = value;
+ offset += 8;
+ }
+#endif
+
internal virtual void GetMetadata(out Guid eventSourceGuid, out string eventSourceName, out EventMetadata[] eventData, out byte[] manifestBytes)
{
//
@@ -1185,7 +1279,7 @@ namespace System.Diagnostics.Tracing
// by default the Descriptor.Keyword will have the perEventSourceSessionId bit
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
// synthesize a new one
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
@@ -1205,7 +1299,7 @@ namespace System.Diagnostics.Tracing
m_eventData[eventId].Descriptor.Task,
unchecked((long)etwSessions.ToEventKeywords() | origKwd));
- if (!m_provider.WriteEvent(ref desc, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
}
}
@@ -1235,7 +1329,7 @@ namespace System.Diagnostics.Tracing
#else
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
@@ -1328,6 +1422,7 @@ namespace System.Diagnostics.Tracing
if (disposing)
{
#if FEATURE_MANAGED_ETW
+#if !FEATURE_PERFTRACING
// Send the manifest one more time to ensure circular buffers have a chance to get to this information
// even in scenarios with a high volume of ETW events.
if (m_eventSourceEnabled)
@@ -1340,6 +1435,7 @@ namespace System.Diagnostics.Tracing
{ } // If it fails, simply give up.
m_eventSourceEnabled = false;
}
+#endif
if (m_provider != null)
{
m_provider.Dispose();
@@ -1474,6 +1570,7 @@ namespace System.Diagnostics.Tracing
// Set m_provider, which allows this.
m_provider = provider;
+#if PLATFORM_WINDOWS
#if (!ES_BUILD_STANDALONE && !ES_BUILD_PN)
// API available on OS >= Win 8 and patched Win 7.
// Disable only for FrameworkEventSource to avoid recursion inside exception handling.
@@ -1492,8 +1589,8 @@ namespace System.Diagnostics.Tracing
metadataHandle.Free();
}
+#endif // PLATFORM_WINDOWS
#endif // FEATURE_MANAGED_ETW
-
Debug.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted.
// We are logically completely initialized at this point.
m_completelyInited = true;
@@ -1945,7 +2042,7 @@ namespace System.Diagnostics.Tracing
// by default the Descriptor.Keyword will have the perEventSourceSessionId bit
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
// synthesize a new one
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
@@ -1962,7 +2059,7 @@ namespace System.Diagnostics.Tracing
m_eventData[eventId].Descriptor.Task,
unchecked((long)etwSessions.ToEventKeywords() | origKwd));
- if (!m_provider.WriteEvent(ref desc, pActivityId, childActivityID, args))
+ if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
}
}
@@ -1992,7 +2089,7 @@ namespace System.Diagnostics.Tracing
#else
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
@@ -2102,32 +2199,26 @@ namespace System.Diagnostics.Tracing
#endif //!ES_BUILD_PCL
}
- private int GetParamLenghtIncludingByteArray(ParameterInfo[] parameters)
+ unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
{
- int sum = 0;
- foreach (ParameterInfo info in parameters)
+ // We represent a byte[] as a integer denoting the length and then a blob of bytes in the data pointer. This causes a spurious
+ // warning because eventDataCount is off by one for the byte[] case since a byte[] has 2 items associated it. So we want to check
+ // that the number of parameters is correct against the byte[] case, but also we the args array would be one too long if
+ // we just used the modifiedParamCount here -- so we need both.
+ int paramCount = GetParameterCount(m_eventData[eventId]);
+ int modifiedParamCount = 0;
+ for (int i = 0; i < paramCount; i++)
{
- if (info.ParameterType == typeof(byte[]))
+ Type parameterType = GetDataType(m_eventData[eventId], i);
+ if (parameterType == typeof(byte[]))
{
- sum += 2;
+ modifiedParamCount += 2;
}
else
{
- sum++;
+ modifiedParamCount++;
}
}
-
- return sum;
- }
-
- unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
- {
- // We represent a byte[] as a integer denoting the length and then a blob of bytes in the data pointer. This causes a spurious
- // warning because eventDataCount is off by one for the byte[] case since a byte[] has 2 items associated it. So we want to check
- // that the number of parameters is correct against the byte[] case, but also we the args array would be one too long if
- // we just used the modifiedParamCount here -- so we need both.
- int paramCount = m_eventData[eventId].Parameters.Length;
- int modifiedParamCount = GetParamLenghtIncludingByteArray(m_eventData[eventId].Parameters);
if (eventDataCount != modifiedParamCount)
{
ReportOutOfBandMessage(Resources.GetResourceString("EventSource_EventParametersMismatch", eventId, eventDataCount, paramCount), true);
@@ -2200,7 +2291,7 @@ namespace System.Diagnostics.Tracing
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
private unsafe void WriteEventString(EventLevel level, long keywords, string msgString)
{
-#if FEATURE_MANAGED_ETW
+#if FEATURE_MANAGED_ETW && !FEATURE_PERFTRACING
if (m_provider != null)
{
string eventName = "EventSourceMessage";
@@ -2236,7 +2327,7 @@ namespace System.Diagnostics.Tracing
data.Ptr = (ulong)msgStringPtr;
data.Size = (uint)(2 * (msgString.Length + 1));
data.Reserved = 0;
- m_provider.WriteEvent(ref descr, null, null, 1, (IntPtr)((void*)&data));
+ m_provider.WriteEvent(ref descr, IntPtr.Zero, null, null, 1, (IntPtr)((void*)&data));
}
}
}
@@ -2521,6 +2612,7 @@ namespace System.Diagnostics.Tracing
partial struct EventMetadata
{
public EventDescriptor Descriptor;
+ public IntPtr EventHandle; // EventPipeEvent handle.
public EventTags Tags;
public bool EnabledForAnyListener; // true if any dispatcher has this event turned on
public bool EnabledForETW; // is this event on for the OS ETW data dispatcher?
@@ -2683,11 +2775,13 @@ namespace System.Diagnostics.Tracing
{
// eventSourceDispatcher == null means this is the ETW manifest
+#if !FEATURE_PERFTRACING
// Note that we unconditionally send the manifest whenever we are enabled, even if
// we were already enabled. This is because there may be multiple sessions active
// and we can't know that all the sessions have seen the manifest.
if (!SelfDescribingEvents)
SendManifest(m_rawManifest);
+#endif
}
#if FEATURE_ACTIVITYSAMPLING
@@ -2811,12 +2905,14 @@ namespace System.Diagnostics.Tracing
}
else
{
+#if !FEATURE_PERFTRACING
if (commandArgs.Command == EventCommand.SendManifest)
{
// TODO: should we generate the manifest here if we hadn't already?
if (m_rawManifest != null)
SendManifest(m_rawManifest);
}
+#endif
// These are not used for non-update commands and thus should always be 'default' values
// Debug.Assert(enable == true);
@@ -3036,6 +3132,7 @@ namespace System.Diagnostics.Tracing
{
// GetMetadata failed, so we have to set it via reflection.
Debug.Assert(m_rawManifest == null);
+
m_rawManifest = CreateManifestAndDescriptors(this.GetType(), Name, this);
Debug.Assert(m_eventData != null);
@@ -3069,6 +3166,10 @@ namespace System.Diagnostics.Tracing
dispatcher.m_EventEnabled = new bool[m_eventData.Length];
dispatcher = dispatcher.m_Next;
}
+#if FEATURE_PERFTRACING
+ // Initialize the EventPipe event handles.
+ DefineEventPipeEvents();
+#endif
}
if (s_currentPid == 0)
{
@@ -3123,7 +3224,7 @@ namespace System.Diagnostics.Tracing
dataDescrs[1].Size = (uint)Math.Min(dataLeft, chunkSize);
if (m_provider != null)
{
- if (!m_provider.WriteEvent(ref manifestDescr, null, null, 2, (IntPtr)dataDescrs))
+ if (!m_provider.WriteEvent(ref manifestDescr, IntPtr.Zero, null, null, 2, (IntPtr)dataDescrs))
{
// Turns out that if users set the BufferSize to something less than 64K then WriteEvent
// can fail. If we get this failure on the first chunk try again with something smaller
@@ -3690,6 +3791,7 @@ namespace System.Diagnostics.Tracing
eventData[eventAttribute.EventId].Message = eventAttribute.Message;
eventData[eventAttribute.EventId].ActivityOptions = eventAttribute.ActivityOptions;
eventData[eventAttribute.EventId].HasRelatedActivityID = hasRelatedActivityID;
+ eventData[eventAttribute.EventId].EventHandle = IntPtr.Zero;
}
// Helper used by code:CreateManifestAndDescriptors that trims the m_eventData array to the correct