diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 057057a0a1d97..a6b278aa708a4 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -775,8 +775,8 @@ DEFINE_FIELD_U(rgiColumnNumber, StackFrameHelper, rgiColumnNumber) DEFINE_FIELD_U(rgiLastFrameFromForeignExceptionStackTrace, StackFrameHelper, rgiLastFrameFromForeignExceptionStackTrace) DEFINE_FIELD_U(iFrameCount, StackFrameHelper, iFrameCount) -DEFINE_CLASS(RUNTIME_EVENT_SOURCE, Tracing, RuntimeEventSource) -DEFINE_METHOD(RUNTIME_EVENT_SOURCE, INITIALIZE, Initialize, SM_RetVoid) +DEFINE_CLASS(EVENT_SOURCE, Tracing, EventSource) +DEFINE_METHOD(EVENT_SOURCE, INITIALIZE_DEFAULT_EVENT_SOURCES, InitializeDefaultEventSources, SM_RetVoid) DEFINE_CLASS(STARTUP_HOOK_PROVIDER, System, StartupHookProvider) DEFINE_METHOD(STARTUP_HOOK_PROVIDER, MANAGED_STARTUP, ManagedStartup, SM_PtrChar_RetVoid) diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index 44e7a733bfc93..35c724e10a9ca 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -665,11 +665,11 @@ HRESULT CorHost2::CreateAppDomainWithManager( m_fAppDomainCreated = TRUE; #ifdef FEATURE_PERFTRACING - // Initialize RuntimeEventSource + // Initialize default event sources { GCX_COOP(); - MethodDescCallSite initRuntimeEventSource(METHOD__RUNTIME_EVENT_SOURCE__INITIALIZE); - initRuntimeEventSource.Call(NULL); + MethodDescCallSite initEventSources(METHOD__EVENT_SOURCE__INITIALIZE_DEFAULT_EVENT_SOURCES); + initEventSources.Call(NULL); } #endif // FEATURE_PERFTRACING diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Descriptors.LibraryBuild.xml b/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Descriptors.LibraryBuild.xml new file mode 100644 index 0000000000000..a42d7f0e7e82d --- /dev/null +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index 62a37ab56e29f..3db1dbd5a06ef 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -25,6 +25,7 @@ System.Diagnostics.DiagnosticSource + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs index cc837b995fece..520307cc4c479 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs @@ -46,6 +46,11 @@ internal sealed class MetricsEventSource : EventSource { public static readonly MetricsEventSource Log = new(); + // Although this API isn't public, it is invoked via reflection from System.Private.CoreLib and needs the same back-compat + // consideration as a public API. See EventSource.InitializeDefaultEventSources() in System.Private.CoreLib source for more + // details. We have a unit test GetInstanceMethodIsReflectable that verifies this method isn't accidentally removed or renamed. + public static MetricsEventSource GetInstance() { return Log; } + private const string SharedSessionId = "SHARED"; private const string ClientIdKey = "ClientId"; private const string MaxHistogramsKey = "MaxHistograms"; diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs index f78cb9a44b2a3..b43aba298f3f0 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs @@ -5,6 +5,7 @@ using System.Diagnostics.Tracing; using System.Globalization; using System.Linq; +using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; @@ -26,6 +27,23 @@ public MetricEventSourceTests(ITestOutputHelper output) _output = output; } + [Fact] + public void GetInstanceMethodIsReflectable() + { + // The startup code in System.Private.CoreLib needs to be able to get the MetricsEventSource instance via reflection. See EventSource.InitializeDefaultEventSources() in + // the System.Private.CoreLib source. + // Even though the the type isn't public this test ensures the GetInstance() API isn't removed or renamed. + Type? metricsEventSourceType = Type.GetType("System.Diagnostics.Metrics.MetricsEventSource, System.Diagnostics.DiagnosticSource", throwOnError: false); + Assert.True(metricsEventSourceType != null, "Unable to get MetricsEventSource type via reflection"); + + MethodInfo? getInstanceMethod = metricsEventSourceType.GetMethod("GetInstance", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, Type.EmptyTypes, null); + Assert.True(getInstanceMethod != null, "Unable to get MetricsEventSource.GetInstance method via reflection"); + + object? o = getInstanceMethod.Invoke(null, null); + Assert.True(o != null, "Expected non-null result invoking MetricsEventSource.GetInstance() via reflection"); + Assert.True(o is EventSource, "Expected object returned from MetricsEventSource.GetInstance() to be assignable to EventSource"); + } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] [OuterLoop("Slow and has lots of console spew")] public void MultipleListeners_DifferentCounters() diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestUtilities.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestUtilities.cs index ec7c8f1c2cd32..78c978be3451e 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestUtilities.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestUtilities.cs @@ -31,6 +31,7 @@ public static void CheckNoEventSourcesRunning(string message = "") eventSource.Name != "System.Reflection.Runtime.Tracing" && eventSource.Name != "Microsoft-Windows-DotNETRuntime" && eventSource.Name != "System.Runtime" && + eventSource.Name != "System.Diagnostics.Metrics" && // event source from xunit runner eventSource.Name != "xUnit.TestEventSource" && diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.EventSource.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.EventSource.xml index 3cdf676501162..9804fa8eb1594 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.EventSource.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.EventSource.xml @@ -1,7 +1,7 @@ - - + + diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs index 606d149d800db..398f94001a7e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs @@ -70,12 +70,12 @@ private static unsafe void Callback(byte* sourceId, int isEnabled, byte level, } // Register an event provider. - internal override unsafe void Register(EventSource eventSource) + internal override unsafe void Register(Guid id, string name) { Debug.Assert(!_gcHandle.IsAllocated); _gcHandle = GCHandle.Alloc(this); - _provHandle = EventPipeInternal.CreateProvider(eventSource.Name, &Callback, (void*)GCHandle.ToIntPtr(_gcHandle)); + _provHandle = EventPipeInternal.CreateProvider(name, &Callback, (void*)GCHandle.ToIntPtr(_gcHandle)); if (_provHandle == 0) { // Unable to create the provider. diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs index f52b0e934e0a5..a25f52aad37f2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs @@ -103,14 +103,14 @@ internal EventProvider(EventProviderType providerType) } /// - /// This method registers the controlGuid of this class with ETW. + /// This method registers the provider with the backing tracing mechanism, either ETW or EventPipe. /// - internal unsafe void Register(EventSource eventSource) + internal unsafe void Register(Guid id, string name) { - _providerName = eventSource.Name; - _providerId = eventSource.Guid; + _providerName = name; + _providerId = id; - _eventProvider.Register(eventSource); + _eventProvider.Register(id, name); } // @@ -827,13 +827,13 @@ private static unsafe void Callback(Guid* sourceId, int isEnabled, byte level, // Register an event provider. - internal override unsafe void Register(EventSource eventSource) + internal override unsafe void Register(Guid id, string name) { Debug.Assert(!_gcHandle.IsAllocated); _gcHandle = GCHandle.Alloc(this); long registrationHandle = 0; - _providerId = eventSource.Guid; + _providerId = id; Guid providerId = _providerId; uint status = Interop.Advapi32.EventRegister( &providerId, @@ -1235,7 +1235,7 @@ internal virtual void Disable() _allKeywordMask = 0; } - internal virtual void Register(EventSource eventSource) + internal virtual void Register(Guid id, string name) { } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index b4fa216916878..3edb4ad9d54f6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -1602,15 +1602,37 @@ private unsafe void Initialize(Guid eventSourceGuid, string eventSourceName, str } // Register the provider with ETW - var etwProvider = new OverrideEventProvider(this, EventProviderType.ETW); - etwProvider.Register(this); + Func eventSourceFactory = () => this; + OverrideEventProvider? etwProvider = TryGetPreregisteredEtwProvider(eventSourceGuid); + if(etwProvider == null) + { + etwProvider = new OverrideEventProvider(eventSourceFactory, EventProviderType.ETW); + etwProvider.Register(eventSourceGuid, eventSourceName); + #if TARGET_WINDOWS + // API available on OS >= Win 8 and patched Win 7. + // Disable only for FrameworkEventSource to avoid recursion inside exception handling. + if (this.Name != "System.Diagnostics.Eventing.FrameworkEventSource" || Environment.IsWindows8OrAbove) + { + var providerMetadata = ProviderMetadata; + fixed (byte* pMetadata = providerMetadata) + { + etwProvider.SetInformation( + Interop.Advapi32.EVENT_INFO_CLASS.SetTraits, + pMetadata, + (uint)providerMetadata.Length); + } + } + #endif // TARGET_WINDOWS + } #if FEATURE_PERFTRACING // Register the provider with EventPipe - var eventPipeProvider = new OverrideEventProvider(this, EventProviderType.EventPipe); - lock (EventListener.EventListenersLock) + OverrideEventProvider? eventPipeProvider = TryGetPreregisteredEventPipeProvider(eventSourceName); + if (eventPipeProvider == null) { - eventPipeProvider.Register(this); + eventPipeProvider = new OverrideEventProvider(eventSourceFactory, EventProviderType.EventPipe); + eventPipeProvider.Register(eventSourceGuid, eventSourceName); + } #endif // Add the eventSource to the global (weak) list. @@ -1621,22 +1643,6 @@ private unsafe void Initialize(Guid eventSourceGuid, string eventSourceName, str // Set m_provider, which allows this. m_etwProvider = etwProvider; -#if TARGET_WINDOWS - // API available on OS >= Win 8 and patched Win 7. - // Disable only for FrameworkEventSource to avoid recursion inside exception handling. - if (this.Name != "System.Diagnostics.Eventing.FrameworkEventSource" || Environment.IsWindows8OrAbove) - { - var providerMetadata = ProviderMetadata; - fixed (byte* pMetadata = providerMetadata) - { - m_etwProvider.SetInformation( - Interop.Advapi32.EVENT_INFO_CLASS.SetTraits, - pMetadata, - (uint)providerMetadata.Length); - } - } -#endif // TARGET_WINDOWS - #if FEATURE_PERFTRACING m_eventPipeProvider = eventPipeProvider; #endif @@ -2398,22 +2404,22 @@ internal static EventOpcode GetOpcodeWithDefault(EventOpcode opcode, string? eve /// private sealed class OverrideEventProvider : EventProvider { - public OverrideEventProvider(EventSource eventSource, EventProviderType providerType) + public OverrideEventProvider(Func eventSourceFactory, EventProviderType providerType) : base(providerType) { - this.m_eventSource = eventSource; - this.m_eventProviderType = providerType; + _eventSourceFactory = eventSourceFactory; + _eventProviderType = providerType; } internal override void OnControllerCommand(ControllerCommand command, IDictionary? arguments, int perEventSourceSessionId) { // We use null to represent the ETW EventListener. EventListener? listener = null; - m_eventSource.SendCommand(listener, m_eventProviderType, perEventSourceSessionId, + _eventSourceFactory()?.SendCommand(listener, _eventProviderType, perEventSourceSessionId, (EventCommand)command, IsEnabled(), Level, MatchAnyKeyword, arguments); } - private readonly EventSource m_eventSource; - private readonly EventProviderType m_eventProviderType; + private readonly Func _eventSourceFactory; + private readonly EventProviderType _eventProviderType; } /// @@ -3799,6 +3805,161 @@ private bool SelfDescribingEvents } } +#if NATIVEAOT + // If EventSource feature is enabled, default EventSources need to be initialized for NativeAOT + // In CoreCLR, this is done via a call from the runtime as part of coreclr_initialize +#pragma warning disable CA2255 + [ModuleInitializer] +#pragma warning restore CA2255 +#endif + internal static void InitializeDefaultEventSources() + { + if(!EventSource.IsSupported) + { + return; + } + +// NOTE: this define is being used inconsistently. Most places mean just EventPipe support, but then a few places use +// it to mean other aspects of tracing such as these EventSources. +#if FEATURE_PERFTRACING + _ = NativeRuntimeEventSource.Log; + _ = RuntimeEventSource.Log; +#endif + // System.Diagnostics.MetricsEventSource allows listening to Meters and indirectly + // also creates the System.Runtime Meter. + + // Functionally we could preregister NativeRuntimeEventSource and RuntimeEventSource as well, but it may not provide + // much benefit. The main benefit for MetricsEventSource is that the app may never use it and it defers + // pulling the System.Diagnostics.DiagnosticSource assembly into the process until it is needed. + if (AppContext.TryGetSwitch("System.Diagnostics.Metrics.Meter.IsSupported", out bool isSupported) ? isSupported : true) + { + const string name = "System.Diagnostics.Metrics"; + Guid id = new Guid("20752bc4-c151-50f5-f27b-df92d8af5a61"); + PreregisterEventProviders(id, name, GetMetricsEventSource); + } + } + + private static EventSource? GetMetricsEventSource() + { + Type? metricsEventSourceType = Type.GetType( + "System.Diagnostics.Metrics.MetricsEventSource, System.Diagnostics.DiagnosticSource", + throwOnError: false); + + if (metricsEventSourceType == null) + { + return null; + } + MethodInfo? getInstanceMethod = metricsEventSourceType.GetMethod("GetInstance", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, Type.EmptyTypes, null); + if (getInstanceMethod == null) + { + return null; + } + return getInstanceMethod.Invoke(null, null) as EventSource; + } + + // Pre-registration creates and registers an EventProvider prior to the EventSource being constructed. + // If a tracing session is started using the provider then the EventSource will be constructed on demand. + private static unsafe void PreregisterEventProviders(Guid id, string name, Func eventSourceFactory) + { + // NOTE: Pre-registration has some minor limitations and variations to normal EventSource behavior: + // 1. Instead of delivering OnEventCommand callbacks during the EventSource constructor it may deliver them after + // the constructor instead. This occurs because the EventProvider callback might create the EventSource instance + // in the factory method, then deliver the callback. + // 2. EventSource traits aren't supported. Normally EventSource.Initialize() would init provider metadata including + // traits but the SetInformation() call we use below generates metadata from name only. If we want traits support + // in the future it could be added. + + // NOTE: You might think this preregister logic could be simplified by using an Action to create the EventSource instead of + // Func and then allow the EventSource to initialize as normal. This doesn't work however because calling + // EtwEventProvider.Register() inside of an ETW callback deadlocks. Instead we have to bind the EventSource to the + // EtwEventProvider that was already registered and use the callback we got on that provider to invoke EventSource.SendCommand(). + try + { + s_preregisteredEventSourceFactories.Add(eventSourceFactory); + + OverrideEventProvider etwProvider = new OverrideEventProvider(eventSourceFactory, EventProviderType.ETW); + etwProvider.Register(id, name); +#if TARGET_WINDOWS + byte[] providerMetadata = Statics.MetadataForString(name, 0, 0, 0); + fixed (byte* pMetadata = providerMetadata) + { + etwProvider.SetInformation( + Interop.Advapi32.EVENT_INFO_CLASS.SetTraits, + pMetadata, + (uint)providerMetadata.Length); + } +#endif // TARGET_WINDOWS + lock (s_preregisteredEtwProviders) + { + s_preregisteredEtwProviders[id] = etwProvider; + } + +#if FEATURE_PERFTRACING + OverrideEventProvider eventPipeProvider = new OverrideEventProvider(eventSourceFactory, EventProviderType.EventPipe); + eventPipeProvider.Register(id, name); + lock (s_preregisteredEventPipeProviders) + { + s_preregisteredEventPipeProviders[name] = eventPipeProvider; + } +#endif + } + catch (Exception) + { + // If there is a failure registering then the normal EventSource.Initialize() path can try to register + // again if/when the EventSource is constructed. + } + } + + internal static void EnsurePreregisteredEventSourcesExist() + { + if (!EventSource.IsSupported) + { + return; + } + + // In a multi-threaded race its possible that one thread will be creating the EventSources while a 2nd thread + // exits this function and observes the s_EventSources list without the new EventSources in it. + // There is no known issue here having a small window of time where the pre-registered EventSources are not in + // the list as long as we still guarantee they get initialized in the near future and reported to the + // same EventListener.OnEventSourceCreated() callback. + Func[] factories; + lock(s_preregisteredEventSourceFactories) + { + factories = s_preregisteredEventSourceFactories.ToArray(); + s_preregisteredEventSourceFactories.Clear(); + } + foreach (Func factory in factories) + { + factory(); + } + } + + private static List> s_preregisteredEventSourceFactories = new List>(); + + private static OverrideEventProvider? TryGetPreregisteredEtwProvider(Guid id) + { + lock (s_preregisteredEtwProviders) + { + s_preregisteredEtwProviders.Remove(id, out OverrideEventProvider? provider); + return provider; + } + } + + private static readonly Dictionary s_preregisteredEtwProviders = new Dictionary(); + +#if FEATURE_PERFTRACING + private static OverrideEventProvider? TryGetPreregisteredEventPipeProvider(string name) + { + lock (s_preregisteredEventPipeProviders) + { + s_preregisteredEventPipeProviders.Remove(name, out OverrideEventProvider? provider); + return provider; + } + } + + private static readonly Dictionary s_preregisteredEventPipeProviders = new Dictionary(); +#endif + // private instance state private string m_name = null!; // My friendly name (privided in ctor) internal int m_id; // A small integer that is unique to this instance. @@ -4410,15 +4571,6 @@ internal static object EventListenersLock if (s_EventSources == null) { Interlocked.CompareExchange(ref s_EventSources, new List>(2), null); -#if FEATURE_PERFTRACING - // It is possible that another thread could observe the s_EventSources list at this point and it - // won't have the NativeRuntimeEventSource in it. In the past we guaranteed that the NativeRuntimeEventSource - // was always visible in the list by initializing it in the EventListener static constructor, however doing it - // that way triggered deadlocks between the static constructor and an OS ETW lock. There is no known issue here - // having a small window of time where NativeRuntimeEventSource is not in the list as long - // as we still guarantee it gets initialized eventually. - GC.KeepAlive(NativeRuntimeEventSource.Log); -#endif } return s_EventSources; } @@ -4426,6 +4578,10 @@ internal static object EventListenersLock private void CallBackForExistingEventSources(bool addToListenersList, EventHandler? callback) { + // Pre-registered EventSources may not have been constructed yet but we need to do so now to ensure they are + // reported to the EventListener. + EventSource.EnsurePreregisteredEventSourcesExist(); + lock (EventListenersLock) { Debug.Assert(s_EventSources != null); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs index f50d85e7007c6..558507211b17f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs @@ -14,6 +14,7 @@ namespace System.Diagnostics.Tracing [EventSourceAutoGenerate] internal sealed partial class RuntimeEventSource : EventSource { + internal static readonly Guid EventSourceGuid = new Guid("49592C0F-5A05-516D-AA4B-A64E02026C89"); internal const string EventSourceName = "System.Runtime"; public static class Keywords @@ -22,7 +23,7 @@ public static class Keywords public const EventKeywords ProcessorCount = (EventKeywords)0x2; } - private static RuntimeEventSource? s_RuntimeEventSource; + internal static RuntimeEventSource? Log => new RuntimeEventSource(); private PollingCounter? _gcHeapSizeCounter; private IncrementingPollingCounter? _gen0GCCounter; private IncrementingPollingCounter? _gen1GCCounter; @@ -51,21 +52,6 @@ public static class Keywords private PollingCounter? _methodsJittedCounter; private IncrementingPollingCounter? _jitTimeCounter; -#if NATIVEAOT - // If EventSource feature is enabled, RuntimeEventSource needs to be initialized for NativeAOT - // In CoreCLR, this is done via a call from the runtime as part of coreclr_initialize -#pragma warning disable CA2255 - [ModuleInitializer] -#pragma warning restore CA2255 -#endif - public static void Initialize() - { - // initializing more than once may lead to missing events - Debug.Assert(s_RuntimeEventSource == null); - if (IsSupported) - s_RuntimeEventSource = new RuntimeEventSource(); - } - // Parameterized constructor to block initialization and ensure the EventSourceGenerator is creating the default constructor // as you can't make a constructor partial. private RuntimeEventSource(int _) { } diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c index a8890ca4bf66e..c75bb43007630 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.c +++ b/src/mono/mono/eventpipe/ep-rt-mono.c @@ -838,9 +838,9 @@ ep_rt_mono_init_finish (void) // Managed init of diagnostics classes, like registration of RuntimeEventSource (if available). ERROR_DECL (error); - MonoClass *runtime_event_source = mono_class_from_name_checked (mono_get_corlib (), "System.Diagnostics.Tracing", "RuntimeEventSource", error); - if (is_ok (error) && runtime_event_source) { - MonoMethod *init = mono_class_get_method_from_name_checked (runtime_event_source, "Initialize", -1, 0, error); + MonoClass *event_source = mono_class_from_name_checked (mono_get_corlib (), "System.Diagnostics.Tracing", "EventSource", error); + if (is_ok (error) && event_source) { + MonoMethod *init = mono_class_get_method_from_name_checked (event_source, "InitializeDefaultEventSources", -1, 0, error); if (is_ok (error) && init) { mono_runtime_try_invoke_handle (init, NULL_HANDLE, NULL, error); }