From 21f579b5a42f2c974b3d3fa1c5156ae981e4e0a0 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 29 Oct 2025 19:16:42 +0100 Subject: [PATCH 01/21] 1) Remove `[EventSourceAutoGenerate]`, we rely on just [EventSource] + no explicit ctors 2) Introduce a new global SourceGenerators - EventSourceGenerator (and move the existing impl from SPC.Generators to this new project) 3) Update slnx files (via the UpdateSolutionFiles task) 4) Migrate all classes with [EventSource] to use the SG. Except for the ones with EtwSelfDescribingEventFormat --- eng/generators.targets | 12 ++++++++++ .../PerfEventSource.cs | 4 +--- .../Compiler/PerfEventSource.cs | 4 +--- src/libraries/NetCoreAppLibrary.props | 1 + .../Concurrent/CDSCollectionETWBCLProvider.cs | 4 +--- .../Data/Common/DataCommonEventSource.cs | 2 +- .../Data/Common/DataCommonEventSource.cs | 2 +- .../Diagnostics/Metrics/MetricsEventSource.cs | 11 ++-------- .../ref/System.Diagnostics.Tracing.cs | 3 +++ .../Linq/Parallel/Utils/PLINQETWProvider.cs | 4 +--- .../Net/Http/NetEventSource.WinHttpHandler.cs | 5 +---- .../src/System/Net/Http/HttpTelemetry.cs | 9 +------- .../System/Net/Http/NetEventSource.Http.cs | 6 +---- .../System/Net/NetEventSource.HttpListener.cs | 5 +---- .../System/Net/Mail/NetEventSource.Mail.cs | 5 +---- .../src/System/Net/NameResolutionTelemetry.cs | 11 ++-------- .../Net/NetEventSource.NameResolution.cs | 5 +---- .../NetEventSource.NetworkInformation.cs | 8 ++----- .../System/Net/NetEventSource.Primitives.cs | 5 +---- .../System/Net/Quic/NetEventSource.Quic.cs | 6 +---- .../src/System/Net/NetEventSource.Requests.cs | 5 +---- .../Net/Security/NetEventSource.Security.cs | 6 +---- .../Net/Security/NetSecurityTelemetry.cs | 11 ++-------- .../Net/Sockets/NetEventSource.Sockets.cs | 6 +---- .../System/Net/Sockets/SocketsTelemetry.cs | 11 ++-------- .../WebSockets/NetEventSource.WebSockets.cs | 6 +---- .../gen/EventSourceGenerator.Emitter.cs | 4 +++- .../gen/EventSourceGenerator.Parser.cs | 18 ++++++++++++++- .../gen/EventSourceGenerator.cs | 7 +++--- .../gen/EventSourceGenerator.csproj | 22 +++++++++++++++++++ .../System.Private.CoreLib.Generators.csproj | 3 --- .../System/Buffers/ArrayPoolEventSource.cs | 5 ----- .../System/Diagnostics/Tracing/EventSource.cs | 12 +++------- .../Tracing/FrameworkEventSource.cs | 5 ----- .../Tracing/NativeRuntimeEventSource.cs | 5 ----- .../Diagnostics/Tracing/RuntimeEventSource.cs | 5 ----- .../TraceLogging/TraceLoggingEventSource.cs | 2 +- .../System/Threading/Tasks/TplEventSource.cs | 5 ----- .../XmlSerializationEventSource.cs | 11 ++-------- .../Binary/BinaryFormatterEventSource.cs | 6 +---- .../OpenSslX509ChainEventSource.cs | 11 ++-------- .../src/Internal/DataflowEtwProvider.cs | 4 +--- .../Threading/Tasks/ParallelETWProvider.cs | 5 +---- .../System/Threading/CDSsyncETWBCLProvider.cs | 3 +-- .../Transactions/TransactionsEtwProvider.cs | 3 +-- 45 files changed, 102 insertions(+), 191 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.csproj diff --git a/eng/generators.targets b/eng/generators.targets index 1a25554a78f1b5..0c4188723a2bab 100644 --- a/eng/generators.targets +++ b/eng/generators.targets @@ -40,6 +40,13 @@ '$(DisableImplicitFrameworkReferences)' == 'true' and '@(ProjectReference->AnyHaveMetadataValue('Filename', 'System.Runtime.InteropServices'))' == 'true' )" /> + + + ComInterfaceGenerator; + EventSourceGenerator; LibraryImportGenerator; JSImportGenerator; Microsoft.Interop.SourceGeneration; diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs index 1eff615ae941b6..0437ae575efc4f 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs @@ -19,15 +19,13 @@ namespace System.Collections.Concurrent Name = "System.Collections.Concurrent.ConcurrentCollectionsEventSource", Guid = "35167F8E-49B2-4b96-AB86-435B59336B5E" )] - internal sealed class CDSCollectionETWBCLProvider : EventSource + internal sealed partial class CDSCollectionETWBCLProvider : EventSource { /// /// Defines the singleton instance for the collection ETW provider. /// The collection provider GUID is {35167F8E-49B2-4b96-AB86-435B59336B5E}. /// public static readonly CDSCollectionETWBCLProvider Log = new CDSCollectionETWBCLProvider(); - /// Prevent external instantiation. All logging should go through the Log instance. - private CDSCollectionETWBCLProvider() { } /// Enabled for all keywords. private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1); diff --git a/src/libraries/System.Data.Common/src/System/Data/Common/DataCommonEventSource.cs b/src/libraries/System.Data.Common/src/System/Data/Common/DataCommonEventSource.cs index 0144c53cf75220..3d32b06bb666ce 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Common/DataCommonEventSource.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Common/DataCommonEventSource.cs @@ -7,7 +7,7 @@ namespace System.Data { [EventSource(Name = "System.Data.DataCommonEventSource")] - internal sealed class DataCommonEventSource : EventSource + internal sealed partial class DataCommonEventSource : EventSource { internal static readonly DataCommonEventSource Log = new DataCommonEventSource(); private static long s_nextScopeId; diff --git a/src/libraries/System.Data.OleDb/src/System/Data/Common/DataCommonEventSource.cs b/src/libraries/System.Data.OleDb/src/System/Data/Common/DataCommonEventSource.cs index 5fc0234b3c9b98..5dd2d1a511aced 100644 --- a/src/libraries/System.Data.OleDb/src/System/Data/Common/DataCommonEventSource.cs +++ b/src/libraries/System.Data.OleDb/src/System/Data/Common/DataCommonEventSource.cs @@ -7,7 +7,7 @@ namespace System.Data { [EventSource(Name = "System.Data.DataCommonEventSource")] - internal sealed class DataCommonEventSource : EventSource + internal sealed partial class DataCommonEventSource : EventSource { internal static readonly DataCommonEventSource Log = new DataCommonEventSource(); private const int TraceEventId = 1; 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 9656e8303c186b..6e32ccb5dab21d 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 @@ -48,11 +48,9 @@ namespace System.Diagnostics.Metrics /// not counting the special zero bucket. The default value is 160. /// o reportDeltas - If true, the histogram will report deltas instead of whole accumulated values. The default value is false. /// - [EventSource(Name = MetricsEventSourceName)] - internal sealed class MetricsEventSource : EventSource + [EventSource(Name = "System.Diagnostics.Metrics")] + internal sealed partial class MetricsEventSource : EventSource { - private const string MetricsEventSourceName = "System.Diagnostics.Metrics"; - 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 @@ -98,11 +96,6 @@ private CommandHandler Handler } } - private MetricsEventSource() - : base(MetricsEventSourceName, EventSourceSettings.EtwManifestEventFormat) - { - } - /// /// Used to send ad-hoc diagnostics to humans. /// diff --git a/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs b/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs index 30f85c26f85250..67355b30bd10d2 100644 --- a/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs +++ b/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs @@ -155,6 +155,9 @@ protected EventSource(System.Diagnostics.Tracing.EventSourceSettings settings, p public EventSource(string eventSourceName) { } public EventSource(string eventSourceName, System.Diagnostics.Tracing.EventSourceSettings config) { } public EventSource(string eventSourceName, System.Diagnostics.Tracing.EventSourceSettings config, params string[]? traits) { } + public EventSource(string eventSourceName, Guid eventSourceGuid) { } + public EventSource(string eventSourceName, Guid eventSourceGuid, System.Diagnostics.Tracing.EventSourceSettings settings, params string[]? traits) { } + public System.Exception? ConstructionException { get { throw null; } } public static System.Guid CurrentThreadActivityId { get { throw null; } } public System.Guid Guid { get { throw null; } } diff --git a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs index 590dbce5a518cc..9d37055e6262c0 100644 --- a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs +++ b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs @@ -22,15 +22,13 @@ namespace System.Linq.Parallel [EventSource( Name = "System.Linq.Parallel.PlinqEventSource", Guid = "159eeeec-4a14-4418-a8fe-faabcd987887")] - internal sealed class PlinqEtwProvider : EventSource + internal sealed partial class PlinqEtwProvider : EventSource { /// /// Defines the singleton instance for the PLINQ ETW provider. /// The PLINQ Event provider GUID is {159eeeec-4a14-4418-a8fe-faabcd987887}. /// internal static readonly PlinqEtwProvider Log = new PlinqEtwProvider(); - /// Prevent external instantiation. All logging should go through the Log instance. - private PlinqEtwProvider() { } /// Cached id for the default scheduler. /// If PLINQ ever supports other schedulers, that information will need to be passed into the query events. diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NetEventSource.WinHttpHandler.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NetEventSource.WinHttpHandler.cs index c3fc2335d362e4..d6a6adb8143708 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NetEventSource.WinHttpHandler.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/NetEventSource.WinHttpHandler.cs @@ -5,11 +5,8 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.Http.WinHttpHandler")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.Http.WinHttpHandler"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs index 1c7a6ce5f36b86..f06fb5c0314379 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs @@ -9,16 +9,9 @@ namespace System.Net.Http { - [EventSource(Name = HttpTelemetryName)] + [EventSource(Name = "System.Net.Http")] internal sealed partial class HttpTelemetry : EventSource { - private const string HttpTelemetryName = "System.Net.Http"; - - public HttpTelemetry() - : base(HttpTelemetryName, EventSourceSettings.EtwManifestEventFormat) - { - } - public static readonly HttpTelemetry Log = new HttpTelemetry(); public static class Keywords diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/NetEventSource.Http.cs b/src/libraries/System.Net.Http/src/System/Net/Http/NetEventSource.Http.cs index d3ba13ff485e2a..95c5af48e6c12a 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/NetEventSource.Http.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/NetEventSource.Http.cs @@ -7,13 +7,9 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.Http")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.Http"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } - private const int UriBaseAddressId = NextAvailableEventId; private const int ContentNullId = UriBaseAddressId + 1; private const int HeadersInvalidValueId = ContentNullId + 1; diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/NetEventSource.HttpListener.cs b/src/libraries/System.Net.HttpListener/src/System/Net/NetEventSource.HttpListener.cs index a7b68f1952b748..3ef05bd677c08a 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/NetEventSource.HttpListener.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/NetEventSource.HttpListener.cs @@ -5,11 +5,8 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.HttpListener")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.HttpListener"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } } } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/NetEventSource.Mail.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/NetEventSource.Mail.cs index fabf71247ec6c5..d7589a6846c717 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/NetEventSource.Mail.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/NetEventSource.Mail.cs @@ -7,11 +7,8 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.Mail")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.Mail"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } } } diff --git a/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionTelemetry.cs b/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionTelemetry.cs index e7b4266701ad8a..59c2b47cc00a3a 100644 --- a/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionTelemetry.cs +++ b/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionTelemetry.cs @@ -9,16 +9,9 @@ namespace System.Net { - [EventSource(Name = NameResolutionTelemetryName)] - internal sealed class NameResolutionTelemetry : EventSource + [EventSource(Name = "System.Net.NameResolution")] + internal sealed partial class NameResolutionTelemetry : EventSource { - private const string NameResolutionTelemetryName = "System.Net.NameResolution"; - - public NameResolutionTelemetry() - : base(NameResolutionTelemetryName, EventSourceSettings.EtwManifestEventFormat) - { - } - public static readonly NameResolutionTelemetry Log = new NameResolutionTelemetry(); private const int ResolutionStartEventId = 1; diff --git a/src/libraries/System.Net.NameResolution/src/System/Net/NetEventSource.NameResolution.cs b/src/libraries/System.Net.NameResolution/src/System/Net/NetEventSource.NameResolution.cs index e4ef4f752ab1c6..89ec14ab2edd6e 100644 --- a/src/libraries/System.Net.NameResolution/src/System/Net/NetEventSource.NameResolution.cs +++ b/src/libraries/System.Net.NameResolution/src/System/Net/NetEventSource.NameResolution.cs @@ -5,11 +5,8 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.NameResolution")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.NameResolution"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetEventSource.NetworkInformation.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetEventSource.NetworkInformation.cs index 74c8ec1e8228bd..d6293b9101ec4d 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetEventSource.NetworkInformation.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetEventSource.NetworkInformation.cs @@ -7,13 +7,9 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] - internal sealed class NetEventSource : EventSource + [EventSource(Name = "Private.InternalDiagnostics.System.Net.NetworkInformation")] + internal sealed partial class NetEventSource : EventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.NetworkInformation"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } - public static readonly NetEventSource Log = new NetEventSource(); private const int ErrorEventId = 2; diff --git a/src/libraries/System.Net.Primitives/src/System/Net/NetEventSource.Primitives.cs b/src/libraries/System.Net.Primitives/src/System/Net/NetEventSource.Primitives.cs index 58c50d26c6ef16..271827788686da 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/NetEventSource.Primitives.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/NetEventSource.Primitives.cs @@ -5,11 +5,8 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.Primitives")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.Primitives"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.cs index 7e1ea926160686..37dbeab080837c 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.cs @@ -6,13 +6,9 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.Quic")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.Quic"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } - static partial void AdditionalCustomizedToString(object value, ref string? result) { if (value is MsQuicSafeHandle safeHandle) diff --git a/src/libraries/System.Net.Requests/src/System/Net/NetEventSource.Requests.cs b/src/libraries/System.Net.Requests/src/System/Net/NetEventSource.Requests.cs index 070684e7b45b61..1d1e4e3a23bbfc 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/NetEventSource.Requests.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/NetEventSource.Requests.cs @@ -5,11 +5,8 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.Requests")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.Requests"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } } } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/NetEventSource.Security.cs b/src/libraries/System.Net.Security/src/System/Net/Security/NetEventSource.Security.cs index 5835dec28d18c7..5ca0be27a35723 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/NetEventSource.Security.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/NetEventSource.Security.cs @@ -11,13 +11,9 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.Security")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.Security"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } - #if WINDOWS // More events are defined in NetEventSource.Security.Windows.cs private const int LocatingPrivateKeyId = OperationReturnedSomethingId + 1; diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs b/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs index 2be354f4a71ce1..ac71e2127e43d5 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs @@ -9,16 +9,9 @@ namespace System.Net.Security { - [EventSource(Name = NetSecurityTelemetryName)] - internal sealed class NetSecurityTelemetry : EventSource + [EventSource(Name = "System.Net.Security")] + internal sealed partial class NetSecurityTelemetry : EventSource { - private const string NetSecurityTelemetryName = "System.Net.Security"; - - public NetSecurityTelemetry() - : base(NetSecurityTelemetryName, EventSourceSettings.EtwManifestEventFormat) - { - } - private const string ActivitySourceName = "Experimental.System.Net.Security"; private const string ActivityName = ActivitySourceName + ".TlsHandshake"; diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetEventSource.Sockets.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetEventSource.Sockets.cs index 99669d885af960..ed5460ffcb7c94 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetEventSource.Sockets.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetEventSource.Sockets.cs @@ -7,13 +7,9 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.Sockets")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.Sockets"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } - private const int AcceptedId = NextAvailableEventId; private const int ConnectedId = AcceptedId + 1; private const int ConnectedAsyncDnsId = ConnectedId + 1; diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketsTelemetry.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketsTelemetry.cs index 3507638bc2ca20..1171961a204351 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketsTelemetry.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketsTelemetry.cs @@ -7,16 +7,9 @@ namespace System.Net.Sockets { - [EventSource(Name = SocketsTelemetryName)] - internal sealed class SocketsTelemetry : EventSource + [EventSource(Name = "System.Net.Sockets")] + internal sealed partial class SocketsTelemetry : EventSource { - private const string SocketsTelemetryName = "System.Net.Sockets"; - - public SocketsTelemetry() - : base(SocketsTelemetryName, EventSourceSettings.EtwManifestEventFormat) - { - } - private const string ActivitySourceName = "Experimental.System.Net.Sockets"; private const string ConnectActivityName = ActivitySourceName + ".Connect"; private static readonly ActivitySource s_connectActivitySource = new ActivitySource(ActivitySourceName); diff --git a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/NetEventSource.WebSockets.cs b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/NetEventSource.WebSockets.cs index 4f8ae05d2fbe20..fceeadd862d3c6 100644 --- a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/NetEventSource.WebSockets.cs +++ b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/NetEventSource.WebSockets.cs @@ -8,13 +8,9 @@ namespace System.Net { - [EventSource(Name = NetEventSourceName)] + [EventSource(Name = "Private.InternalDiagnostics.System.Net.WebSockets")] internal sealed partial class NetEventSource { - private const string NetEventSourceName = "Private.InternalDiagnostics.System.Net.WebSockets"; - - public NetEventSource() : base(NetEventSourceName, EventSourceSettings.EtwManifestEventFormat) { } - // NOTE // - The 'Start' and 'Stop' suffixes on the following event names have special meaning in EventSource. They // enable creating 'activities'. diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs index 2dcedb1b435ce8..d711d3f403ad6f 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs @@ -57,12 +57,13 @@ partial class {ec.ClassName} private static void GenerateConstructor(EventSourceClass ec, StringBuilder sb) { sb.AppendLine($@" - private {ec.ClassName}() : base(new Guid({ec.Guid.ToString("x").Replace("{", "").Replace("}", "")}), ""{ec.SourceName}"") {{ }}"); + private {ec.ClassName}() : base(""{ec.SourceName}"", new Guid({ec.Guid.ToString("x").Replace("{", "").Replace("}", "")})) {{ }}"); } private static void GenerateProviderMetadata(string sourceName, StringBuilder sb) { sb.Append(@" +#if SYSTEM_PRIVATE_CORELIB private protected override ReadOnlySpan ProviderMetadata => new byte[] { "); byte[] metadataBytes = MetadataForString(sourceName); @@ -72,6 +73,7 @@ private static void GenerateProviderMetadata(string sourceName, StringBuilder sb } sb.AppendLine(@"};"); + sb.AppendLine("#endif"); } // From System.Private.CoreLib diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index fa2e1a2fc8598e..945b141fd9ff3f 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Generators @@ -40,6 +41,21 @@ public partial class EventSourceGenerator continue; } + foreach (MemberDeclarationSyntax member in classDef.Members) + { + if (member is ConstructorDeclarationSyntax ctor) + { + foreach (SyntaxToken ctorModifier in ctor.Modifiers) + { + if (!ctorModifier.IsKind(SyntaxKind.StaticKeyword)) + { + // Contains an explicit constructor, skip generation + return null; + } + } + } + } + nspace ??= ConstructNamespace(ns); string className = classDef.Identifier.ValueText; @@ -75,7 +91,7 @@ public partial class EventSourceGenerator return eventSourceClass; } - private static string? ConstructNamespace(NamespaceDeclarationSyntax? ns) + private static string ConstructNamespace(NamespaceDeclarationSyntax? ns) { if (ns is null) return string.Empty; diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index 90ea79020dda9f..5345cf3104a10e 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -16,7 +16,6 @@ public partial class EventSourceGenerator : IIncrementalGenerator // Example input: // // [EventSource(Guid = "49592C0F-5A05-516D-AA4B-A64E02026C89", Name = "System.Runtime")] - // [EventSourceAutoGenerate] // internal sealed partial class RuntimeEventSource : EventSource // // Example generated output: @@ -27,7 +26,7 @@ public partial class EventSourceGenerator : IIncrementalGenerator // { // partial class RuntimeEventSource // { - // private RuntimeEventSource() : base(new Guid(0x49592c0f,0x5a05,0x516d,0xaa,0x4b,0xa6,0x4e,0x02,0x02,0x6c,0x89), "System.Runtime") { } + // private RuntimeEventSource() : base("System.Runtime", new Guid(0x49592c0f,0x5a05,0x516d,0xaa,0x4b,0xa6,0x4e,0x02,0x02,0x6c,0x89)) { } // // private protected override ReadOnlySpan ProviderMetadata => new byte[] { 0x11, 0x0, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x0, }; // } @@ -35,11 +34,11 @@ public partial class EventSourceGenerator : IIncrementalGenerator public void Initialize(IncrementalGeneratorInitializationContext context) { - const string EventSourceAutoGenerateAttribute = "System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"; + const string EventSourceAttribute = "System.Diagnostics.Tracing.EventSourceAttribute"; IncrementalValuesProvider eventSourceClasses = context.SyntaxProvider.ForAttributeWithMetadataName( - EventSourceAutoGenerateAttribute, + EventSourceAttribute, (node, _) => node is ClassDeclarationSyntax, GetSemanticTargetForGeneration) .Where(x => x is not null); diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.csproj b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.csproj new file mode 100644 index 00000000000000..11e72b22f18b6c --- /dev/null +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.csproj @@ -0,0 +1,22 @@ + + + netstandard2.0 + $(NoWarn);CS3001 + true + + + $(DefineConstants);STABILIZE_PACKAGE_VERSION + + + + + + + + + + + + + + diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index 79a254539cee71..f5aa981c3a3c76 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -10,9 +10,6 @@ - - - diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/ArrayPoolEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/ArrayPoolEventSource.cs index b2855224fc12e4..8a0f9582864941 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/ArrayPoolEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/ArrayPoolEventSource.cs @@ -7,7 +7,6 @@ namespace System.Buffers { [EventSource(Guid = "0866B2B8-5CEF-5DB9-2612-0C0FFD814A44", Name = "System.Buffers.ArrayPoolEventSource")] - [EventSourceAutoGenerate] internal sealed partial class ArrayPoolEventSource : EventSource { private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; @@ -36,10 +35,6 @@ internal enum BufferDroppedReason : int OverMaximumSize, } - // Parameterized constructor to block initialization and ensure the EventSourceGenerator is creating the default constructor - // as you can't make a constructor partial. - private ArrayPoolEventSource(int _) { } - /// /// Event for when a buffer is rented. This is invoked once for every successful call to Rent, /// regardless of whether a buffer is allocated or a buffer is taken from the pool. In a 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 50c72800319882..9407cc9426d617 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 @@ -177,12 +177,6 @@ namespace System.Diagnostics.Tracing { - [Conditional("NEEDED_FOR_SOURCE_GENERATOR_ONLY")] - [AttributeUsage(AttributeTargets.Class)] - internal sealed class EventSourceAutoGenerateAttribute : Attribute - { - } - /// /// This class is meant to be inherited by a user-defined event source in order to define a managed /// ETW provider. Please See DESIGN NOTES above for the internal architecture. @@ -1612,12 +1606,12 @@ private unsafe void WriteEventRaw( // FrameworkEventSource is on the startup path for the framework, so we have this internal overload that it can use // to prevent the working set hit from looking at the custom attributes on the type to get the Guid. - internal EventSource(Guid eventSourceGuid, string eventSourceName) - : this(eventSourceGuid, eventSourceName, EventSourceSettings.EtwManifestEventFormat) + public EventSource(string eventSourceName, Guid eventSourceGuid) + : this(eventSourceName, eventSourceGuid, EventSourceSettings.EtwManifestEventFormat) { } // Used by the internal FrameworkEventSource constructor and the TraceLogging-style event source constructor - internal EventSource(Guid eventSourceGuid, string eventSourceName, EventSourceSettings settings, string[]? traits = null) + public EventSource(string eventSourceName, Guid eventSourceGuid, EventSourceSettings settings, string[]? traits = null) { if (IsSupported) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs index 264f4a6bc85576..20f76ff9b646fe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs @@ -7,7 +7,6 @@ namespace System.Diagnostics.Tracing { [EventSource(Guid = "8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1", Name = "System.Diagnostics.Eventing.FrameworkEventSource")] - [EventSourceAutoGenerate] internal sealed partial class FrameworkEventSource : EventSource { private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; @@ -30,10 +29,6 @@ public static class Keywords public const EventTask ThreadTransfer = (EventTask)3; } - // Parameterized constructor to block initialization and ensure the EventSourceGenerator is creating the default constructor - // as you can't make a constructor partial. - private FrameworkEventSource(int _) { } - // optimized for common signatures (used by the ThreadTransferSend/Receive events) [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.cs index 092cd3af35d078..0f1b7817bc202d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/NativeRuntimeEventSource.cs @@ -23,7 +23,6 @@ namespace System.Diagnostics.Tracing /// for the native platform. /// [EventSource(Guid = "E13C0D23-CCBC-4E12-931B-D9CC2EEE27E4", Name = EventSourceName)] - [EventSourceAutoGenerate] internal sealed partial class NativeRuntimeEventSource : EventSource { internal const string EventSourceName = "Microsoft-Windows-DotNETRuntime"; @@ -34,10 +33,6 @@ internal sealed partial class NativeRuntimeEventSource : EventSource // pools would be in moderate use. private const ushort DefaultClrInstanceId = 0; - // Parameterized constructor to block initialization and ensure the EventSourceGenerator is creating the default constructor - // as you can't make a constructor partial. - private NativeRuntimeEventSource(int _) { } - #if FEATURE_PERFTRACING /// /// Dispatch a single event with the specified event ID and payload. 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 30f62f7b4d5769..be2c9e72b1ea8b 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 @@ -11,7 +11,6 @@ namespace System.Diagnostics.Tracing /// RuntimeEventSource is an EventSource that represents events emitted by the managed runtime. /// [EventSource(Guid = "49592C0F-5A05-516D-AA4B-A64E02026C89", Name = EventSourceName)] - [EventSourceAutoGenerate] internal sealed partial class RuntimeEventSource : EventSource { internal const string EventSourceName = "System.Runtime"; @@ -52,10 +51,6 @@ public static class Keywords private PollingCounter? _methodsJittedCounter; private IncrementingPollingCounter? _jitTimeCounter; - // 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 _) { } - private enum EventId : int { AppContextSwitch = 1, diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs index 20c6c8516d9f40..e18a27209475cf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs @@ -70,8 +70,8 @@ public EventSource( EventSourceSettings config, params string[]? traits) : this( - GenerateGuidFromName((eventSourceName ?? throw new ArgumentNullException(nameof(eventSourceName))).ToUpperInvariant()), eventSourceName, + GenerateGuidFromName((eventSourceName ?? throw new ArgumentNullException(nameof(eventSourceName))).ToUpperInvariant()), config, traits) { } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs index 16eee9081ceb96..5418d665ab43b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs @@ -12,7 +12,6 @@ namespace System.Threading.Tasks Name = "System.Threading.Tasks.TplEventSource", Guid = "2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5" )] - [EventSourceAutoGenerate] internal sealed partial class TplEventSource : EventSource { private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; @@ -42,10 +41,6 @@ protected override void OnEventCommand(EventCommandEventArgs command) /// public static readonly TplEventSource Log = new TplEventSource(); - // Parameterized constructor to block initialization and ensure the EventSourceGenerator is creating the default constructor - // as you can't make a constructor partial. - private TplEventSource(int _) { } - /// Configured behavior of a task wait operation. public enum TaskWaitBehavior : int { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationEventSource.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationEventSource.cs index ca093164ff6094..b68ecb2b86f666 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationEventSource.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationEventSource.cs @@ -5,16 +5,9 @@ namespace System.Xml.Serialization { - [EventSource(Name = XmlSerializationEventSourceName)] - internal sealed class XmlSerializationEventSource : EventSource + [EventSource(Name = "System.Xml.Serialzation.XmlSerialization")] + internal sealed partial class XmlSerializationEventSource : EventSource { - private const string XmlSerializationEventSourceName = "System.Xml.Serialzation.XmlSerialization"; - - public XmlSerializationEventSource() - : base(XmlSerializationEventSourceName, EventSourceSettings.EtwManifestEventFormat) - { - } - internal static readonly XmlSerializationEventSource Log = new XmlSerializationEventSource(); [Event(EventIds.XmlSerializerExpired, Level = EventLevel.Informational)] diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatterEventSource.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatterEventSource.cs index 70ebce0d4e004e..3fc9a9006b90f8 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatterEventSource.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatterEventSource.cs @@ -8,7 +8,7 @@ namespace System.Runtime.Serialization.Formatters.Binary { [EventSource( Name = "System.Runtime.Serialization.Formatters.Binary.BinaryFormatterEventSource")] - internal sealed class BinaryFormatterEventSource : EventSource + internal sealed partial class BinaryFormatterEventSource : EventSource { private const int EventId_SerializationStart = 10; private const int EventId_SerializationStop = 11; @@ -19,10 +19,6 @@ internal sealed class BinaryFormatterEventSource : EventSource public static readonly BinaryFormatterEventSource Log = new BinaryFormatterEventSource(); - private BinaryFormatterEventSource() - { - } - [Event(EventId_SerializationStart, Opcode = EventOpcode.Start, Keywords = Keywords.Serialization, Level = EventLevel.Informational, ActivityOptions = EventActivityOptions.Recursive)] public void SerializationStart() { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainEventSource.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainEventSource.cs index 726b3486d939bf..3facb39ae1320c 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainEventSource.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainEventSource.cs @@ -7,16 +7,9 @@ namespace System.Security.Cryptography.X509Certificates { - [EventSource(Name = OpenSslX509ChainEventSourceName)] - internal sealed class OpenSslX509ChainEventSource : EventSource + [EventSource(Name = "System.Security.Cryptography.X509Certificates.X509Chain.OpenSsl")] + internal sealed partial class OpenSslX509ChainEventSource : EventSource { - private const string OpenSslX509ChainEventSourceName = "System.Security.Cryptography.X509Certificates.X509Chain.OpenSsl"; - - public OpenSslX509ChainEventSource() - : base(OpenSslX509ChainEventSourceName, EventSourceSettings.EtwManifestEventFormat) - { - } - internal static readonly OpenSslX509ChainEventSource Log = new OpenSslX509ChainEventSource(); private const int EventId_ChainStart = 1; diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs index 2f17ecf0cc8441..25184973162486 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs @@ -22,15 +22,13 @@ namespace System.Threading.Tasks.Dataflow.Internal [EventSource( Name = "System.Threading.Tasks.Dataflow.DataflowEventSource", Guid = "16F53577-E41D-43D4-B47E-C17025BF4025")] - internal sealed class DataflowEtwProvider : EventSource + internal sealed partial class DataflowEtwProvider : EventSource { /// /// Defines the singleton instance for the dataflow ETW provider. /// The dataflow provider GUID is {16F53577-E41D-43D4-B47E-C17025BF4025}. /// internal static readonly DataflowEtwProvider Log = new DataflowEtwProvider(); - /// Prevent external instantiation. All logging should go through the Log instance. - private DataflowEtwProvider() { } /// Enabled for all keywords. private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1); diff --git a/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/ParallelETWProvider.cs b/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/ParallelETWProvider.cs index 3e92c6790bb58c..d3e735115c9f2b 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/ParallelETWProvider.cs +++ b/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/ParallelETWProvider.cs @@ -18,7 +18,7 @@ namespace System.Threading.Tasks { /// Provides an event source for tracing TPL information. [EventSource(Name = "System.Threading.Tasks.Parallel.EventSource")] - internal sealed class ParallelEtwProvider : EventSource + internal sealed partial class ParallelEtwProvider : EventSource { private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; /// @@ -26,9 +26,6 @@ internal sealed class ParallelEtwProvider : EventSource /// public static readonly ParallelEtwProvider Log = new ParallelEtwProvider(); - /// Prevent external instantiation. All logging should go through the Log instance. - private ParallelEtwProvider() { } - /// Type of a fork/join operation. public enum ForkJoinOperationType { diff --git a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs index 64f46a74635bc4..a64dc0fa2120ef 100644 --- a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs +++ b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs @@ -25,7 +25,7 @@ namespace System.Threading Name = "System.Threading.SynchronizationEventSource", Guid = "EC631D38-466B-4290-9306-834971BA0217" )] - internal sealed class CdsSyncEtwBCLProvider : EventSource + internal sealed partial class CdsSyncEtwBCLProvider : EventSource { /// /// Defines the singleton instance for the CDS Sync ETW provider. @@ -33,7 +33,6 @@ internal sealed class CdsSyncEtwBCLProvider : EventSource /// public static readonly CdsSyncEtwBCLProvider Log = new CdsSyncEtwBCLProvider(); /// Prevent external instantiation. All logging should go through the Log instance. - private CdsSyncEtwBCLProvider() { } /// Enabled for all keywords. private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs index 39ab21b8049674..39d7ab50528f54 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs @@ -74,7 +74,7 @@ internal enum TraceSourceType [EventSource( Name = "System.Transactions.TransactionsEventSource", Guid = "8ac2d80a-1f1a-431b-ace4-bff8824aef0b")] - internal sealed class TransactionsEtwProvider : EventSource + internal sealed partial class TransactionsEtwProvider : EventSource { /// /// Defines the singleton instance for the Transactions ETW provider. @@ -85,7 +85,6 @@ internal sealed class TransactionsEtwProvider : EventSource internal static readonly TransactionsEtwProvider Log = new TransactionsEtwProvider(); /// Prevent external instantiation. All logging should go through the Log instance. - private TransactionsEtwProvider() { } /// Enabled for all keywords. private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1); From f5dbdd24e8091a28a07841a9d3381ada7e52d9b8 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 30 Oct 2025 02:01:46 +0100 Subject: [PATCH 02/21] fix build --- .../tests/BasicEventSourceTest/ActivityTracking.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/ActivityTracking.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/ActivityTracking.cs index e975859721f929..bfd7263e6e9ac8 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/ActivityTracking.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/ActivityTracking.cs @@ -164,6 +164,8 @@ public async Task SetCurrentActivityIdAfterEventDoesNotFlowAsync() [EventSource(Name = "ActivityEventSource")] class ActivityEventSource : EventSource { + public ActivityEventSource() { } + [Event(1)] public void ExampleStart() => WriteEvent(1); From 62433fe76f3f866e42b9f979760d2a2908453a66 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 30 Oct 2025 02:09:44 +0100 Subject: [PATCH 03/21] cleanup --- eng/generators.targets | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/eng/generators.targets b/eng/generators.targets index 0c4188723a2bab..c24eca9be55dd1 100644 --- a/eng/generators.targets +++ b/eng/generators.targets @@ -44,9 +44,8 @@ + '$(DisableImplicitFrameworkReferences)' == 'true' + " /> ProviderMetadata => new byte[] { "); + private protected override ReadOnlySpan ProviderMetadata => ["); byte[] metadataBytes = MetadataForString(sourceName); foreach (byte b in metadataBytes) @@ -72,8 +74,7 @@ private static void GenerateProviderMetadata(string sourceName, StringBuilder sb sb.Append($"0x{b:x}, "); } - sb.AppendLine(@"};"); - sb.AppendLine("#endif"); + sb.AppendLine(@"];"); } // From System.Private.CoreLib diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index 945b141fd9ff3f..964ccea627d378 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -84,7 +84,17 @@ public partial class EventSourceGenerator result = GenerateGuidFromName(name.ToUpperInvariant()); } - eventSourceClass = new EventSourceClass(nspace, className, name, result); + bool hasProviderMetadataProperty = false; + foreach (MemberDeclarationSyntax member in classDef.Members) + { + if (member is PropertyDeclarationSyntax prop && prop.Identifier.Text == "ProviderMetadata") + { + hasProviderMetadataProperty = true; + break; + } + } + + eventSourceClass = new EventSourceClass(nspace, className, name, result, hasProviderMetadataProperty); continue; } diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index 5345cf3104a10e..09c4ae5171ea88 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -46,6 +46,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.RegisterSourceOutput(eventSourceClasses, EmitSourceFile); } - private sealed record EventSourceClass(string Namespace, string ClassName, string SourceName, Guid Guid); + private sealed record EventSourceClass(string Namespace, string ClassName, string SourceName, Guid Guid, bool HasProviderMetadataProperty); } } diff --git a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs index a64dc0fa2120ef..97a440d6cf9153 100644 --- a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs +++ b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs @@ -32,7 +32,6 @@ internal sealed partial class CdsSyncEtwBCLProvider : EventSource /// The CDS Sync Event provider GUID is {EC631D38-466B-4290-9306-834971BA0217}. /// public static readonly CdsSyncEtwBCLProvider Log = new CdsSyncEtwBCLProvider(); - /// Prevent external instantiation. All logging should go through the Log instance. /// Enabled for all keywords. private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs index 39d7ab50528f54..8c20cbbbbe3169 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs @@ -80,11 +80,7 @@ internal sealed partial class TransactionsEtwProvider : EventSource /// Defines the singleton instance for the Transactions ETW provider. /// The Transactions provider GUID is {8ac2d80a-1f1a-431b-ace4-bff8824aef0b}. /// - /// - - internal static readonly TransactionsEtwProvider Log = new TransactionsEtwProvider(); - /// Prevent external instantiation. All logging should go through the Log instance. /// Enabled for all keywords. private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1); From 20d795315ff8fc33df1bd7091e89c976c65d83b0 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Tue, 4 Nov 2025 22:49:22 +0100 Subject: [PATCH 05/21] Introduce a warning --- Directory.Build.props | 4 ++++ .../src/DependencyInjectionEventSource.cs | 2 ++ .../src/LoggingEventSource.cs | 2 ++ .../Diagnostics/DiagnosticSourceEventSource.cs | 2 ++ .../gen/EventSourceGenerator.Emitter.cs | 6 ++++++ .../gen/EventSourceGenerator.Parser.cs | 16 +++++++++++++--- .../gen/EventSourceGenerator.cs | 8 +++++++- 7 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 99eee260233d71..7ecae637ec3053 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -319,6 +319,8 @@ $(NoWarn);CS8625 $(NoWarn);CS8617 + + $(NoWarn);ESGEN001 none @@ -360,6 +362,8 @@ $(NoWarn);SYSLIB0011;SYSLIB0050;SYSLIB0051 $(NoWarn);IL2121 + + $(NoWarn);ESGEN001 annotations diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs index 052f1f5a80aac9..7fd787bcf3778b 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs @@ -27,9 +27,11 @@ public static class Keywords private readonly List> _providers = new(); +#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. private DependencyInjectionEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } +#pragma warning restore ESGEN001 // EventSource classes should not declare constructors. // There is a risk that each ServiceProviderBuilt call only finds one entry to remove, and the next call will clean the list again and spend O(n) time on that. // So instead of tying the cleaning to the resizing, it might be better to have a separate counter. diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs index 9ea52e603c222b..ae847bb1f657d0 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs @@ -126,9 +126,11 @@ public static class Keywords private static readonly char[] s_semicolon = new[] { ';' }; private static readonly char[] s_colon = new[] { ':' }; +#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. private LoggingEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } +#pragma warning restore ESGEN001 // EventSource classes should not declare constructors. /// /// FormattedMessage() is called when ILogger.Log() is called. and the FormattedMessage keyword is active diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index 431fc96b534e6a..4d2f990d75987d 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -404,12 +404,14 @@ protected override void OnEventCommand(EventCommandEventArgs command) } #region private +#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. private DiagnosticSourceEventSource() // This constructor uses EventSourceSettings which is only available on V4.6 and above // Use the EventSourceSettings to turn on support for complex types, if available (v4.6 and above). : base(DiagnosticSourceEventSourceName, EventSourceSettings.EtwSelfDescribingEventFormat) { } +#pragma warning restore ESGEN001 // EventSource classes should not declare constructors. // trivial helper to allow you to join two strings the first of which can be null. private static string NewLineSeparate(string? str1, string str2) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs index ca8aaf6e0881ef..a0e424342fd381 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs @@ -17,6 +17,12 @@ public partial class EventSourceGenerator private static void EmitSourceFile(SourceProductionContext context, EventSourceClass ec) { + if (ec.Diagnostic != null) + { + context.ReportDiagnostic(ec.Diagnostic); + return; + } + StringBuilder sb = new StringBuilder(1024); sb.AppendLine(@"// "); diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index 964ccea627d378..752cd60ae6a0d3 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.IO; using System.Security.Cryptography; using System.Text; using System.Threading; @@ -49,8 +50,17 @@ public partial class EventSourceGenerator { if (!ctorModifier.IsKind(SyntaxKind.StaticKeyword)) { - // Contains an explicit constructor, skip generation - return null; + var diagnostic = Diagnostic.Create( + new DiagnosticDescriptor( + "ESGEN001", + "EventSource class contains explicit constructor", + "EventSource class '{0}' contains an explicit constructor. EventSource classes must not declare constructors.", + "EventSourceGenerator", + DiagnosticSeverity.Warning, + isEnabledByDefault: true), + ctor.GetLocation(), + classDef.Identifier.ValueText); + return new EventSourceClass(diagnostic, null, null, null, default, false); } } } @@ -94,7 +104,7 @@ public partial class EventSourceGenerator } } - eventSourceClass = new EventSourceClass(nspace, className, name, result, hasProviderMetadataProperty); + eventSourceClass = new EventSourceClass(null, nspace, className, name, result, hasProviderMetadataProperty); continue; } diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs index 09c4ae5171ea88..8162be97142f5b 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.cs @@ -46,6 +46,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.RegisterSourceOutput(eventSourceClasses, EmitSourceFile); } - private sealed record EventSourceClass(string Namespace, string ClassName, string SourceName, Guid Guid, bool HasProviderMetadataProperty); + private sealed record EventSourceClass( + Diagnostic Diagnostic, + string Namespace, + string ClassName, + string SourceName, + Guid Guid, + bool HasProviderMetadataProperty); } } From 2f306031b35e8b762151fbc04c241db93cbb922e Mon Sep 17 00:00:00 2001 From: EgorBo Date: Tue, 4 Nov 2025 23:59:18 +0100 Subject: [PATCH 06/21] feedback --- .../gen/EventSourceGenerator.Parser.cs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index 752cd60ae6a0d3..dda110a369084c 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -46,23 +46,30 @@ public partial class EventSourceGenerator { if (member is ConstructorDeclarationSyntax ctor) { + bool isStatic = false; foreach (SyntaxToken ctorModifier in ctor.Modifiers) { - if (!ctorModifier.IsKind(SyntaxKind.StaticKeyword)) + if (ctorModifier.IsKind(SyntaxKind.StaticKeyword)) { - var diagnostic = Diagnostic.Create( - new DiagnosticDescriptor( - "ESGEN001", - "EventSource class contains explicit constructor", - "EventSource class '{0}' contains an explicit constructor. EventSource classes must not declare constructors.", - "EventSourceGenerator", - DiagnosticSeverity.Warning, - isEnabledByDefault: true), - ctor.GetLocation(), - classDef.Identifier.ValueText); - return new EventSourceClass(diagnostic, null, null, null, default, false); + isStatic = true; + break; } } + + if (!isStatic) + { + var diagnostic = Diagnostic.Create( + new DiagnosticDescriptor( + "ESGEN001", + "EventSource class contains explicit constructor", + "EventSource class '{0}' contains an explicit constructor. EventSource classes must not declare constructors.", + "EventSourceGenerator", + DiagnosticSeverity.Warning, + isEnabledByDefault: true), + ctor.GetLocation(), + classDef.Identifier.ValueText); + return new EventSourceClass(diagnostic, null, null, null, default, false); + } } } From 0e832077b69f4032993dbf48783be4422baaaa0f Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 9 Nov 2025 00:59:36 +0100 Subject: [PATCH 07/21] Address feedback --- Directory.Build.props | 4 +-- .../src/DependencyInjectionEventSource.cs | 4 +-- .../src/LoggingEventSource.cs | 4 +-- .../DiagnosticSourceEventSource.cs | 4 +-- .../BasicEventSourceTest/ActivityTracking.cs | 2 -- .../gen/EventSourceGenerator.Parser.cs | 33 ++++++++++++++++--- 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 7ecae637ec3053..84877200392e0c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -320,7 +320,7 @@ $(NoWarn);CS8617 - $(NoWarn);ESGEN001 + $(NoWarn);ESGEN001;ESGEN002 none @@ -363,7 +363,7 @@ $(NoWarn);IL2121 - $(NoWarn);ESGEN001 + $(NoWarn);ESGEN001;ESGEN002 annotations diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs index 7fd787bcf3778b..e206a86239a2e7 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs @@ -12,8 +12,10 @@ namespace Microsoft.Extensions.DependencyInjection { +#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = "Microsoft-Extensions-DependencyInjection")] internal sealed class DependencyInjectionEventSource : EventSource +#pragma warning restore ESGEN001 { public static readonly DependencyInjectionEventSource Log = new DependencyInjectionEventSource(); @@ -27,11 +29,9 @@ public static class Keywords private readonly List> _providers = new(); -#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. private DependencyInjectionEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } -#pragma warning restore ESGEN001 // EventSource classes should not declare constructors. // There is a risk that each ServiceProviderBuilt call only finds one entry to remove, and the next call will clean the list again and spend O(n) time on that. // So instead of tying the cleaning to the resizing, it might be better to have a separate counter. diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs index ae847bb1f657d0..6de30ff01c3175 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs @@ -82,8 +82,10 @@ namespace Microsoft.Extensions.Logging.EventSource /// } /// /// +#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = "Microsoft-Extensions-Logging")] public sealed class LoggingEventSource : System.Diagnostics.Tracing.EventSource +#pragma warning restore ESGEN001 { /// /// Defines the different ways data can be formatted in an event. @@ -126,11 +128,9 @@ public static class Keywords private static readonly char[] s_semicolon = new[] { ';' }; private static readonly char[] s_colon = new[] { ':' }; -#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. private LoggingEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } -#pragma warning restore ESGEN001 // EventSource classes should not declare constructors. /// /// FormattedMessage() is called when ILogger.Log() is called. and the FormattedMessage keyword is active diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index 4d2f990d75987d..dbea23f58cc8c9 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -159,8 +159,10 @@ namespace System.Diagnostics /// /// See the DiagnosticSourceEventSourceBridgeTest.cs for more explicit examples of using this bridge. /// +#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = DiagnosticSourceEventSourceName)] internal sealed class DiagnosticSourceEventSource : EventSource +#pragma warning restore ESGEN001 { private const string DiagnosticSourceEventSourceName = "Microsoft-Diagnostics-DiagnosticSource"; @@ -404,14 +406,12 @@ protected override void OnEventCommand(EventCommandEventArgs command) } #region private -#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. private DiagnosticSourceEventSource() // This constructor uses EventSourceSettings which is only available on V4.6 and above // Use the EventSourceSettings to turn on support for complex types, if available (v4.6 and above). : base(DiagnosticSourceEventSourceName, EventSourceSettings.EtwSelfDescribingEventFormat) { } -#pragma warning restore ESGEN001 // EventSource classes should not declare constructors. // trivial helper to allow you to join two strings the first of which can be null. private static string NewLineSeparate(string? str1, string str2) diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/ActivityTracking.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/ActivityTracking.cs index bfd7263e6e9ac8..e975859721f929 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/ActivityTracking.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/ActivityTracking.cs @@ -164,8 +164,6 @@ public async Task SetCurrentActivityIdAfterEventDoesNotFlowAsync() [EventSource(Name = "ActivityEventSource")] class ActivityEventSource : EventSource { - public ActivityEventSource() { } - [Event(1)] public void ExampleStart() => WriteEvent(1); diff --git a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs index dda110a369084c..85f884958e642b 100644 --- a/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs @@ -42,6 +42,31 @@ public partial class EventSourceGenerator continue; } + bool isPartial = false; + foreach (var modifier in classDef.Modifiers) + { + if (modifier.IsKind(SyntaxKind.PartialKeyword)) + { + isPartial = true; + break; + } + } + + if (!isPartial) + { + var diagnostic = Diagnostic.Create( + new DiagnosticDescriptor( + "ESGEN001", + "EventSource class is not partial", + "EventSource class '{0}' is not partial. EventSource classes must be declared as partial to take advantage of EventSourceGenerator.", + nameof(EventSourceGenerator), + DiagnosticSeverity.Warning, + isEnabledByDefault: true), + classDef.GetLocation(), + classDef.Identifier.ValueText); + return new EventSourceClass(diagnostic, null, null, null, default, false); + } + foreach (MemberDeclarationSyntax member in classDef.Members) { if (member is ConstructorDeclarationSyntax ctor) @@ -60,13 +85,13 @@ public partial class EventSourceGenerator { var diagnostic = Diagnostic.Create( new DiagnosticDescriptor( - "ESGEN001", + "ESGEN002", "EventSource class contains explicit constructor", - "EventSource class '{0}' contains an explicit constructor. EventSource classes must not declare constructors.", - "EventSourceGenerator", + "EventSource class '{0}' contains an explicit constructor. EventSource classes must not declare constructors to take advantage of EventSourceGenerator.", + nameof(EventSourceGenerator), DiagnosticSeverity.Warning, isEnabledByDefault: true), - ctor.GetLocation(), + classDef.GetLocation(), classDef.Identifier.ValueText); return new EventSourceClass(diagnostic, null, null, null, default, false); } From e072e4b638f39d8413d74622eb3e1443f5ed09ca Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 9 Nov 2025 01:05:01 +0100 Subject: [PATCH 08/21] Add a comment --- .../src/LoggingEventSource.cs | 4 +++- .../src/System/Diagnostics/DiagnosticSourceEventSource.cs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs index 6de30ff01c3175..3bacff6b616df4 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs @@ -82,7 +82,9 @@ namespace Microsoft.Extensions.Logging.EventSource /// } /// /// -#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. See https://github.com/dotnet/runtime/issues/121205. +#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. + // This EventSource needs to set EtwSelfDescribingEventFormat which is not supported by the source generator yet. + // See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = "Microsoft-Extensions-Logging")] public sealed class LoggingEventSource : System.Diagnostics.Tracing.EventSource #pragma warning restore ESGEN001 diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index dbea23f58cc8c9..f81fa36492c3ec 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -159,7 +159,9 @@ namespace System.Diagnostics /// /// See the DiagnosticSourceEventSourceBridgeTest.cs for more explicit examples of using this bridge. /// -#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. See https://github.com/dotnet/runtime/issues/121205. +#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. + // This EventSource uses EtwSelfDescribingEventFormat which is not supported by the source generator yet. + // See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = DiagnosticSourceEventSourceName)] internal sealed class DiagnosticSourceEventSource : EventSource #pragma warning restore ESGEN001 From c5b09c7e05b806c2b2b28b2b7c4cba783c4fb454 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 9 Nov 2025 01:12:16 +0100 Subject: [PATCH 09/21] cleanup --- .../src/DependencyInjectionEventSource.cs | 5 ++++- .../src/LoggingEventSource.cs | 5 +++-- .../src/System/Diagnostics/DiagnosticSourceEventSource.cs | 5 +++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs index e206a86239a2e7..4dc50d8370ad12 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs @@ -12,7 +12,10 @@ namespace Microsoft.Extensions.DependencyInjection { -#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. See https://github.com/dotnet/runtime/issues/121205. +#pragma warning disable ESGEN001 // EventSource class is not partial. + // This EventSource uses EtwSelfDescribingEventFormat in its + // constructor which is not supported by the source generator yet. + // See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = "Microsoft-Extensions-DependencyInjection")] internal sealed class DependencyInjectionEventSource : EventSource #pragma warning restore ESGEN001 diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs index 3bacff6b616df4..5d60efe2ef96d5 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs @@ -82,8 +82,9 @@ namespace Microsoft.Extensions.Logging.EventSource /// } /// /// -#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. - // This EventSource needs to set EtwSelfDescribingEventFormat which is not supported by the source generator yet. +#pragma warning disable ESGEN001 // EventSource class is not partial. + // This EventSource uses EtwSelfDescribingEventFormat in its + // constructor which is not supported by the source generator yet. // See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = "Microsoft-Extensions-Logging")] public sealed class LoggingEventSource : System.Diagnostics.Tracing.EventSource diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index f81fa36492c3ec..89aca3fbd80469 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -159,8 +159,9 @@ namespace System.Diagnostics /// /// See the DiagnosticSourceEventSourceBridgeTest.cs for more explicit examples of using this bridge. /// -#pragma warning disable ESGEN001 // EventSource classes should not declare constructors. - // This EventSource uses EtwSelfDescribingEventFormat which is not supported by the source generator yet. +#pragma warning disable ESGEN001 // EventSource class is not partial. + // This EventSource uses EtwSelfDescribingEventFormat in its + // constructor which is not supported by the source generator yet. // See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = DiagnosticSourceEventSourceName)] internal sealed class DiagnosticSourceEventSource : EventSource From 01e1199eff5f81eba5c0ef8f1fffc09cb26a1eff Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 9 Nov 2025 01:16:16 +0100 Subject: [PATCH 10/21] Feedback --- .../src/DependencyInjectionEventSource.cs | 3 +-- .../src/LoggingEventSource.cs | 4 ++-- .../src/System/Diagnostics/DiagnosticSourceEventSource.cs | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs index 4dc50d8370ad12..36a467075a28be 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs @@ -13,8 +13,7 @@ namespace Microsoft.Extensions.DependencyInjection { #pragma warning disable ESGEN001 // EventSource class is not partial. - // This EventSource uses EtwSelfDescribingEventFormat in its - // constructor which is not supported by the source generator yet. + // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat // See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = "Microsoft-Extensions-DependencyInjection")] internal sealed class DependencyInjectionEventSource : EventSource diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs index 5d60efe2ef96d5..7e8de6f724bfbf 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs @@ -82,9 +82,9 @@ namespace Microsoft.Extensions.Logging.EventSource /// } /// /// +{ #pragma warning disable ESGEN001 // EventSource class is not partial. - // This EventSource uses EtwSelfDescribingEventFormat in its - // constructor which is not supported by the source generator yet. + // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat // See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = "Microsoft-Extensions-Logging")] public sealed class LoggingEventSource : System.Diagnostics.Tracing.EventSource diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index 89aca3fbd80469..948d33982b8edd 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -159,9 +159,9 @@ namespace System.Diagnostics /// /// See the DiagnosticSourceEventSourceBridgeTest.cs for more explicit examples of using this bridge. /// +{ #pragma warning disable ESGEN001 // EventSource class is not partial. - // This EventSource uses EtwSelfDescribingEventFormat in its - // constructor which is not supported by the source generator yet. + // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat // See https://github.com/dotnet/runtime/issues/121205. [EventSource(Name = DiagnosticSourceEventSourceName)] internal sealed class DiagnosticSourceEventSource : EventSource From 6e8f9181918070ba86b0ed1c1f274b6856f5914e Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 9 Nov 2025 19:31:07 +0100 Subject: [PATCH 11/21] feedback --- .../src/DependencyInjectionEventSource.cs | 5 ++--- .../src/LoggingEventSource.cs | 5 ++--- .../src/System/Diagnostics/DiagnosticSourceEventSource.cs | 6 ++---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs index 36a467075a28be..ab04023b90b50c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs @@ -12,9 +12,7 @@ namespace Microsoft.Extensions.DependencyInjection { -#pragma warning disable ESGEN001 // EventSource class is not partial. - // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat - // See https://github.com/dotnet/runtime/issues/121205. +#pragma warning disable ESGEN001 // EventSource class is not partial. It's blocked by https://github.com/dotnet/runtime/issues/121205 [EventSource(Name = "Microsoft-Extensions-DependencyInjection")] internal sealed class DependencyInjectionEventSource : EventSource #pragma warning restore ESGEN001 @@ -31,6 +29,7 @@ public static class Keywords private readonly List> _providers = new(); + // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat. private DependencyInjectionEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs index 7e8de6f724bfbf..13d439edf7b391 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs @@ -83,9 +83,7 @@ namespace Microsoft.Extensions.Logging.EventSource /// /// { -#pragma warning disable ESGEN001 // EventSource class is not partial. - // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat - // See https://github.com/dotnet/runtime/issues/121205. +#pragma warning disable ESGEN001 // EventSource class is not partial. It's blocked by https://github.com/dotnet/runtime/issues/121205 [EventSource(Name = "Microsoft-Extensions-Logging")] public sealed class LoggingEventSource : System.Diagnostics.Tracing.EventSource #pragma warning restore ESGEN001 @@ -131,6 +129,7 @@ public static class Keywords private static readonly char[] s_semicolon = new[] { ';' }; private static readonly char[] s_colon = new[] { ':' }; + // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat. private LoggingEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index 948d33982b8edd..d3af01b6ed3315 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -159,10 +159,7 @@ namespace System.Diagnostics /// /// See the DiagnosticSourceEventSourceBridgeTest.cs for more explicit examples of using this bridge. /// -{ -#pragma warning disable ESGEN001 // EventSource class is not partial. - // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat - // See https://github.com/dotnet/runtime/issues/121205. +#pragma warning disable ESGEN001 // EventSource class is not partial. It's blocked by https://github.com/dotnet/runtime/issues/121205 [EventSource(Name = DiagnosticSourceEventSourceName)] internal sealed class DiagnosticSourceEventSource : EventSource #pragma warning restore ESGEN001 @@ -409,6 +406,7 @@ protected override void OnEventCommand(EventCommandEventArgs command) } #region private + // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat. private DiagnosticSourceEventSource() // This constructor uses EventSourceSettings which is only available on V4.6 and above // Use the EventSourceSettings to turn on support for complex types, if available (v4.6 and above). From 4255dc804c9d715d24da8389bbb2223a7bac2910 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 9 Nov 2025 10:43:44 -0800 Subject: [PATCH 12/21] Apply suggestions from code review --- .../src/DependencyInjectionEventSource.cs | 2 +- .../src/LoggingEventSource.cs | 2 +- .../src/System/Diagnostics/DiagnosticSourceEventSource.cs | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs index ab04023b90b50c..25928cc7e44894 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs @@ -29,7 +29,7 @@ public static class Keywords private readonly List> _providers = new(); - // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat. + // This event source uses EtwSelfDescribingEventFormat for backward compatibility. private DependencyInjectionEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs index 13d439edf7b391..0b5873ca3c5962 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs @@ -129,7 +129,7 @@ public static class Keywords private static readonly char[] s_semicolon = new[] { ';' }; private static readonly char[] s_colon = new[] { ':' }; - // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat. + // This event source uses IEnumerable as an event parameter type which is only supported by EtwSelfDescribingEventFormat. private LoggingEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index d3af01b6ed3315..1c778361e1fd87 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -406,10 +406,8 @@ protected override void OnEventCommand(EventCommandEventArgs command) } #region private - // This event source uses IEnumerable as an event parameter type which is only supported by SelfDescribingFormat. + // This event source uses IEnumerable as an event parameter type which is only supported by EtwSelfDescribingEventFormat. private DiagnosticSourceEventSource() - // This constructor uses EventSourceSettings which is only available on V4.6 and above - // Use the EventSourceSettings to turn on support for complex types, if available (v4.6 and above). : base(DiagnosticSourceEventSourceName, EventSourceSettings.EtwSelfDescribingEventFormat) { } From 91c84655104ec8f907030599ad483006ce406866 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 9 Nov 2025 10:47:10 -0800 Subject: [PATCH 13/21] Apply suggestions from code review --- .../src/System/Diagnostics/DiagnosticSourceEventSource.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index 1c778361e1fd87..fa26bfa9069080 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -407,8 +407,7 @@ protected override void OnEventCommand(EventCommandEventArgs command) #region private // This event source uses IEnumerable as an event parameter type which is only supported by EtwSelfDescribingEventFormat. - private DiagnosticSourceEventSource() - : base(DiagnosticSourceEventSourceName, EventSourceSettings.EtwSelfDescribingEventFormat) + private DiagnosticSourceEventSource() : base(DiagnosticSourceEventSourceName, EventSourceSettings.EtwSelfDescribingEventFormat) { } From 28dee99ba9016c249c1da69f442112c738c2a93d Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 9 Nov 2025 11:07:41 -0800 Subject: [PATCH 14/21] Apply suggestions from code review --- .../System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs | 1 - .../src/System/Linq/Parallel/Utils/PLINQETWProvider.cs | 1 - .../src/Internal/DataflowEtwProvider.cs | 1 - .../src/System/Threading/CDSsyncETWBCLProvider.cs | 1 - .../src/System/Transactions/TransactionsEtwProvider.cs | 1 - 5 files changed, 5 deletions(-) diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs index 0437ae575efc4f..8cf3cab2f42106 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/CDSCollectionETWBCLProvider.cs @@ -23,7 +23,6 @@ internal sealed partial class CDSCollectionETWBCLProvider : EventSource { /// /// Defines the singleton instance for the collection ETW provider. - /// The collection provider GUID is {35167F8E-49B2-4b96-AB86-435B59336B5E}. /// public static readonly CDSCollectionETWBCLProvider Log = new CDSCollectionETWBCLProvider(); diff --git a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs index 9d37055e6262c0..6421694b91a68b 100644 --- a/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs +++ b/src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PLINQETWProvider.cs @@ -26,7 +26,6 @@ internal sealed partial class PlinqEtwProvider : EventSource { /// /// Defines the singleton instance for the PLINQ ETW provider. - /// The PLINQ Event provider GUID is {159eeeec-4a14-4418-a8fe-faabcd987887}. /// internal static readonly PlinqEtwProvider Log = new PlinqEtwProvider(); diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs index 25184973162486..39298b164bfbe1 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs @@ -26,7 +26,6 @@ internal sealed partial class DataflowEtwProvider : EventSource { /// /// Defines the singleton instance for the dataflow ETW provider. - /// The dataflow provider GUID is {16F53577-E41D-43D4-B47E-C17025BF4025}. /// internal static readonly DataflowEtwProvider Log = new DataflowEtwProvider(); diff --git a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs index 97a440d6cf9153..e04feef4668fb0 100644 --- a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs +++ b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs @@ -29,7 +29,6 @@ internal sealed partial class CdsSyncEtwBCLProvider : EventSource { /// /// Defines the singleton instance for the CDS Sync ETW provider. - /// The CDS Sync Event provider GUID is {EC631D38-466B-4290-9306-834971BA0217}. /// public static readonly CdsSyncEtwBCLProvider Log = new CdsSyncEtwBCLProvider(); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs index 8c20cbbbbe3169..2b75b69b9acca0 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs @@ -78,7 +78,6 @@ internal sealed partial class TransactionsEtwProvider : EventSource { /// /// Defines the singleton instance for the Transactions ETW provider. - /// The Transactions provider GUID is {8ac2d80a-1f1a-431b-ace4-bff8824aef0b}. /// internal static readonly TransactionsEtwProvider Log = new TransactionsEtwProvider(); From b2fd58716490a93c17856dac9f3534a3b5aa6092 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 9 Nov 2025 11:15:36 -0800 Subject: [PATCH 15/21] Apply suggestions from code review --- .../src/System/Diagnostics/Tracing/RuntimeEventSource.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 be2c9e72b1ea8b..3e31cac0fe71aa 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 @@ -10,10 +10,9 @@ namespace System.Diagnostics.Tracing /// /// RuntimeEventSource is an EventSource that represents events emitted by the managed runtime. /// - [EventSource(Guid = "49592C0F-5A05-516D-AA4B-A64E02026C89", Name = EventSourceName)] + [EventSource(Guid = "49592C0F-5A05-516D-AA4B-A64E02026C89", Name = "System.Runtime")] internal sealed partial class RuntimeEventSource : EventSource { - internal const string EventSourceName = "System.Runtime"; public static class Keywords { From cbf98254cb0ace9adcf5aff5d0b6cf5fc2593254 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 9 Nov 2025 11:16:16 -0800 Subject: [PATCH 16/21] Update src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs --- .../src/System/Diagnostics/Tracing/RuntimeEventSource.cs | 1 - 1 file changed, 1 deletion(-) 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 3e31cac0fe71aa..1ec6bfb52b6404 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 @@ -13,7 +13,6 @@ namespace System.Diagnostics.Tracing [EventSource(Guid = "49592C0F-5A05-516D-AA4B-A64E02026C89", Name = "System.Runtime")] internal sealed partial class RuntimeEventSource : EventSource { - public static class Keywords { public const EventKeywords AppContext = (EventKeywords)0x1; From b5446055f0881563a0ddaadc75ef89ab64354f0d Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sun, 9 Nov 2025 22:01:23 +0100 Subject: [PATCH 17/21] Update LoggingEventSource.cs --- .../src/LoggingEventSource.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs index 0b5873ca3c5962..177c674f3b34d2 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs @@ -82,7 +82,6 @@ namespace Microsoft.Extensions.Logging.EventSource /// } /// /// -{ #pragma warning disable ESGEN001 // EventSource class is not partial. It's blocked by https://github.com/dotnet/runtime/issues/121205 [EventSource(Name = "Microsoft-Extensions-Logging")] public sealed class LoggingEventSource : System.Diagnostics.Tracing.EventSource From c31708ecc4fd49e81e2dacd786392b51b2dd6f23 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 9 Nov 2025 18:42:06 -0800 Subject: [PATCH 18/21] Update src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs --- .../ref/System.Diagnostics.Tracing.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs b/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs index 67355b30bd10d2..3938e9fc768713 100644 --- a/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs +++ b/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs @@ -155,9 +155,8 @@ protected EventSource(System.Diagnostics.Tracing.EventSourceSettings settings, p public EventSource(string eventSourceName) { } public EventSource(string eventSourceName, System.Diagnostics.Tracing.EventSourceSettings config) { } public EventSource(string eventSourceName, System.Diagnostics.Tracing.EventSourceSettings config, params string[]? traits) { } - public EventSource(string eventSourceName, Guid eventSourceGuid) { } - public EventSource(string eventSourceName, Guid eventSourceGuid, System.Diagnostics.Tracing.EventSourceSettings settings, params string[]? traits) { } - + public EventSource(string eventSourceName, System.Guid eventSourceGuid) { } + public EventSource(string eventSourceName, System.Guid eventSourceGuid, System.Diagnostics.Tracing.EventSourceSettings settings, params string[]? traits) { } public System.Exception? ConstructionException { get { throw null; } } public static System.Guid CurrentThreadActivityId { get { throw null; } } public System.Guid Guid { get { throw null; } } From e85c9f7607e5b22018b2d73102bff52994b8e4f7 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Mon, 10 Nov 2025 23:44:45 +0100 Subject: [PATCH 19/21] Update System.Diagnostics.Tracing.cs --- .../ref/System.Diagnostics.Tracing.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs b/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs index 3938e9fc768713..5f7e0b9e3cc26f 100644 --- a/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs +++ b/src/libraries/System.Diagnostics.Tracing/ref/System.Diagnostics.Tracing.cs @@ -156,7 +156,7 @@ public EventSource(string eventSourceName) { } public EventSource(string eventSourceName, System.Diagnostics.Tracing.EventSourceSettings config) { } public EventSource(string eventSourceName, System.Diagnostics.Tracing.EventSourceSettings config, params string[]? traits) { } public EventSource(string eventSourceName, System.Guid eventSourceGuid) { } - public EventSource(string eventSourceName, System.Guid eventSourceGuid, System.Diagnostics.Tracing.EventSourceSettings settings, params string[]? traits) { } + public EventSource(string eventSourceName, System.Guid eventSourceGuid, System.Diagnostics.Tracing.EventSourceSettings settings, string[]? traits = null) { } public System.Exception? ConstructionException { get { throw null; } } public static System.Guid CurrentThreadActivityId { get { throw null; } } public System.Guid Guid { get { throw null; } } From 4b33cf0d07542795696bc95d0336ee0108e3f318 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 16 Nov 2025 06:36:10 +0100 Subject: [PATCH 20/21] Address feedback --- .../tests/BasicEventSourceTest/TestsTraits.cs | 47 +++++++++++++++++++ .../System/Diagnostics/Tracing/EventSource.cs | 31 ++++++++++-- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsTraits.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsTraits.cs index 6221bf677682d6..5fd63529e60298 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsTraits.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsTraits.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Diagnostics.Tracing; using Xunit; @@ -54,5 +55,51 @@ public void Test_EventSource_Traits_Dynamic() } TestUtilities.CheckNoEventSourcesRunning("Stop"); } + + [Fact] + public void Test_EventSource_Traits_Contract_Guid() + { + var guid = new Guid("{EB2FA63A-C72F-4D58-B6AC-ED6F82E9BF38}"); + TestUtilities.CheckNoEventSourcesRunning("Start"); + using (var mySource = new EventSource("MyEventSource", guid)) + { + Assert.Equal(EventSourceSettings.EtwManifestEventFormat, mySource.Settings); + Assert.Equal(guid, mySource.Guid); + Assert.Equal("MyEventSource", mySource.Name); + } + TestUtilities.CheckNoEventSourcesRunning("Stop"); + } + + [Fact] + public void Test_EventSource_Traits_Contract_Guid_Manifest() + { + var guid = new Guid("{B8CE9801-6828-4311-AF29-72DB02EA9D8B}"); + TestUtilities.CheckNoEventSourcesRunning("Start"); + using (var mySource = new EventSource("MyEventSource", guid, EventSourceSettings.EtwSelfDescribingEventFormat)) + { + Assert.Equal(EventSourceSettings.EtwSelfDescribingEventFormat, mySource.Settings); + Assert.Equal(guid, mySource.Guid); + Assert.Equal("MyEventSource", mySource.Name); + } + TestUtilities.CheckNoEventSourcesRunning("Stop"); + } + + [Fact] + public void Test_EventSource_Traits_Dynamic_Guid() + { + var guid = new Guid("{C96ADE53-54EE-4AEA-B5E4-369E97AD7DD2}"); + TestUtilities.CheckNoEventSourcesRunning("Start"); + using (var mySource = new EventSource("DynamicEventSourceWithTraits", + guid, EventSourceSettings.Default, + ["MyTrait", "MyTraitValue", + "ETW_GROUP", "{4f50731a-89cf-4782-b3e0-dce8c90476ba}"])) + { + Assert.Equal(EventSourceSettings.EtwSelfDescribingEventFormat, mySource.Settings); + Assert.Equal(guid, mySource.Guid); + Assert.Equal("MyTraitValue", mySource.GetTrait("MyTrait")); + Assert.Equal("{4f50731a-89cf-4782-b3e0-dce8c90476ba}", mySource.GetTrait("ETW_GROUP")); + } + TestUtilities.CheckNoEventSourcesRunning("Stop"); + } } } 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 9407cc9426d617..1cba7af43767d4 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 @@ -1604,13 +1604,38 @@ private unsafe void WriteEventRaw( } } - // FrameworkEventSource is on the startup path for the framework, so we have this internal overload that it can use - // to prevent the working set hit from looking at the custom attributes on the type to get the Guid. + /// + /// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API) + /// and a given Guid to identify the source. + /// + /// + /// The name of the event source. Must not be null. + /// + /// + /// The unique identifier for the event source. Must not be Guid.Empty. + /// public EventSource(string eventSourceName, Guid eventSourceGuid) : this(eventSourceName, eventSourceGuid, EventSourceSettings.EtwManifestEventFormat) { } - // Used by the internal FrameworkEventSource constructor and the TraceLogging-style event source constructor + /// + /// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API) + /// and a given Guid to identify the source. + /// + /// Also specify a list of key-value pairs called traits (you must pass an even number of strings). + /// The first string is the key and the second is the value. These are not interpreted by EventSource + /// itself but may be interpreted the listeners. Can be fetched with GetTrait(string). + /// + /// + /// The name of the event source. Must not be null. + /// + /// + /// The unique identifier for the event source. Must not be Guid.Empty. + /// + /// + /// Configuration options for the EventSource as a whole. + /// + /// A collection of key-value strings (must be an even number). public EventSource(string eventSourceName, Guid eventSourceGuid, EventSourceSettings settings, string[]? traits = null) { if (IsSupported) From e4ef659f7b731bf88739148a2408fe47ea30eb65 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sun, 16 Nov 2025 09:29:16 +0100 Subject: [PATCH 21/21] Update EventSource.cs --- .../src/System/Diagnostics/Tracing/EventSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1cba7af43767d4..918e35161eab87 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 @@ -1632,7 +1632,7 @@ public EventSource(string eventSourceName, Guid eventSourceGuid) /// /// The unique identifier for the event source. Must not be Guid.Empty. /// - /// + /// /// Configuration options for the EventSource as a whole. /// /// A collection of key-value strings (must be an even number).