File: System\Net\WebSockets\NetEventSource.WebSockets.cs
Web Access
Project: src\src\libraries\System.Net.WebSockets\src\System.Net.WebSockets.csproj (System.Net.WebSockets)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using System.Runtime.CompilerServices;
 
namespace System.Net
{
    [EventSource(Name = "Private.InternalDiagnostics.System.Net.WebSockets")]
    internal sealed partial class NetEventSource
    {
        // NOTE
        // - The 'Start' and 'Stop' suffixes on the following event names have special meaning in EventSource. They
        //   enable creating 'activities'.
        //   For more information, take a look at the following blog post:
        //   https://blogs.msdn.microsoft.com/vancem/2015/09/14/exploring-eventsource-activity-correlation-and-causation-features/
        // - A stop event's event id must be next one after its start event.
 
        private const int KeepAliveSentId = NextAvailableEventId;
        private const int KeepAliveAckedId = KeepAliveSentId + 1;
 
        private const int WsTraceId = KeepAliveAckedId + 1;
 
        private const int CloseStartId = WsTraceId + 1;
        private const int CloseStopId = CloseStartId + 1;
 
        private const int ReceiveStartId = CloseStopId + 1;
        private const int ReceiveStopId = ReceiveStartId + 1;
 
        private const int SendStartId = ReceiveStopId + 1;
        private const int SendStopId = SendStartId + 1;
 
        private const int MutexEnterId = SendStopId + 1;
        private const int MutexExitId = MutexEnterId + 1;
 
        //
        // Keep-Alive
        //
 
        private const string Ping = "Ping";
        private const string Pong = "Pong";
 
        [Event(KeepAliveSentId, Keywords = Keywords.Debug, Level = EventLevel.Informational)]
        private void KeepAliveSent(string objName, string opcode, long payload) =>
            WriteEvent(KeepAliveSentId, objName, opcode, payload);
 
        [Event(KeepAliveAckedId, Keywords = Keywords.Debug, Level = EventLevel.Informational)]
        private void KeepAliveAcked(string objName, long payload) =>
            WriteEvent(KeepAliveAckedId, objName, payload);
 
        [NonEvent]
        public static void KeepAlivePingSent(object? obj, long payload)
        {
            Debug.Assert(Log.IsEnabled());
            Log.KeepAliveSent(IdOf(obj), Ping, payload);
        }
 
        [NonEvent]
        public static void UnsolicitedPongSent(object? obj)
        {
            Debug.Assert(Log.IsEnabled());
            Log.KeepAliveSent(IdOf(obj), Pong, 0);
        }
 
        [NonEvent]
        public static void PongResponseReceived(object? obj, long payload)
        {
            Debug.Assert(Log.IsEnabled());
            Log.KeepAliveAcked(IdOf(obj), payload);
        }
 
        //
        // Debug Messages
        //
 
        [Event(WsTraceId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
        private void WsTrace(string objName, string memberName, string message) =>
            WriteEvent(WsTraceId, objName, memberName, message);
 
        [NonEvent]
        public static void TraceErrorMsg(object? obj, Exception exception, [CallerMemberName] string? memberName = null)
            => Trace(obj, $"{exception.GetType().Name}: {exception.Message}", memberName);
 
        [NonEvent]
        public static void TraceException(object? obj, Exception exception, [CallerMemberName] string? memberName = null)
            => Trace(obj, exception.ToString(), memberName);
 
        [NonEvent]
        public static void Trace(object? obj, string? message = null, [CallerMemberName] string? memberName = null)
        {
            Debug.Assert(Log.IsEnabled());
            Log.WsTrace(IdOf(obj), memberName ?? MissingMember, message ?? memberName ?? string.Empty);
        }
 
        //
        // Close
        //
 
        [Event(CloseStartId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
        private void CloseStart(string objName, string memberName) =>
            WriteEvent(CloseStartId, objName, memberName);
 
        [Event(CloseStopId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
        private void CloseStop(string objName, string memberName) =>
            WriteEvent(CloseStopId, objName, memberName);
 
        [NonEvent]
        public static void CloseAsyncPrivateStarted(object? obj, [CallerMemberName] string? memberName = null)
        {
            Debug.Assert(Log.IsEnabled());
            Log.CloseStart(IdOf(obj), memberName ?? MissingMember);
        }
 
        [NonEvent]
        public static void CloseAsyncPrivateCompleted(object? obj, [CallerMemberName] string? memberName = null)
        {
            Debug.Assert(Log.IsEnabled());
            Log.CloseStop(IdOf(obj), memberName ?? MissingMember);
        }
 
        //
        // ReceiveAsyncPrivate
        //
 
        [Event(ReceiveStartId, Keywords = Keywords.Debug, Level = EventLevel.Informational)]
        private void ReceiveStart(string objName, string memberName, int bufferLength) =>
            WriteEvent(ReceiveStartId, objName, memberName, bufferLength);
 
        [Event(ReceiveStopId, Keywords = Keywords.Debug, Level = EventLevel.Informational)]
        private void ReceiveStop(string objName, string memberName) =>
            WriteEvent(ReceiveStopId, objName, memberName);
 
        [NonEvent]
        public static void ReceiveAsyncPrivateStarted(object? obj, int bufferLength, [CallerMemberName] string? memberName = null)
        {
            Debug.Assert(Log.IsEnabled());
            Log.ReceiveStart(IdOf(obj), memberName ?? MissingMember, bufferLength);
        }
 
        [NonEvent]
        public static void ReceiveAsyncPrivateCompleted(object? obj, [CallerMemberName] string? memberName = null)
        {
            Debug.Assert(Log.IsEnabled());
            Log.ReceiveStop(IdOf(obj), memberName ?? MissingMember);
        }
 
        //
        // SendFrameAsync
        //
 
        [Event(SendStartId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
        private void SendStart(string objName, string memberName, string opcode, int bufferLength) =>
            WriteEvent(SendStartId, objName, memberName, opcode, bufferLength);
 
        [Event(SendStopId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
        private void SendStop(string objName, string memberName) =>
            WriteEvent(SendStopId, objName, memberName);
 
        [NonEvent]
        public static void SendFrameAsyncStarted(object? obj, string opcode, int bufferLength, [CallerMemberName] string? memberName = null)
        {
            Debug.Assert(Log.IsEnabled());
            Log.SendStart(IdOf(obj), memberName ?? MissingMember, opcode, bufferLength);
        }
 
        [NonEvent]
        public static void SendFrameAsyncCompleted(object? obj, [CallerMemberName] string? memberName = null)
        {
            Debug.Assert(Log.IsEnabled());
            Log.SendStop(IdOf(obj), memberName ?? MissingMember);
        }
 
        //
        // AsyncMutex
        //
 
        [Event(MutexEnterId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
        private void MutexEnter(string objName, string memberName) =>
            WriteEvent(MutexEnterId, objName, memberName);
 
        [Event(MutexExitId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
        private void MutexExit(string objName, string memberName) =>
            WriteEvent(MutexExitId, objName, memberName);
 
        [NonEvent]
        public static void MutexEntered(object? obj, [CallerMemberName] string? memberName = null)
        {
            Debug.Assert(Log.IsEnabled());
            Log.MutexEnter(IdOf(obj), memberName ?? MissingMember);
        }
 
        [NonEvent]
        public static void MutexExited(object? obj, [CallerMemberName] string? memberName = null)
        {
            Debug.Assert(Log.IsEnabled());
            Log.MutexExit(IdOf(obj), memberName ?? MissingMember);
        }
 
        //
        // WriteEvent overloads
        //
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
                   Justification = EventSourceSuppressMessage)]
        [NonEvent]
        private unsafe void WriteEvent(int eventId, string arg1, string arg2, long arg3)
        {
            fixed (char* arg1Ptr = arg1)
            fixed (char* arg2Ptr = arg2)
            {
                const int NumEventDatas = 3;
                EventData* descrs = stackalloc EventData[NumEventDatas];
 
                descrs[0] = new EventData
                {
                    DataPointer = (IntPtr)(arg1Ptr),
                    Size = (arg1.Length + 1) * sizeof(char)
                };
                descrs[1] = new EventData
                {
                    DataPointer = (IntPtr)(arg2Ptr),
                    Size = (arg2.Length + 1) * sizeof(char)
                };
                descrs[2] = new EventData
                {
                    DataPointer = (IntPtr)(&arg3),
                    Size = sizeof(long)
                };
 
                WriteEventCore(eventId, NumEventDatas, descrs);
            }
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
                   Justification = EventSourceSuppressMessage)]
        [NonEvent]
        private unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3, int arg4)
        {
            fixed (char* arg1Ptr = arg1)
            fixed (char* arg2Ptr = arg2)
            fixed (char* arg3Ptr = arg3)
            {
                const int NumEventDatas = 4;
                EventData* descrs = stackalloc EventData[NumEventDatas];
 
                descrs[0] = new EventData
                {
                    DataPointer = (IntPtr)(arg1Ptr),
                    Size = (arg1.Length + 1) * sizeof(char)
                };
                descrs[1] = new EventData
                {
                    DataPointer = (IntPtr)(arg2Ptr),
                    Size = (arg2.Length + 1) * sizeof(char)
                };
                descrs[2] = new EventData
                {
                    DataPointer = (IntPtr)(arg3Ptr),
                    Size = (arg3.Length + 1) * sizeof(char)
                };
                descrs[3] = new EventData
                {
                    DataPointer = (IntPtr)(&arg4),
                    Size = sizeof(int)
                };
 
                WriteEventCore(eventId, NumEventDatas, descrs);
            }
        }
 
    }
}