-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add DiagnosticSource.Write<T> API to assist with trimming #50454
Comments
Tagging subscribers to this area: @tommcdon, @krwq Issue DetailsBackground and MotivationThe runtime/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs Line 34 in 82ca681
Internally, we have a In order to resolve the ILLink warnings in However, a common usage of private void RecordBeginRequestDiagnostics(HttpContext httpContext, long startTimestamp)
{
_diagnosticListener.Write(
DeprecatedDiagnosticsBeginRequestKey,
new
{
httpContext = httpContext,
timestamp = startTimestamp
}); Since the type is anonymous, there isn't a way to add a To resolve this issue, we should add a new overload to the Write method that is generic, so we can annotate the See this conversation for more background and reasoning. Proposed APInamespace System.Diagnostics
{
public abstract class DiagnosticSource
{
[RequiresUnreferencedCode]
public abstract void Write(string name, object? value);
+ [RequiresUnreferencedCode]
+ public void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(string name, T? value);
[RequiresUnreferencedCode]
public Activity StartActivity(Activity activity, object? args);
+ [RequiresUnreferencedCode]
+ public Activity StartActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(Activity activity, T? args);
[RequiresUnreferencedCode]
public void StopActivity(Activity activity, object? args);
+ [RequiresUnreferencedCode]
+ public void StopActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(Activity activity, T? args);
}
} Usage ExamplesThe usage is the same as the existing APIs. _diagnosticListener.Write(
DeprecatedDiagnosticsBeginRequestKey,
new
{
httpContext = httpContext,
timestamp = startTimestamp
}); Alternative DesignsN/A RisksIs it possible that caller may still bind to the API accepting
|
@eerhardt - I am guessing this work is not planned for 6.0 at this point? I'm changing the milestone but if this was something you plan to do you are welcome to change it further. |
Correct. This is a new API and 6.0 has reached feature complete. |
These new overloads don't quite solve the problem (recursive preservation, polymorphism), but it's an improvement at low cost. namespace System.Diagnostics
{
public abstract class DiagnosticSource
{
[RequiresUnreferencedCode]
public abstract void Write(string name, object? value);
+ [RequiresUnreferencedCode]
+ public void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(string name, T? value);
[RequiresUnreferencedCode]
public Activity StartActivity(Activity activity, object? args);
+ [RequiresUnreferencedCode]
+ public Activity StartActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(Activity activity, T? args);
[RequiresUnreferencedCode]
public void StopActivity(Activity activity, object? args);
+ [RequiresUnreferencedCode]
+ public void StopActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(Activity activity, T? args);
}
} |
Background and Motivation
The
DiagnosticSource.Write
API is not trim-friendly because the type of object being passed in cannot be statically discovered.runtime/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs
Line 34 in 82ca681
Internally, we have a
DiagnosticSourceEventSource
class which listens to events being written to aDiagnosticSource
and will forward the event on to anEventSource
. This functionality assumes that all the properties on the object, and any properties recursively on the Types of those properties, are available at runtime. It uses Reflection to access the property values based onFilterAndPayloadSpecs
strings that are passed to theDiagnosticSourceEventSource
.In order to resolve the ILLink warnings in
System.Diagnostics.DiagnosticSource
, we are markingDiagnosticSource.Write
withRequiresUnreferencedCode
. This means any caller of this API will get ILLink warnings themselves, and will need to preserve the necessary properties with[DynamicDependency]
attributes, or some other mechanism.However, a common usage of
DiagnosticSource.Write
is to pass in an anonymous type, for example this is how ASP.NET uses the API:https://github.com/dotnet/aspnetcore/blob/85a6cb07ae2e1adf5a03740f8d40333b7b8e360c/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs#L212-L218
Since the type is anonymous, there isn't a way to add a
[DynamicDependency]
pointing to the type.To resolve this issue, we should add a new overload to the Write method that is generic, so we can annotate the
T
type with a[DynamicallyAccessedMembers]
attribute. Unfortunately, this won't make the API 100% trim compatible because recursive properties aren't supported (see dotnet/linker#1087), thus it will still need to be marked as[RequiresUnreferencedCode]
. However, it will be one less set of properties callers will need to manually preserve themselves, and it will allow anonymous types to be used.See this conversation for more background and reasoning.
Proposed API
Usage Examples
The usage is the same as the existing APIs.
Alternative Designs
N/A
Risks
Is it possible that caller may still bind to the API accepting
object?
and they won't get theDynamicallyAccessedMembers
attribute applied to their types?The text was updated successfully, but these errors were encountered: