-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
[API Proposal]: Add overload for EventSource primitives #83751
Conversation
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti Issue DetailsI've seen a lot of calls to the varargs EventSource overload that have to manually suppress the trim warning because they only use primitive types. Adding this overload solves two problems:
|
Doesn't this need to follow https://github.com/dotnet/runtime/blob/main/docs/project/api-review-process.md? |
@eerhardt Happy to go through that as well. I wanted to get some early feedback on whether this would address areas you've seen. Turns out, I found a bunch of places in the framework that it solves, so maybe that answered my question. |
I take it C# overload resolution rules bind params EventSourcePrimitive[] with higher priority than params object[] when all the parameter types have implicit casting rules defined? How many warnings does this handle? My guess is that if the number of sites is measured in hundreds then it could be worth adding the API, but if it is <100 we should probably just annotate them. The API itself looked fine to me assuming a final version includes all the other things that go along with new APIs like tests and docs. |
I don't have a warm fuzzy feeling about adding new APIs just to make the trimmer happy. Is it possible to make emitting the warning smarter? It seems like it wouldn't be that hard to check if it's just primitives then don't warn, but I haven't thought super hard about it. |
@davmason Adding new APIs when the originals are unsafe is the design recommendation. |
Yup
I've hit a warning from this in almost every third-party library I've tried to annotate, so this is likely worth it just because users wouldn't have to add suppressions (which we explicitly recommend against).
Yeah, I could use some guidance on where the tests live. This may actually be inadvertently testing some old code paths, since they preferentially bind to this one now. |
You can write trimming tests (small .exe apps that get full trimmed and then executed - ensuring they return exit code |
@eerhardt Given that we're compiling libraries tests with AOT now, is that the preferred path? Or is there another reason for the separation? |
The reason for the separation is the same as it always has been: When you are unit testing, your goal is exercise all the code in the code you are testing. Which means very little of it gets trimmed away (if it DOES get trimmed it means you have a test hole). The point of the trimming tests is to use the API under test in an isolated manner, with no other code being rooted in the app. See https://github.com/dotnet/designs/blob/main/accepted/2020/linking-libraries.md#testing for more info. |
I've seen a lot of calls to the varargs EventSource overload that have to manually suppress the trim warning because they only use primitive types. Adding this overload solves two problems: 1. Users won't get a warning if their usage is safe. 2. Users won't have to suppress a warning.
…ould no longer produce warnings
namespace System.Diagnostics.Tracing
{
public class EventSource : IDisposable
{
protected void WriteEvent(int eventId, params EventSourcePrimitive[] args) { }
public readonly struct EventSourcePrimitive
{
private object _reference;
private int _value;
public static implicit operator EventSourcePrimitive(bool value) => ...;
public static implicit operator EventSourcePrimitive(byte value) => ...;
public static implicit operator EventSourcePrimitive(short value) => ...;
public static implicit operator EventSourcePrimitive(int value) => ...;
public static implicit operator EventSourcePrimitive(long value) => ...;
public static implicit operator EventSourcePrimitive(sbyte value) => ...;
public static implicit operator EventSourcePrimitive(ushort value) => ...;
public static implicit operator EventSourcePrimitive(uint value) => ...;
public static implicit operator EventSourcePrimitive(ulong value) => ...;
public static implicit operator EventSourcePrimitive(float value) => ...;
public static implicit operator EventSourcePrimitive(double value) => ...;
public static implicit operator EventSourcePrimitive(decimal value) => ...;
public static implicit operator EventSourcePrimitive(string? value) => ...;
public static implicit operator EventSourcePrimitive(byte[]? value) => ...;
public static implicit operator EventSourcePrimitive(Guid value) => ...;
public static implicit operator EventSourcePrimitive(DateTime value) => ...;
public static implicit operator EventSourcePrimitive(nint value) => ...;
public static implicit operator EventSourcePrimitive(nuint value) => ...;
public static implicit operator EventSourcePrimitive(char value) => ...;
public static implicit operator EventSourcePrimitive(Enum value) => ...;
}
}
} |
@JeremyKuhne this feels like your variant proposal from a while back. |
@davidfowl yes, it does seem very similar. See #28882. I have a fully working prototype that Azure is already using internally. https://github.com/JeremyKuhne/ValuePrototype It would be nice to have a general purpose struct for this sort of stuff. |
One notable difference here is that my proposal has an additional type that |
I've deliberately left some options open here for optimizations. Also noted is some deficiencies in the overall API support
Those things would have to be addressed in a future evolution. |
@davmason I think this is ready to merge. Can you take a look? |
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.
LGTM, thanks!
@agocke are there any outstanding work items that need to be completed or is this PR ready to merge? |
@tommcdon Two failing tests: CoreCLR Linux x64 Debug and Mono Linux x64 Debug are both timing out. Trying to figure out why. |
Failures are unrelated -- also happening in main. |
Summary
I've seen a lot of calls to the varargs EventSource overload that have to manually suppress the trim warning because they only use primitive types.
This PR adds an overload that only supports primitive types, and thus will always be trim-compatible.
Adding this overload solves two problems:
Proposed API
This API exploits C# implicit conversion and overload resolution rules to prefer binding to an EventSourcePrimitive when the input type is one of the implicitly converted types.