diff options
Diffstat (limited to 'src/mscorlib/shared/System/Diagnostics')
6 files changed, 400 insertions, 49 deletions
diff --git a/src/mscorlib/shared/System/Diagnostics/ConditionalAttribute.cs b/src/mscorlib/shared/System/Diagnostics/ConditionalAttribute.cs index d5bca6e208..416625b779 100644 --- a/src/mscorlib/shared/System/Diagnostics/ConditionalAttribute.cs +++ b/src/mscorlib/shared/System/Diagnostics/ConditionalAttribute.cs @@ -4,7 +4,6 @@ namespace System.Diagnostics { - [Serializable] [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)] public sealed class ConditionalAttribute : Attribute { diff --git a/src/mscorlib/shared/System/Diagnostics/Debug.Unix.cs b/src/mscorlib/shared/System/Diagnostics/Debug.Unix.cs new file mode 100644 index 0000000000..495f2f713c --- /dev/null +++ b/src/mscorlib/shared/System/Diagnostics/Debug.Unix.cs @@ -0,0 +1,95 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32.SafeHandles; + +namespace System.Diagnostics +{ + public static partial class Debug + { + private static readonly bool s_shouldWriteToStdErr = Environment.GetEnvironmentVariable("COMPlus_DebugWriteToStdErr") == "1"; + + private static void ShowAssertDialog(string stackTrace, string message, string detailMessage) + { + if (Debugger.IsAttached) + { + Debugger.Break(); + } + else + { + // In Core, we do not show a dialog. + // Fail in order to avoid anyone catching an exception and masking + // an assert failure. + var ex = new DebugAssertException(message, detailMessage, stackTrace); + Environment.FailFast(ex.Message, ex); + } + } + + private static void WriteCore(string message) + { + WriteToDebugger(message); + + if (s_shouldWriteToStdErr) + { + WriteToStderr(message); + } + } + + private static void WriteToDebugger(string message) + { + if (Debugger.IsLogging()) + { + Debugger.Log(0, null, message); + } + else + { + Interop.Sys.SysLog(Interop.Sys.SysLogPriority.LOG_USER | Interop.Sys.SysLogPriority.LOG_DEBUG, "%s", message); + } + } + + private static void WriteToStderr(string message) + { + // We don't want to write UTF-16 to a file like standard error. Ideally we would transcode this + // to UTF8, but the downside of that is it pulls in a bunch of stuff into what is ideally + // a path with minimal dependencies (as to prevent re-entrency), so we'll take the strategy + // of just throwing away any non ASCII characters from the message and writing the rest + + const int BufferLength = 256; + + unsafe + { + byte* buf = stackalloc byte[BufferLength]; + int bufCount; + int i = 0; + + while (i < message.Length) + { + for (bufCount = 0; bufCount < BufferLength && i < message.Length; i++) + { + if (message[i] <= 0x7F) + { + buf[bufCount] = (byte)message[i]; + bufCount++; + } + } + + int totalBytesWritten = 0; + while (bufCount > 0) + { + int bytesWritten = Interop.Sys.Write(2 /* stderr */, buf + totalBytesWritten, bufCount); + if (bytesWritten < 0) + { + // On error, simply stop writing the debug output. This could commonly happen if stderr + // was piped to a program that ended before this program did, resulting in EPIPE errors. + return; + } + + bufCount -= bytesWritten; + totalBytesWritten += bytesWritten; + } + } + } + } + } +} diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs index e18574c1b4..5292551314 100644 --- a/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs +++ b/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs @@ -54,6 +54,7 @@ namespace System.Diagnostics.Tracing // subclasses of EventProvider use when creating efficient (but unsafe) version of // EventWrite. We do make it a nested type because we really don't expect anyone to use // it except subclasses (and then only rarely). + [StructLayout(LayoutKind.Sequential)] public struct EventData { internal unsafe ulong Ptr; @@ -78,6 +79,7 @@ namespace System.Diagnostics.Tracing private static bool m_setInformationMissing; + internal IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions. UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function private long m_regHandle; // Trace Registration Handle private byte m_level; // Tracing Level @@ -119,6 +121,13 @@ namespace System.Diagnostics.Tracing // EventSource has special logic to do this, no one else should be calling EventProvider. internal EventProvider() { +#if PLATFORM_WINDOWS + m_eventProvider = new EtwEventProvider(); +#elif FEATURE_PERFTRACING + m_eventProvider = new EventPipeEventProvider(); +#else + m_eventProvider = new NoOpEventProvider(); +#endif } /// <summary> @@ -429,7 +438,7 @@ namespace System.Diagnostics.Tracing // However the framework version of EventSource DOES have ES_SESSION_INFO defined and thus // does not have this issue. -#if ES_SESSION_INFO || !ES_BUILD_STANDALONE +#if (PLATFORM_WINDOWS && (ES_SESSION_INFO || !ES_BUILD_STANDALONE)) int buffSize = 256; // An initial guess that probably works most of the time. byte* buffer; for (; ; ) @@ -469,7 +478,7 @@ namespace System.Diagnostics.Tracing providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset]; } #else -#if !ES_BUILD_PCL && !FEATURE_PAL // TODO command arguments don't work on PCL builds... +#if !ES_BUILD_PCL && PLATFORM_WINDOWS // TODO command arguments don't work on PCL builds... // This code is only used in the Nuget Package Version of EventSource. because // the code above is using APIs baned from UWP apps. // @@ -553,7 +562,7 @@ namespace System.Diagnostics.Tracing dataStart = 0; if (filterData == null) { -#if (!ES_BUILD_PCL && !ES_BUILD_PN && !FEATURE_PAL) +#if (!ES_BUILD_PCL && !ES_BUILD_PN && PLATFORM_WINDOWS) string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}"; if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8) regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey; @@ -928,7 +937,7 @@ namespace System.Diagnostics.Tracing // </SecurityKernel> [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] - internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, params object[] eventPayload) + internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, params object[] eventPayload) { int status = 0; @@ -1056,7 +1065,7 @@ namespace System.Diagnostics.Tracing userDataPtr[refObjPosition[7]].Ptr = (ulong)v7; } - status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData); + status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData); } } else @@ -1082,7 +1091,7 @@ namespace System.Diagnostics.Tracing } } - status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData); + status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData); for (int i = 0; i < refObjIndex; ++i) { @@ -1124,7 +1133,7 @@ namespace System.Diagnostics.Tracing // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" /> // </SecurityKernel> [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] - internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data) + internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data) { if (childActivityID != null) { @@ -1135,7 +1144,7 @@ namespace System.Diagnostics.Tracing (EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop); } - int status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data); + int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data); if (status != 0) { @@ -1155,9 +1164,10 @@ namespace System.Diagnostics.Tracing { int status; - status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper( + status = m_eventProvider.EventWriteTransferWrapper( m_regHandle, ref eventDescriptor, + IntPtr.Zero, activityID, relatedActivityID, dataCount, @@ -1178,12 +1188,12 @@ namespace System.Diagnostics.Tracing { m_providerId = providerId; m_etwCallback = enableCallback; - return UnsafeNativeMethods.ManifestEtw.EventRegister(ref providerId, enableCallback, null, ref m_regHandle); + return m_eventProvider.EventRegister(ref providerId, enableCallback, null, ref m_regHandle); } private uint EventUnregister(long registrationHandle) { - return UnsafeNativeMethods.ManifestEtw.EventUnregister(registrationHandle); + return m_eventProvider.EventUnregister(registrationHandle); } static int[] nibblebits = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; @@ -1203,5 +1213,108 @@ namespace System.Diagnostics.Tracing return idx; } } + +#if PLATFORM_WINDOWS + + // A wrapper around the ETW-specific API calls. + internal sealed class EtwEventProvider : IEventProvider + { + // Register an event provider. + unsafe uint IEventProvider.EventRegister( + ref Guid providerId, + UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback, + void* callbackContext, + ref long registrationHandle) + { + return UnsafeNativeMethods.ManifestEtw.EventRegister( + ref providerId, + enableCallback, + callbackContext, + ref registrationHandle); + } + + // Unregister an event provider. + uint IEventProvider.EventUnregister(long registrationHandle) + { + return UnsafeNativeMethods.ManifestEtw.EventUnregister(registrationHandle); + } + + // Write an event. + unsafe int IEventProvider.EventWriteTransferWrapper( + long registrationHandle, + ref EventDescriptor eventDescriptor, + IntPtr eventHandle, + Guid* activityId, + Guid* relatedActivityId, + int userDataCount, + EventProvider.EventData* userData) + { + return UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper( + registrationHandle, + ref eventDescriptor, + activityId, + relatedActivityId, + userDataCount, + userData); + } + + // Get or set the per-thread activity ID. + int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId) + { + return UnsafeNativeMethods.ManifestEtw.EventActivityIdControl( + ControlCode, + ref ActivityId); + } + + // Define an EventPipeEvent handle. + unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength) + { + throw new System.NotSupportedException(); + } + } + +#elif !FEATURE_PERFTRACING + + internal sealed class NoOpEventProvider : IEventProvider + { + unsafe uint IEventProvider.EventRegister( + ref Guid providerId, + UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback, + void* callbackContext, + ref long registrationHandle) + { + return 0; + } + + uint IEventProvider.EventUnregister(long registrationHandle) + { + return 0; + } + + unsafe int IEventProvider.EventWriteTransferWrapper( + long registrationHandle, + ref EventDescriptor eventDescriptor, + IntPtr eventHandle, + Guid* activityId, + Guid* relatedActivityId, + int userDataCount, + EventProvider.EventData* userData) + { + return 0; + } + + int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId) + { + return 0; + } + + // Define an EventPipeEvent handle. + unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength) + { + throw new System.NotSupportedException(); + } + } + +#endif } 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 diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSourceException.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSourceException.cs index 88b8da93cd..73e32aaf53 100644 --- a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSourceException.cs +++ b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSourceException.cs @@ -18,9 +18,9 @@ namespace System.Diagnostics.Tracing /// <summary> /// Exception that is thrown when an error occurs during EventSource operation. /// </summary> -#if !ES_BUILD_PCL +#if !CORECLR && !ES_BUILD_PN && !ES_BUILD_PCL && !CORERT [Serializable] -#endif +#endif // !CORECLR && !ES_BUILD_PN && !ES_BUILD_PCL && !CORERT public class EventSourceException : Exception { /// <summary> diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs new file mode 100644 index 0000000000..71a2fe4d44 --- /dev/null +++ b/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32; + +#if ES_BUILD_STANDALONE +namespace Microsoft.Diagnostics.Tracing +#else +namespace System.Diagnostics.Tracing +#endif +{ + // Represents the interface between EventProvider and an external logging mechanism. + internal interface IEventProvider + { + // Register an event provider. + unsafe uint EventRegister( + ref Guid providerId, + UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback, + void* callbackContext, + ref long registrationHandle); + + // Unregister an event provider. + uint EventUnregister(long registrationHandle); + + // Write an event. + unsafe int EventWriteTransferWrapper( + long registrationHandle, + ref EventDescriptor eventDescriptor, + IntPtr eventHandle, + Guid* activityId, + Guid* relatedActivityId, + int userDataCount, + EventProvider.EventData* userData); + + // Get or set the per-thread activity ID. + int EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId); + + // Define an EventPipeEvent handle. + unsafe IntPtr DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength); + } +} |