diff options
Diffstat (limited to 'src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs')
-rwxr-xr-x[-rw-r--r--] | src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs | 172 |
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 |