summaryrefslogtreecommitdiff
path: root/src/mscorlib/shared/System/Diagnostics
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/shared/System/Diagnostics')
-rw-r--r--src/mscorlib/shared/System/Diagnostics/ConditionalAttribute.cs1
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Debug.Unix.cs95
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs135
-rwxr-xr-x[-rw-r--r--]src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs172
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/EventSourceException.cs4
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs42
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);
+ }
+}