File: system\diagnostics\eventing\frameworkeventsource.cs
Project: ndp\clr\src\bcl\mscorlib.csproj (mscorlib)
// ==++==
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
//
// ResourcesEtwProvider.cs
//
// <OWNER>Microsoft</OWNER>
// <OWNER>Microsoft</OWNER>
//
// Managed event source for things that can version with MSCORLIB.  
//
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Text;
using System.Runtime.CompilerServices;
 
namespace System.Diagnostics.Tracing {
 
    // To use the framework provider
    // 
    //     \\clrmain\tools\Perfmonitor /nokernel /noclr /provider:8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1 start
    //     Run run your app
    //     \\clrmain\tools\Perfmonitor stop
    //     \\clrmain\tools\Perfmonitor print
    //
    // This will produce an XML file, where each event is pretty-printed with all its arguments nicely parsed.
    //
    [FriendAccessAllowed]
    [EventSource(Guid = "8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1", Name = "System.Diagnostics.Eventing.FrameworkEventSource")]
    sealed internal class FrameworkEventSource : EventSource {
        // Defines the singleton instance for the Resources ETW provider
        public static readonly FrameworkEventSource Log = new FrameworkEventSource();
 
        // Keyword definitions.  These represent logical groups of events that can be turned on and off independently
        // Often each task has a keyword, but where tasks are determined by subsystem, keywords are determined by
        // usefulness to end users to filter.  Generally users don't mind extra events if they are not high volume
        // so grouping low volume events together in a single keywords is OK (users can post-filter by task if desired)
        public static class Keywords {
            public const EventKeywords Loader     = (EventKeywords)0x0001; // This is bit 0
            public const EventKeywords ThreadPool = (EventKeywords)0x0002; 
            public const EventKeywords NetClient  = (EventKeywords)0x0004;
            //
            // This is a private event we do not want to expose to customers.  It is to be used for profiling
            // uses of dynamic type loading by ProjectN applications running on the desktop CLR
            //
            public const EventKeywords DynamicTypeUsage = (EventKeywords)0x0008;
            public const EventKeywords ThreadTransfer   = (EventKeywords)0x0010;
        }
 
        /// <summary>ETW tasks that have start/stop events.</summary>
        [FriendAccessAllowed]
        public static class Tasks // this name is important for EventSource
        {
            /// <summary>Begin / End - GetResponse.</summary>
            public const EventTask GetResponse      = (EventTask)1;
            /// <summary>Begin / End - GetRequestStream</summary>
            public const EventTask GetRequestStream = (EventTask)2;
            /// <summary>Send / Receive - begin transfer/end transfer</summary>
            public const EventTask ThreadTransfer = (EventTask)3;
        }
 
        [FriendAccessAllowed]
        public static class Opcodes
        {
            public const EventOpcode ReceiveHandled = (EventOpcode)11;
        }
 
        // This predicate is used by consumers of this class to deteremine if the class has actually been initialized,
        // and therefore if the public statics are available for use. This is typically not a problem... if the static
        // class constructor fails, then attempts to access the statics (or even this property) will result in a 
        // TypeInitializationException. However, that is not the case while the class loader is actually trying to construct
        // the TypeInitializationException instance to represent that failure, and some consumers of this class are on
        // that code path, specifically the resource manager. 
        public static bool IsInitialized
        {
            get
            {
                return Log != null;
            }
        }
 
        // The FrameworkEventSource GUID is {8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1}
        private FrameworkEventSource() : base(new Guid(0x8e9f5090, 0x2d75, 0x4d03, 0x8a, 0x81, 0xe5, 0xaf, 0xbf, 0x85, 0xda, 0xf1), "System.Diagnostics.Eventing.FrameworkEventSource") { }
 
        // WriteEvent overloads (to avoid the "params" EventSource.WriteEvent
 
        // optimized for common signatures (used by the ThreadTransferSend/Receive events)
        [NonEvent, System.Security.SecuritySafeCritical]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
        private unsafe void WriteEvent(int eventId, long arg1, int arg2, string arg3, bool arg4)
        {
            if (IsEnabled())
            {
                if (arg3 == null) arg3 = "";
                fixed (char* string3Bytes = arg3)
                {
                    EventSource.EventData* descrs = stackalloc EventSource.EventData[4];
                    descrs[0].DataPointer = (IntPtr)(&arg1);
                    descrs[0].Size = 8;
                    descrs[1].DataPointer = (IntPtr)(&arg2);
                    descrs[1].Size = 4;
                    descrs[2].DataPointer = (IntPtr)string3Bytes;
                    descrs[2].Size = ((arg3.Length + 1) * 2);
                    descrs[3].DataPointer = (IntPtr)(&arg4);
                    descrs[3].Size = 4;
                    WriteEventCore(eventId, 4, descrs);
                }
            }
        }
 
        // optimized for common signatures (used by the ThreadTransferSend/Receive events)
        [NonEvent, System.Security.SecuritySafeCritical]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
        private unsafe void WriteEvent(int eventId, long arg1, int arg2, string arg3)
        {
            if (IsEnabled())
            {
                if (arg3 == null) arg3 = "";
                fixed (char* string3Bytes = arg3)
                {
                    EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
                    descrs[0].DataPointer = (IntPtr)(&arg1);
                    descrs[0].Size = 8;
                    descrs[1].DataPointer = (IntPtr)(&arg2);
                    descrs[1].Size = 4;
                    descrs[2].DataPointer = (IntPtr)string3Bytes;
                    descrs[2].Size = ((arg3.Length + 1) * 2);
                    WriteEventCore(eventId, 3, descrs);
                }
            }
        }
 
        // optimized for common signatures (used by the BeginGetResponse/BeginGetRequestStream events)
        [NonEvent, System.Security.SecuritySafeCritical]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
        private unsafe void WriteEvent(int eventId, long arg1, string arg2, bool arg3, bool arg4)
        {
            if (IsEnabled())
            {
                if (arg2 == null) arg2 = "";
                fixed (char* string2Bytes = arg2)
                {
                    EventSource.EventData* descrs = stackalloc EventSource.EventData[4];
                    descrs[0].DataPointer = (IntPtr)(&arg1);
                    descrs[0].Size = 8;
                    descrs[1].DataPointer = (IntPtr)string2Bytes;
                    descrs[1].Size = ((arg2.Length + 1) * 2);
                    descrs[2].DataPointer = (IntPtr)(&arg3);
                    descrs[2].Size = 4;
                    descrs[3].DataPointer = (IntPtr)(&arg4);
                    descrs[3].Size = 4;
                    WriteEventCore(eventId, 4, descrs);
                }
            }
        }
 
        // optimized for common signatures (used by the EndGetRequestStream event)
        [NonEvent, System.Security.SecuritySafeCritical]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
        private unsafe void WriteEvent(int eventId, long arg1, bool arg2, bool arg3)
        {
            if (IsEnabled())
            {
                EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
                descrs[0].DataPointer = (IntPtr)(&arg1);
                descrs[0].Size = 8;
                descrs[1].DataPointer = (IntPtr)(&arg2);
                descrs[1].Size = 4;
                descrs[2].DataPointer = (IntPtr)(&arg3);
                descrs[2].Size = 4;
                WriteEventCore(eventId, 3, descrs);
            }
        }
 
        // optimized for common signatures (used by the EndGetResponse event)
        [NonEvent, System.Security.SecuritySafeCritical]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
        private unsafe void WriteEvent(int eventId, long arg1, bool arg2, bool arg3, int arg4)
        {
            if (IsEnabled())
            {
                EventSource.EventData* descrs = stackalloc EventSource.EventData[4];
                descrs[0].DataPointer = (IntPtr)(&arg1);
                descrs[0].Size = 8;
                descrs[1].DataPointer = (IntPtr)(&arg2);
                descrs[1].Size = 4;
                descrs[2].DataPointer = (IntPtr)(&arg3);
                descrs[2].Size = 4;
                descrs[3].DataPointer = (IntPtr)(&arg4);
                descrs[3].Size = 4;
                WriteEventCore(eventId, 4, descrs);
            }
        }
 
        // ResourceManager Event Definitions 
 
        [Event(1, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerLookupStarted(String baseName, String mainAssemblyName, String cultureName) {
            WriteEvent(1, baseName, mainAssemblyName, cultureName);
        }
 
        [Event(2, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerLookingForResourceSet(String baseName, String mainAssemblyName, String cultureName) {
            if (IsEnabled())
                WriteEvent(2, baseName, mainAssemblyName, cultureName);
        }
 
        [Event(3, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerFoundResourceSetInCache(String baseName, String mainAssemblyName, String cultureName) {
            if (IsEnabled())
                WriteEvent(3, baseName, mainAssemblyName, cultureName);
        }
 
        // After loading a satellite assembly, we already have the ResourceSet for this culture in
        // the cache. This can happen if you have an assembly load callback that called into this
        // instance of the ResourceManager.
        [Event(4, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
        public void ResourceManagerFoundResourceSetInCacheUnexpected(String baseName, String mainAssemblyName, String cultureName) {
            if (IsEnabled())
                WriteEvent(4, baseName, mainAssemblyName, cultureName);
        }
 
        // manifest resource stream lookup succeeded
        [Event(5, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerStreamFound(String baseName, String mainAssemblyName, String cultureName, String loadedAssemblyName, String resourceFileName) {
            if (IsEnabled())
                WriteEvent(5, baseName, mainAssemblyName, cultureName, loadedAssemblyName, resourceFileName);
        }
 
        // manifest resource stream lookup failed
        [Event(6, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
        public void ResourceManagerStreamNotFound(String baseName, String mainAssemblyName, String cultureName, String loadedAssemblyName, String resourceFileName) {
            if (IsEnabled())
                WriteEvent(6, baseName, mainAssemblyName, cultureName, loadedAssemblyName, resourceFileName);
        }
 
        [Event(7, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerGetSatelliteAssemblySucceeded(String baseName, String mainAssemblyName, String cultureName, String assemblyName) {
            if (IsEnabled())
                WriteEvent(7, baseName, mainAssemblyName, cultureName, assemblyName);
        }
 
        [Event(8, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
        public void ResourceManagerGetSatelliteAssemblyFailed(String baseName, String mainAssemblyName, String cultureName, String assemblyName) {
            if (IsEnabled())
                WriteEvent(8, baseName, mainAssemblyName, cultureName, assemblyName);
        }
 
        [Event(9, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(String baseName, String mainAssemblyName, String assemblyName, String resourceFileName) {
            if (IsEnabled())
                WriteEvent(9, baseName, mainAssemblyName, assemblyName, resourceFileName);
        }
 
        [Event(10, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
        public void ResourceManagerCaseInsensitiveResourceStreamLookupFailed(String baseName, String mainAssemblyName, String assemblyName, String resourceFileName) {
            if (IsEnabled())
                WriteEvent(10, baseName, mainAssemblyName, assemblyName, resourceFileName);
        }
 
        // Could not access the manifest resource the assembly
        [Event(11, Level = EventLevel.Error, Keywords = Keywords.Loader)]
        public void ResourceManagerManifestResourceAccessDenied(String baseName, String mainAssemblyName, String assemblyName, String canonicalName) {
            if (IsEnabled())
                WriteEvent(11, baseName, mainAssemblyName, assemblyName, canonicalName);
        }
 
        // Neutral resources are sufficient for this culture. Skipping satellites
        [Event(12, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerNeutralResourcesSufficient(String baseName, String mainAssemblyName, String cultureName) {
            if (IsEnabled())
                WriteEvent(12, baseName, mainAssemblyName, cultureName);
        }
 
        [Event(13, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
        public void ResourceManagerNeutralResourceAttributeMissing(String mainAssemblyName) {
            if (IsEnabled())
                WriteEvent(13, mainAssemblyName);
        }
 
        [Event(14, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerCreatingResourceSet(String baseName, String mainAssemblyName, String cultureName, String fileName) {
            if (IsEnabled())
                WriteEvent(14, baseName, mainAssemblyName, cultureName, fileName);
        }
 
        [Event(15, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerNotCreatingResourceSet(String baseName, String mainAssemblyName, String cultureName) {
            if (IsEnabled())
                WriteEvent(15, baseName, mainAssemblyName, cultureName);
        }
 
        [Event(16, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
        public void ResourceManagerLookupFailed(String baseName, String mainAssemblyName, String cultureName) {
            if (IsEnabled())
                WriteEvent(16, baseName, mainAssemblyName, cultureName);
        }
 
        [Event(17, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerReleasingResources(String baseName, String mainAssemblyName) {
            if (IsEnabled())
                WriteEvent(17, baseName, mainAssemblyName);
        }
 
        [Event(18, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
        public void ResourceManagerNeutralResourcesNotFound(String baseName, String mainAssemblyName, String resName) {
            if (IsEnabled())
                WriteEvent(18, baseName, mainAssemblyName, resName);
        }
 
        [Event(19, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerNeutralResourcesFound(String baseName, String mainAssemblyName, String resName) {
            if (IsEnabled())
                WriteEvent(19, baseName, mainAssemblyName, resName);
        }
 
        [Event(20, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerAddingCultureFromConfigFile(String baseName, String mainAssemblyName, String cultureName) {
            if (IsEnabled())
                WriteEvent(20, baseName, mainAssemblyName, cultureName);
        }
 
        [Event(21, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerCultureNotFoundInConfigFile(String baseName, String mainAssemblyName, String cultureName) {
            if (IsEnabled())
                WriteEvent(21, baseName, mainAssemblyName, cultureName);
        }
 
        [Event(22, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
        public void ResourceManagerCultureFoundInConfigFile(String baseName, String mainAssemblyName, String cultureName) {
            if (IsEnabled())
                WriteEvent(22, baseName, mainAssemblyName, cultureName);
        }
 
 
        // ResourceManager Event Wrappers
 
        [NonEvent]
        public void ResourceManagerLookupStarted(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled())
                ResourceManagerLookupStarted(baseName, GetName(mainAssembly), cultureName);
        }
 
        [NonEvent]
        public void ResourceManagerLookingForResourceSet(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled())
                ResourceManagerLookingForResourceSet(baseName, GetName(mainAssembly), cultureName);
        }
 
        [NonEvent]
        public void ResourceManagerFoundResourceSetInCache(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled())
                ResourceManagerFoundResourceSetInCache(baseName, GetName(mainAssembly), cultureName);
        }
 
        [NonEvent]
        public void ResourceManagerFoundResourceSetInCacheUnexpected(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled())
                ResourceManagerFoundResourceSetInCacheUnexpected(baseName, GetName(mainAssembly), cultureName);
        }
 
        [NonEvent]
        public void ResourceManagerStreamFound(String baseName, Assembly mainAssembly, String cultureName, Assembly loadedAssembly, String resourceFileName) {
            if (IsEnabled())
                ResourceManagerStreamFound(baseName, GetName(mainAssembly), cultureName, GetName(loadedAssembly), resourceFileName);
        }
 
        [NonEvent]
        public void ResourceManagerStreamNotFound(String baseName, Assembly mainAssembly, String cultureName, Assembly loadedAssembly, String resourceFileName) {
            if (IsEnabled())
                ResourceManagerStreamNotFound(baseName, GetName(mainAssembly), cultureName, GetName(loadedAssembly), resourceFileName);
        }
 
        [NonEvent]
        public void ResourceManagerGetSatelliteAssemblySucceeded(String baseName, Assembly mainAssembly, String cultureName, String assemblyName) {
            if (IsEnabled())
                ResourceManagerGetSatelliteAssemblySucceeded(baseName, GetName(mainAssembly), cultureName, assemblyName);
        }
 
        [NonEvent]
        public void ResourceManagerGetSatelliteAssemblyFailed(String baseName, Assembly mainAssembly, String cultureName, String assemblyName) {
            if (IsEnabled())
                ResourceManagerGetSatelliteAssemblyFailed(baseName, GetName(mainAssembly), cultureName, assemblyName);
        }
 
        [NonEvent]
        public void ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(String baseName, Assembly mainAssembly, String assemblyName, String resourceFileName) {
            if (IsEnabled())
                ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(baseName, GetName(mainAssembly), assemblyName, resourceFileName);
        }
 
        [NonEvent]
        public void ResourceManagerCaseInsensitiveResourceStreamLookupFailed(String baseName, Assembly mainAssembly, String assemblyName, String resourceFileName) {
            if (IsEnabled())
                ResourceManagerCaseInsensitiveResourceStreamLookupFailed(baseName, GetName(mainAssembly), assemblyName, resourceFileName);
        }
 
        [NonEvent]
        public void ResourceManagerManifestResourceAccessDenied(String baseName, Assembly mainAssembly, String assemblyName, String canonicalName) {
            if (IsEnabled())
                ResourceManagerManifestResourceAccessDenied(baseName, GetName(mainAssembly), assemblyName, canonicalName);
        }
 
        [NonEvent]
        public void ResourceManagerNeutralResourcesSufficient(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled()) 
                ResourceManagerNeutralResourcesSufficient(baseName, GetName(mainAssembly), cultureName);
        }
 
        [NonEvent]
        public void ResourceManagerNeutralResourceAttributeMissing(Assembly mainAssembly) {
            if (IsEnabled())
                ResourceManagerNeutralResourceAttributeMissing(GetName(mainAssembly));
        }
 
        [NonEvent]
        public void ResourceManagerCreatingResourceSet(String baseName, Assembly mainAssembly, String cultureName, String fileName) {
            if (IsEnabled())
                ResourceManagerCreatingResourceSet(baseName, GetName(mainAssembly), cultureName, fileName);
        }
 
        [NonEvent]
        public void ResourceManagerNotCreatingResourceSet(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled())
                ResourceManagerNotCreatingResourceSet(baseName, GetName(mainAssembly), cultureName);
        }
 
        [NonEvent]
        public void ResourceManagerLookupFailed(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled())
                ResourceManagerLookupFailed(baseName, GetName(mainAssembly), cultureName);
        }
 
        [NonEvent]
        public void ResourceManagerReleasingResources(String baseName, Assembly mainAssembly) {
            if (IsEnabled())
                ResourceManagerReleasingResources(baseName, GetName(mainAssembly));
        }
 
        [NonEvent]
        public void ResourceManagerNeutralResourcesNotFound(String baseName, Assembly mainAssembly, String resName) {
            if (IsEnabled())
                ResourceManagerNeutralResourcesNotFound(baseName, GetName(mainAssembly), resName);
        }
 
        [NonEvent]
        public void ResourceManagerNeutralResourcesFound(String baseName, Assembly mainAssembly, String resName) {
            if (IsEnabled())
                ResourceManagerNeutralResourcesFound(baseName, GetName(mainAssembly), resName);
        }
 
        [NonEvent]
        public void ResourceManagerAddingCultureFromConfigFile(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled())
                ResourceManagerAddingCultureFromConfigFile(baseName, GetName(mainAssembly), cultureName);
        }
 
        [NonEvent]
        public void ResourceManagerCultureNotFoundInConfigFile(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled())
                ResourceManagerCultureNotFoundInConfigFile(baseName, GetName(mainAssembly), cultureName);
        }
 
        [NonEvent]
        public void ResourceManagerCultureFoundInConfigFile(String baseName, Assembly mainAssembly, String cultureName) {
            if (IsEnabled())
                ResourceManagerCultureFoundInConfigFile(baseName, GetName(mainAssembly), cultureName);
        }
 
        private static string GetName(Assembly assembly) {
            if (assembly == null)
                return "<<NULL>>";
            else
                return assembly.FullName;
        }
 
        [Event(30, Level = EventLevel.Verbose, Keywords = Keywords.ThreadPool|Keywords.ThreadTransfer)]
        public void ThreadPoolEnqueueWork(long workID) {
            WriteEvent(30, workID);
        }
        [NonEvent, System.Security.SecuritySafeCritical]
        public unsafe void ThreadPoolEnqueueWorkObject(object workID) {
            // convert the Object Id to a long
            ThreadPoolEnqueueWork((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref workID)));
        }
 
        [Event(31, Level = EventLevel.Verbose, Keywords = Keywords.ThreadPool|Keywords.ThreadTransfer)]
        public void ThreadPoolDequeueWork(long workID) {
            WriteEvent(31, workID);
        }
 
        [NonEvent, System.Security.SecuritySafeCritical]
        public unsafe void ThreadPoolDequeueWorkObject(object workID) {
            // convert the Object Id to a long
            ThreadPoolDequeueWork((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref workID)));
        }
 
        // In the desktop runtime they don't use Tasks for the point at which the response happens, which means that the
        // Activity ID created by start using implicit activity IDs does not match.   Thus disable implicit activities (until we fix that)
        [Event(140, Level = EventLevel.Informational, Keywords = Keywords.NetClient, ActivityOptions=EventActivityOptions.Disable,
         Task = Tasks.GetResponse, Opcode = EventOpcode.Start, Version = 1)]
        private void GetResponseStart(long id, string uri, bool success, bool synchronous) {
            WriteEvent(140, id, uri, success, synchronous);
        }
 
        [Event(141, Level = EventLevel.Informational, Keywords = Keywords.NetClient, ActivityOptions=EventActivityOptions.Disable, 
         Task = Tasks.GetResponse, Opcode = EventOpcode.Stop, Version = 1)]
        private void GetResponseStop(long id, bool success, bool synchronous, int statusCode) {
            WriteEvent(141, id, success, synchronous, statusCode);
        }
 
        // In the desktop runtime they don't use Tasks for the point at which the response happens, which means that the
        // Activity ID created by start using implicit activity IDs does not match.   Thus disable implicit activities (until we fix that)
        [Event(142, Level = EventLevel.Informational, Keywords = Keywords.NetClient, ActivityOptions=EventActivityOptions.Disable,
         Task = Tasks.GetRequestStream, Opcode = EventOpcode.Start, Version = 1)]
        private void GetRequestStreamStart(long id, string uri, bool success, bool synchronous) {
            WriteEvent(142, id, uri, success, synchronous);
        }
 
        [Event(143, Level = EventLevel.Informational, Keywords = Keywords.NetClient, ActivityOptions=EventActivityOptions.Disable,
         Task = Tasks.GetRequestStream, Opcode = EventOpcode.Stop, Version = 1)]
        private void GetRequestStreamStop(long id, bool success, bool synchronous) {
            WriteEvent(143, id, success, synchronous);
        }
 
        [NonEvent, System.Security.SecuritySafeCritical]
        public unsafe void BeginGetResponse(object id, string uri, bool success, bool synchronous) {
            if (IsEnabled())
                GetResponseStart(IdForObject(id), uri, success, synchronous);
        }
            
        [NonEvent, System.Security.SecuritySafeCritical]
        public unsafe void EndGetResponse(object id, bool success, bool synchronous, int statusCode) {
            if (IsEnabled())
                GetResponseStop(IdForObject(id), success, synchronous, statusCode);
        }
 
        [NonEvent, System.Security.SecuritySafeCritical]
        public unsafe void BeginGetRequestStream(object id, string uri, bool success, bool synchronous) {
            if (IsEnabled())
                GetRequestStreamStart(IdForObject(id), uri, success, synchronous);
        }
 
        [NonEvent, System.Security.SecuritySafeCritical]
        public unsafe void EndGetRequestStream(object id, bool success, bool synchronous) {
            if (IsEnabled())
                GetRequestStreamStop(IdForObject(id), success, synchronous);
        }
 
        // id -   represents a correlation ID that allows correlation of two activities, one stamped by 
        //        ThreadTransferSend, the other by ThreadTransferReceive
        // kind - identifies the transfer: values below 64 are reserved for the runtime. Currently used values:
        //        1 - managed Timers ("roaming" ID)
        //        2 - managed async IO operations (FileStream, PipeStream, a.o.)
        //        3 - WinRT dispatch operations
        // info - any additional information user code might consider interesting
        [Event(150, Level = EventLevel.Informational, Keywords = Keywords.ThreadTransfer, Task = Tasks.ThreadTransfer, Opcode = EventOpcode.Send)]
        public void ThreadTransferSend(long id, int kind, string info, bool multiDequeues) {
            if (IsEnabled())
                WriteEvent(150, id, kind, info, multiDequeues);
        }
        // id - is a managed object. it gets translated to the object's address. ETW listeners must
        //      keep track of GC movements in order to correlate the value passed to XyzSend with the
        //      (possibly changed) value passed to XyzReceive
        [NonEvent, System.Security.SecuritySafeCritical]
        public unsafe void ThreadTransferSendObj(object id, int kind, string info, bool multiDequeues) {
            ThreadTransferSend((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref id)), kind, info, multiDequeues);
        }
 
        // id -   represents a correlation ID that allows correlation of two activities, one stamped by 
        //        ThreadTransferSend, the other by ThreadTransferReceive
        // kind - identifies the transfer: values below 64 are reserved for the runtime. Currently used values:
        //        1 - managed Timers ("roaming" ID)
        //        2 - managed async IO operations (FileStream, PipeStream, a.o.)
        //        3 - WinRT dispatch operations
        // info - any additional information user code might consider interesting
        [Event(151, Level = EventLevel.Informational, Keywords = Keywords.ThreadTransfer, Task = Tasks.ThreadTransfer, Opcode = EventOpcode.Receive)]
        public void ThreadTransferReceive(long id, int kind, string info) {
            if (IsEnabled())
                WriteEvent(151, id, kind, info);
        }
        // id - is a managed object. it gets translated to the object's address. ETW listeners must
        //      keep track of GC movements in order to correlate the value passed to XyzSend with the
        //      (possibly changed) value passed to XyzReceive
        [NonEvent, System.Security.SecuritySafeCritical]
        public unsafe void ThreadTransferReceiveObj(object id, int kind, string info) {
            ThreadTransferReceive((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref id)), kind, info);
        }
 
        // id -   represents a correlation ID that allows correlation of two activities, one stamped by 
        //        ThreadTransferSend, the other by ThreadTransferReceive
        // kind - identifies the transfer: values below 64 are reserved for the runtime. Currently used values:
        //        1 - managed Timers ("roaming" ID)
        //        2 - managed async IO operations (FileStream, PipeStream, a.o.)
        //        3 - WinRT dispatch operations
        // info - any additional information user code might consider interesting
        [Event(152, Level = EventLevel.Informational, Keywords = Keywords.ThreadTransfer, Task = Tasks.ThreadTransfer, Opcode = Opcodes.ReceiveHandled)]
        public void ThreadTransferReceiveHandled(long id, int kind, string info) {
            if (IsEnabled())
                WriteEvent(152, id, kind, info);
        }
        // id - is a managed object. it gets translated to the object's address. ETW listeners must
        //      keep track of GC movements in order to correlate the value passed to XyzSend with the
        //      (possibly changed) value passed to XyzReceive
        [NonEvent, System.Security.SecuritySafeCritical]
        public unsafe void ThreadTransferReceiveHandledObj(object id, int kind, string info) {
            ThreadTransferReceive((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref id)), kind, info);
        }
 
        // return a stable ID for a an object.  We use the hash code which is not truely unique but is 
        // close enough for now at least. we add to it 0x7FFFFFFF00000000 to make it distinguishable
        // from the style of ID that simply casts the object reference to a long (since old versions of the 
        // runtime will emit IDs of that form).  
        private static long IdForObject(object obj) {
            return obj.GetHashCode() + 0x7FFFFFFF00000000;
        }
    }
}