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);
}