// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.ObjectModel; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; namespace System.Diagnostics.Tracing { /// <summary> /// NativeRuntimeEventSource is an EventSource that represents the ETW/EventPipe events emitted by the native runtime. /// Most of NativeRuntimeEventSource is auto-generated by NativeRuntimeEventSourceGenerator based on the contents of the /// Microsoft-Windows-DotNETRuntime provider and will throw a NotImplementedException without hand-written overloads of the Events. /// To have a runtime event be fired from the managed code, you need to add a managed definition for that event /// and call into the native runtime that invoke the appropriate native sinks for the platform (i.e. ETW, EventPipe, LTTng). /// To see some examples of this, refer to NativeRuntimeEventSource.Threading.NativeSinks.cs and NativeRuntimeEventSource.Threading.cs. /// Then, modify NativeRuntimeEventSourceGenerator.cs to skip over the event so that it doesn't generate the dummy method. /// /// The events in NativeRuntimeEventSource.*.NativeSinks.cs do not call into the typical WriteEvent* APIs unlike most EventSources because that results in the /// events to be forwarded to EventListeners twice, once directly from the managed WriteEvent API, and another time /// from the mechanism in NativeRuntimeEventSource.ProcessEvents that forwards native runtime events to EventListeners. /// To prevent this, these events call directly into QCalls provided by the runtime in NativeRuntimeEventSource.*.NativeSinks.Internal.cs which call /// FireEtw* methods auto-generated from ClrEtwAll.man. This ensures that corresponding event sinks are being used /// for the native platform. /// </summary> [EventSource(Guid = "E13C0D23-CCBC-4E12-931B-D9CC2EEE27E4", Name = EventSourceName)] internal sealed partial class NativeRuntimeEventSource : EventSource { internal const string EventSourceName = "Microsoft-Windows-DotNETRuntime"; public static readonly NativeRuntimeEventSource Log = new NativeRuntimeEventSource(); // This value does not seem to be used, leaving it as zero for now. It may be useful for a scenario that may involve // multiple instances of the runtime within the same process, but then it seems unlikely that both instances' thread // pools would be in moderate use. private const ushort DefaultClrInstanceId = 0; #if FEATURE_PERFTRACING /// <summary> /// Dispatch a single event with the specified event ID and payload. /// </summary> /// <param name="eventID">The eventID corresponding to the event as defined in the auto-generated portion of the NativeRuntimeEventSource class.</param> /// <param name="osThreadID">The thread ID of the operating system thread.</param> /// <param name="timeStamp">The current timestamp.</param> /// <param name="activityId">The ID of the current activity.</param> /// <param name="childActivityId">The ID of the current child activity.</param> /// <param name="payload">A span pointing to the data payload for the event.</param> [NonEvent] internal unsafe void ProcessEvent(uint eventID, uint osThreadID, DateTime timeStamp, Guid activityId, Guid childActivityId, ReadOnlySpan<byte> payload) { // A simple fix to avoid dependencies brought by this method if event source is disabled via a feature switch. // Should be reconsidered when https://github.com/dotnet/runtime/issues/43657 is done. if (!IsSupported) { return; } // Make sure the eventID is valid. ref EventMetadata metadata = ref CollectionsMarshal.GetValueRefOrNullRef(m_eventData!, (int)eventID); if (Unsafe.IsNullRef(ref metadata)) { return; } // Decode the payload. object[] decodedPayloadFields = EventPipePayloadDecoder.DecodePayload(ref metadata, payload); var eventCallbackArgs = new EventWrittenEventArgs(this, (int)eventID, &activityId, &childActivityId) { OSThreadId = (int)osThreadID, TimeStamp = timeStamp, Payload = new ReadOnlyCollection<object?>(decodedPayloadFields) }; DispatchToAllListeners(eventCallbackArgs); } #endif // FEATURE_PERFTRACING } } |