-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Introduce a new internal EventSourceGenerator and use it for all ES implementations #121180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
hm.. probably should move the SLNX update to a separate (last) commit (or maybe even PR?) |
…+ 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
We will likely want more than just this, e.g. it'll need to be |
Do we need to modify the slnx files? Could we instead globally include via .props? |
it's not needed to build the projects, but needed for people opening slnx files for the SG project to show up there in slnx. All other source generator projects are already added there (added automatically by the UpdateSolutionFile task, which is manually invoked (it's slow)) |
| } | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we generate warning when we run into EventSource that we are not able to generate the ctor for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jkotas we have 3 that we can't generate for:
Microsoft.Extensions.DependencyInjection\src\DependencyInjectionEventSource.csMicrosoft.Extensions.Logging.EventSource\src\LoggingEventSource.csSystem.Diagnostics.DiagnosticSource\src\System\Diagnostics\DiagnosticSourceEventSource.cs
they need to pass EventSourceSettings.EtwSelfDescribingEventFormat to the settings argument.
We have 3 options:
- Propose an API to add
EventSourceSettingsto the [EventSource] arg so we can define it there (and use from the SG) - Leave some internal hint for the SG that we need EtwSelfDescribingEventFormat instead of the default (e.g. some constant field?)
- Leave these 3 as is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like (1)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
they need to pass EventSourceSettings.EtwSelfDescribingEventFormat to the settings argument.
Why do these need to pass EventSourceSettings.EtwSelfDescribingEventFormat?
I would like to understand whether EtwSelfDescribingEventFormat is a corner-case that is only used in handful of places in runtime repo (3 is ok in that case), or whether it is something that gets used reasonably often (1 is worth doing in that case).
Similar concern about the other EventSource ctor arguments. How often are they used in practice? If they are used reasonably often, we may want to do some sort of extended version of (1).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to understand whether EtwSelfDescribingEventFormat is a corner-case that is only used in handful of places in runtime repo (3 is ok in that case), or whether it is something that gets used reasonably often (1 is worth doing in that case).
I'm afraid I don't know, perhaps someone from @dotnet/dotnet-diag can answer?
I also noticed there is an inconsistency among the base EventSource constructors:
protected EventSource() { } // EtwManifestEventFormat
protected EventSource(bool) { } // EtwManifestEventFormat
public EventSource(string) { } // EtwSelfDescribingEventFormat
public EventSource(string, Guid) { } // EtwManifestEventFormat`so in the end, it does look like we only have 3 ES that uses EtwSelfDescribingEventFormat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do these need to pass EventSourceSettings.EtwSelfDescribingEventFormat?
- DependencyInjectionEventSource - looks compatible with both formats. Changing from SelfDescribing to Manifest could prevent the EventSource from working properly with ETW profilers that don't use the TraceEvent library to abstract the data parsing
- LoggingEventSource and DiagnosticSourceEventSource - Use IEnumerable<T> as an event parameter type which is only supported by SelfDescribingFormat
I would like to understand whether EtwSelfDescribingEventFormat is a corner-case that is only used in handful of places in runtime repo (3 is ok in that case), or whether it is something that gets used reasonably often (1 is worth doing in that case).
SelfDescribing is more than a corner case for 3P usage - it has more capabilities and better compatibility with ETW profilers that don't use the TraceEvent library. However it has higher per-event serialization overhead which is why most of our runtime EventSources don't use it.
Similar concern about the other EventSource ctor arguments. How often are they used in practice? If they are used reasonably often, we may want to do some sort of extended version of (1).
Aside from name, Guid, and EventSourceSettings enum there are only two other ctor arguments:
bool throwOnEventWriteErrors- this is superceded by EventSourceSettings so no reason to include it separatelystring[] traits- Arbitrary key value pairs that can be associated with an EventSource. I don't recall seeing a real-world use. I believe it is rare but its not easy to back that up with simple code search results because both 'EventSource' and 'traits' find huge numbers of unrelated references.
I like (1)
Ditto 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, then let's put the PR on pause till the API proposal lands
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not think you need to wait for that API proposal to land. You can leave the 3 event sources that need that API proposal alone (disable the warning for them), and deal with the rest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jkotas ok, then I guess it's ready for review
src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a source generator for EventSource classes to automatically generate constructors and metadata, eliminating the need for manual boilerplate code. The generator creates parameterless constructors that call the base EventSource constructor with the correct parameter order (name, guid).
Key changes:
- Introduces
EventSourceGeneratorsource generator that triggers on classes with[EventSource]attribute - Removes
[EventSourceAutoGenerate]attribute and makes affected EventSource classespartial - Changes EventSource base constructor parameter order from
(Guid, string)to(string, Guid)for consistency - Removes manual constructors from EventSource classes across the codebase
Reviewed Changes
Copilot reviewed 50 out of 50 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| EventSourceGenerator.cs | New source generator that creates constructors for EventSource classes |
| EventSourceGenerator.Parser.cs | Parser logic to extract EventSource metadata and validate constructors |
| EventSourceGenerator.Emitter.cs | Code generation logic for constructors and provider metadata |
| EventSource.cs | Changes constructor parameter order and visibility for source generator |
| TraceLoggingEventSource.cs | Updates constructor call to match new parameter order |
| Multiple EventSource classes | Removes manual constructors and adds partial keyword |
| NetCoreAppLibrary.props | Registers EventSourceGenerator |
| generators.targets | Enables generator for source projects |
| Directory.Build.props | Suppresses ESGEN001 warnings globally |
Comments suppressed due to low confidence (1)
src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs:24
- The parser only checks for
NamespaceDeclarationSyntaxbut doesn't check forFileScopedNamespaceDeclarationSyntax. This will cause the generator to skip classes in file-scoped namespaces. UseBaseNamespaceDeclarationSyntaxas the base type to handle both traditional and file-scoped namespace declarations.
src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Emitter.cs
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/gen/EventSourceGenerator.Parser.cs
Outdated
Show resolved
Hide resolved
|
|
||
| private readonly List<WeakReference<ServiceProvider>> _providers = new(); | ||
|
|
||
| #pragma warning disable ESGEN001 // EventSource classes should not declare constructors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a tracking issue for these?
| [EventSource(Name = "ActivityEventSource")] | ||
| class ActivityEventSource : EventSource | ||
| { | ||
| public ActivityEventSource() { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts on what it would take to make this source generator part of the SDK?
| private readonly List<WeakReference<ServiceProvider>> _providers = new(); | ||
|
|
||
| #pragma warning disable ESGEN001 // EventSource classes should not declare constructors. | ||
| private DependencyInjectionEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| private DependencyInjectionEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) | |
| // Uses EtwSelfDescribingEventFormat for backward compatibility | |
| private DependencyInjectionEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) |
Capture insights from PR comments
| private static readonly char[] s_colon = new[] { ':' }; | ||
|
|
||
| #pragma warning disable ESGEN001 // EventSource classes should not declare constructors. | ||
| private LoggingEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| private LoggingEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) | |
| // This event source uses IEnumerable<T> as an event parameter type which is only supported by SelfDescribingFormat | |
| private LoggingEventSource() : base(EventSourceSettings.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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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) | |
| // This event source uses IEnumerable<T> as an event parameter type which is only supported by SelfDescribingFormat | |
| private DiagnosticSourceEventSource() : base(DiagnosticSourceEventSourceName, EventSourceSettings.EtwSelfDescribingEventFormat) |
| new DiagnosticDescriptor( | ||
| "ESGEN001", | ||
| "EventSource class contains explicit constructor", | ||
| "EventSource class '{0}' contains an explicit constructor. EventSource classes must not declare constructors.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "EventSource class '{0}' contains an explicit constructor. EventSource classes must not declare constructors.", | |
| "EventSource class '{0}' contains an explicit constructor. EventSource classes must not declare constructors to take advantage of this source generator.", |
?
Closes #28290
[EventSourceAutoGenerate], we rely on just [EventSource] + no explicit ctorsEventSourceSettings.EtwSelfDescribingEventFormat-- there are 3 ES impl defining this settings 🤔