From 47ce518f037811c4595d64252a3e491d6cce807b Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Mon, 25 Jan 2021 10:09:18 -0600 Subject: [PATCH 1/3] Resolve ILLink warnings in System.Diagnostics.DiagnosticSource (Round 1) Contributes to #45623 --- .../src/ILLink/ILLink.Suppressions.xml | 8 +------- .../src/System.Diagnostics.DiagnosticSource.csproj | 4 +--- .../System/Diagnostics/DiagnosticSourceEventSource.cs | 11 ++++++----- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Suppressions.xml index b958c7cf8e0c6a..a1b30534b261af 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Suppressions.xml @@ -7,11 +7,5 @@ member M:System.Diagnostics.DiagnosticSourceEventSource.FilterAndTransform.MakeImplicitTransforms(System.Type) - - ILLink - IL2070 - member - M:System.Diagnostics.DiagnosticSourceEventSource.TransformSpec.PropertySpec.PropertyFetch.FetcherForProperty(System.Type,System.String) - - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index d5a7d0ac9ff5ad..92292532c52897 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -1,4 +1,4 @@ - + true false @@ -29,8 +29,6 @@ - - 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 154cd8c07b6b00..8f0c407148a479 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -1331,9 +1331,6 @@ public PropertyFetch(Type? type) /// /// Create a property fetcher for a propertyName /// - [DynamicDependency("#ctor(System.Type)", typeof(EnumeratePropertyFetch<>))] - [DynamicDependency("#ctor(System.Type,System.Reflection.PropertyInfo)", typeof(RefTypedFetchProperty<,>))] - [DynamicDependency("#ctor(System.Type,System.Reflection.PropertyInfo)", typeof(ValueTypedFetchProperty<,>))] public static PropertyFetch FetcherForProperty(Type? type, string propertyName) { if (propertyName == null) @@ -1382,10 +1379,14 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName) } else { - PropertyInfo? propertyInfo = typeInfo.GetDeclaredProperty(propertyName); + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:RequiresUnreferencedCode", + Justification = "If the property is trimmed, a message gets logged to inform the user.")] + static PropertyInfo? GetProperty(TypeInfo type, string name) => type.GetDeclaredProperty(name); + + PropertyInfo? propertyInfo = GetProperty(typeInfo, propertyName); if (propertyInfo == null) { - Logger.Message($"Property {propertyName} not found on {type}"); + Logger.Message($"Property {propertyName} not found on {type}. Ensure the name is spelled correctly. If you published the application with PublishTrimmed=true, ensure the property was not trimmed away."); return new PropertyFetch(type); } // Delegate creation below is incompatible with static properties. From d6ef851cf19bad752b94cc82eba512523855b2c4 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 30 Mar 2021 16:49:38 -0500 Subject: [PATCH 2/3] Update based on the following plan: 1. Mark DiagnosticSource.Write(string,object) as RequiresUnreferencedCode 2. Suppress the warnings for any .NET libraries that call the DiagnosticSource.Write() API, and annotate the .NET types being passed in to preserve their important properties. - This was done for HttpClient. ASP.NET and EF will need separate changes when those assemblies are made trim compatible 3. Annotate Activity and its small closure of types (ActivityLink, ActivityEvent, ActivityContext, etc) to ensure none of those properties are trimmed. 4. Suppress trim warnings inside DiagnosticSourceEventSource since the public Write method is marked with RequiresUnreferencedCode. --- .../src/ILLink/ILLink.Suppressions.xml | 11 --- ...System.Diagnostics.DiagnosticSource.csproj | 3 + .../System/Diagnostics/DiagnosticListener.cs | 2 + .../System/Diagnostics/DiagnosticSource.cs | 4 + .../Diagnostics/DiagnosticSourceActivity.cs | 3 + .../DiagnosticSourceEventSource.cs | 93 ++++++++++++------- .../src/System/Net/Http/DiagnosticsHandler.cs | 62 ++++++++++++- 7 files changed, 127 insertions(+), 51 deletions(-) delete mode 100644 src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Suppressions.xml diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Suppressions.xml deleted file mode 100644 index a1b30534b261af..00000000000000 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/ILLink/ILLink.Suppressions.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - ILLink - IL2070 - member - M:System.Diagnostics.DiagnosticSourceEventSource.FilterAndTransform.MakeImplicitTransforms(System.Type) - - - diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index 92292532c52897..ab2970430a42c3 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -29,6 +29,9 @@ + + + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs index 4aaf2bb37afbac..c851f1db6c67d7 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticListener.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics { @@ -255,6 +256,7 @@ public override bool IsEnabled(string name, object? arg1, object? arg2 = null) /// /// Override abstract method /// + [RequiresUnreferencedCode(WriteRequiresUnreferencedCode)] public override void Write(string name, object? value) { for (DiagnosticSubscription? curSubscription = _subscriptions; curSubscription != null; curSubscription = curSubscription.Next) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs index 10ad9e62a26166..2db2e7ff48cf29 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSource.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics { @@ -15,6 +16,8 @@ namespace System.Diagnostics /// public abstract partial class DiagnosticSource { + internal const string WriteRequiresUnreferencedCode = "The type of object being written to DiagnosticSource cannot be discovered statically."; + /// /// Write is a generic way of logging complex payloads. Each notification /// is given a name, which identifies it as well as a object (typically an anonymous type) @@ -31,6 +34,7 @@ public abstract partial class DiagnosticSource /// The name of the event being written. /// An object that represent the value being passed as a payload for the event. /// This is often an anonymous type which contains several sub-values. + [RequiresUnreferencedCode(WriteRequiresUnreferencedCode)] public abstract void Write(string name, object? value); /// diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs index 549c4a8274cb20..3a10702ca1400b 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceActivity.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics { @@ -24,6 +25,7 @@ public abstract partial class DiagnosticSource /// An object that represent the value being passed as a payload for the event. /// Started Activity for convenient chaining /// + [RequiresUnreferencedCode(WriteRequiresUnreferencedCode)] public Activity StartActivity(Activity activity, object? args) { activity.Start(); @@ -41,6 +43,7 @@ public Activity StartActivity(Activity activity, object? args) /// Activity to be stopped /// An object that represent the value being passed as a payload for the event. /// + [RequiresUnreferencedCode(WriteRequiresUnreferencedCode)] public void StopActivity(Activity activity, object? args) { // Stop sets the end time if it was unset, but we want it set before we issue the write 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 8f0c407148a479..f1f0bcbceb7936 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -717,7 +717,9 @@ public FilterAndTransform(string filterAndPayloadSpec, int startIdx, int endIdx, if (eventNameFilter != null) eventNameFilterPredicate = (string eventName) => eventNameFilter == eventName; - var subscription = newListener.Subscribe(new CallbackObserver>(delegate (KeyValuePair evnt) + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "DiagnosticSource.Write is marked with RequiresUnreferencedCode.")] + void OnEventWritten(KeyValuePair evnt) { // The filter given to the DiagnosticSource may not work if users don't is 'IsEnabled' as expected. // Thus we look for any events that may have snuck through and filter them out before forwarding. @@ -727,7 +729,9 @@ public FilterAndTransform(string filterAndPayloadSpec, int startIdx, int endIdx, var outputArgs = this.Morph(evnt.Value); var eventName = evnt.Key; writeEvent(newListener.Name, eventName, outputArgs); - }), eventNameFilterPredicate); + } + + var subscription = newListener.Subscribe(new CallbackObserver>(OnEventWritten), eventNameFilterPredicate); _liveSubscriptions = new Subscriptions(subscription, _liveSubscriptions); } })); @@ -948,41 +952,55 @@ internal static void CreateActivityListener(DiagnosticSourceEventSource eventSou return false; }; - eventSource._activityListener.ActivityStarted = activity => + eventSource._activityListener.ActivityStarted = activity => OnActivityStarted(eventSource, activity); + + eventSource._activityListener.ActivityStopped = activity => OnActivityStopped(eventSource, activity); + + ActivitySource.AddActivityListener(eventSource._activityListener); + } + + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(Activity))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(ActivityContext))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(ActivityEvent))] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(ActivityLink))] + [DynamicDependency(nameof(DateTime.Ticks), typeof(DateTime))] + [DynamicDependency(nameof(TimeSpan.Ticks), typeof(TimeSpan))] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")] + private static void OnActivityStarted(DiagnosticSourceEventSource eventSource, Activity activity) + { + FilterAndTransform? list = eventSource._activitySourceSpecs; + while (list != null) { - FilterAndTransform? list = eventSource._activitySourceSpecs; - while (list != null) + if ((list.Events & ActivityEvents.ActivityStart) != 0 && + (activity.Source.Name == list.SourceName || list.SourceName == "*") && + (list.ActivityName == null || list.ActivityName == activity.OperationName)) { - if ((list.Events & ActivityEvents.ActivityStart) != 0 && - (activity.Source.Name == list.SourceName || list.SourceName == "*") && - (list.ActivityName == null || list.ActivityName == activity.OperationName)) - { - eventSource.ActivityStart(activity.Source.Name, activity.OperationName, list.Morph(activity)); - return; - } - - list = list.Next; + eventSource.ActivityStart(activity.Source.Name, activity.OperationName, list.Morph(activity)); + return; } - }; - eventSource._activityListener.ActivityStopped = activity => + list = list.Next; + } + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")] + private static void OnActivityStopped(DiagnosticSourceEventSource eventSource, Activity activity) + { + FilterAndTransform? list = eventSource._activitySourceSpecs; + while (list != null) { - FilterAndTransform? list = eventSource._activitySourceSpecs; - while (list != null) + if ((list.Events & ActivityEvents.ActivityStop) != 0 && + (activity.Source.Name == list.SourceName || list.SourceName == "*") && + (list.ActivityName == null || list.ActivityName == activity.OperationName)) { - if ((list.Events & ActivityEvents.ActivityStop) != 0 && - (activity.Source.Name == list.SourceName || list.SourceName == "*") && - (list.ActivityName == null || list.ActivityName == activity.OperationName)) - { - eventSource.ActivityStop(activity.Source.Name, activity.OperationName, list.Morph(activity)); - return; - } - - list = list.Next; + eventSource.ActivityStop(activity.Source.Name, activity.OperationName, list.Morph(activity)); + return; } - }; - ActivitySource.AddActivityListener(eventSource._activityListener); + list = list.Next; + } } // Move all wildcard nodes at the end of the list. @@ -1067,6 +1085,7 @@ private void Dispose() } } + [RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)] public List> Morph(object? args) { // Transform the args into a bag of key-value strings. @@ -1105,7 +1124,11 @@ private void Dispose() Interlocked.CompareExchange(ref _implicitTransformsTable, new ConcurrentDictionary(1, 8), null); } - implicitTransforms = _implicitTransformsTable.GetOrAdd(argType, type => MakeImplicitTransforms(type)); + implicitTransforms = _implicitTransformsTable.GetOrAdd(argType, type => MakeImplicitTransformsWrapper(type)); + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The Morph method has RequiresUnreferencedCode, but the trimmer can't see through lamdba calls.")] + static TransformSpec? MakeImplicitTransformsWrapper(Type transformType) => MakeImplicitTransforms(transformType); } // implicitTransformas now fetched from cache or constructed, use it to Fetch all the implicit fields. @@ -1145,6 +1168,7 @@ private void Dispose() // Given a type generate all the implicit transforms for type (that is for every field // generate the spec that fetches it). + [RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)] private static TransformSpec? MakeImplicitTransforms(Type type) { TransformSpec? newSerializableArgs = null; @@ -1239,6 +1263,7 @@ public TransformSpec(string transformSpec, int startIdx, int endIdx, TransformSp /// if the spec is OUTSTR=EVENT_VALUE.PROP1.PROP2.PROP3 and the ultimate value of PROP3 is /// 10 then the return key value pair is KeyValuePair("OUTSTR","10") /// + [RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)] public KeyValuePair Morph(object? obj) { for (PropertySpec? cur = _fetches; cur != null; cur = cur.Next) @@ -1289,6 +1314,7 @@ public PropertySpec(string propertyName, PropertySpec? next) /// Given an object fetch the property that this PropertySpec represents. /// obj may be null when IsStatic is true, otherwise it must be non-null. /// + [RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)] public object? Fetch(object? obj) { PropertyFetch? fetch = _fetchForExpectedType; @@ -1331,6 +1357,7 @@ public PropertyFetch(Type? type) /// /// Create a property fetcher for a propertyName /// + [RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)] public static PropertyFetch FetcherForProperty(Type? type, string propertyName) { if (propertyName == null) @@ -1379,11 +1406,7 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName) } else { - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:RequiresUnreferencedCode", - Justification = "If the property is trimmed, a message gets logged to inform the user.")] - static PropertyInfo? GetProperty(TypeInfo type, string name) => type.GetDeclaredProperty(name); - - PropertyInfo? propertyInfo = GetProperty(typeInfo, propertyName); + PropertyInfo? propertyInfo = typeInfo.GetDeclaredProperty(propertyName); if (propertyInfo == null) { Logger.Message($"Property {propertyName} not found on {type}. Ensure the name is spelled correctly. If you published the application with PublishTrimmed=true, ensure the property was not trimmed away."); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs index ab88b3578df1ab..4e4d730c4c188a 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; @@ -90,7 +91,7 @@ await base.SendAsync(request, cancellationToken).ConfigureAwait(false) : // Only send start event to users who subscribed for it, but start activity anyway if (diagnosticListener.IsEnabled(DiagnosticsHandlerLoggingStrings.ActivityStartName)) { - diagnosticListener.StartActivity(activity, new ActivityStartData(request)); + StartActivity(diagnosticListener, activity, new ActivityStartData(request)); } else { @@ -102,7 +103,7 @@ await base.SendAsync(request, cancellationToken).ConfigureAwait(false) : { long timestamp = Stopwatch.GetTimestamp(); loggingRequestId = Guid.NewGuid(); - diagnosticListener.Write(DiagnosticsHandlerLoggingStrings.RequestWriteNameDeprecated, + Write(diagnosticListener, DiagnosticsHandlerLoggingStrings.RequestWriteNameDeprecated, new RequestData(request, loggingRequestId, timestamp)); } @@ -138,7 +139,7 @@ await base.SendAsync(request, cancellationToken).ConfigureAwait(false) : // If request was initially instrumented, Activity.Current has all necessary context for logging // Request is passed to provide some context if instrumentation was disabled and to avoid // extensive Activity.Tags usage to tunnel request properties - diagnosticListener.Write(DiagnosticsHandlerLoggingStrings.ExceptionEventName, new ExceptionData(ex, request)); + Write(diagnosticListener, DiagnosticsHandlerLoggingStrings.ExceptionEventName, new ExceptionData(ex, request)); } throw; } @@ -147,7 +148,7 @@ await base.SendAsync(request, cancellationToken).ConfigureAwait(false) : // always stop activity if it was started if (activity != null) { - diagnosticListener.StopActivity(activity, new ActivityStopData( + StopActivity(diagnosticListener, activity, new ActivityStopData( response, // If request is failed or cancelled, there is no response, therefore no information about request; // pass the request in the payload, so consumers can have it in Stop for failed/canceled requests @@ -159,7 +160,7 @@ await base.SendAsync(request, cancellationToken).ConfigureAwait(false) : if (diagnosticListener.IsEnabled(DiagnosticsHandlerLoggingStrings.ResponseWriteNameDeprecated)) { long timestamp = Stopwatch.GetTimestamp(); - diagnosticListener.Write(DiagnosticsHandlerLoggingStrings.ResponseWriteNameDeprecated, + Write(diagnosticListener, DiagnosticsHandlerLoggingStrings.ResponseWriteNameDeprecated, new ResponseData( response, loggingRequestId, @@ -173,6 +174,12 @@ await base.SendAsync(request, cancellationToken).ConfigureAwait(false) : private sealed class ActivityStartData { + // matches the properties selected in https://github.com/dotnet/diagnostics/blob/ffd0254da3bcc47847b1183fa5453c0877020abd/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/HttpRequestSourceConfiguration.cs#L36-L40 + [DynamicDependency(nameof(HttpRequestMessage.RequestUri), typeof(HttpRequestMessage))] + [DynamicDependency(nameof(HttpRequestMessage.Method), typeof(HttpRequestMessage))] + [DynamicDependency(nameof(HttpRequestMessage.RequestUri), typeof(HttpRequestMessage))] + [DynamicDependency(nameof(Uri.Host), typeof(Uri))] + [DynamicDependency(nameof(Uri.Port), typeof(Uri))] internal ActivityStartData(HttpRequestMessage request) { Request = request; @@ -201,6 +208,14 @@ internal ActivityStopData(HttpResponseMessage? response, HttpRequestMessage requ private sealed class ExceptionData { + // preserve the same properties as ActivityStartData above + common Exception properties + [DynamicDependency(nameof(HttpRequestMessage.RequestUri), typeof(HttpRequestMessage))] + [DynamicDependency(nameof(HttpRequestMessage.Method), typeof(HttpRequestMessage))] + [DynamicDependency(nameof(HttpRequestMessage.RequestUri), typeof(HttpRequestMessage))] + [DynamicDependency(nameof(Uri.Host), typeof(Uri))] + [DynamicDependency(nameof(Uri.Port), typeof(Uri))] + [DynamicDependency(nameof(System.Exception.Message), typeof(Exception))] + [DynamicDependency(nameof(System.Exception.StackTrace), typeof(Exception))] internal ExceptionData(Exception exception, HttpRequestMessage request) { Exception = exception; @@ -215,6 +230,12 @@ internal ExceptionData(Exception exception, HttpRequestMessage request) private sealed class RequestData { + // preserve the same properties as ActivityStartData above + [DynamicDependency(nameof(HttpRequestMessage.RequestUri), typeof(HttpRequestMessage))] + [DynamicDependency(nameof(HttpRequestMessage.Method), typeof(HttpRequestMessage))] + [DynamicDependency(nameof(HttpRequestMessage.RequestUri), typeof(HttpRequestMessage))] + [DynamicDependency(nameof(Uri.Host), typeof(Uri))] + [DynamicDependency(nameof(Uri.Port), typeof(Uri))] internal RequestData(HttpRequestMessage request, Guid loggingRequestId, long timestamp) { Request = request; @@ -231,6 +252,7 @@ internal RequestData(HttpRequestMessage request, Guid loggingRequestId, long tim private sealed class ResponseData { + [DynamicDependency(nameof(HttpResponseMessage.StatusCode), typeof(HttpResponseMessage))] internal ResponseData(HttpResponseMessage? response, Guid loggingRequestId, long timestamp, TaskStatus requestTaskStatus) { Response = response; @@ -316,6 +338,36 @@ private static void InjectHeaders(Activity currentActivity, HttpRequestMessage r } } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "The values being passed into Write have the commonly used properties being preserved with DynamicDependency.")] + private static void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( + DiagnosticSource diagnosticSource, + string name, + T value) + { + diagnosticSource.Write(name, value); + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "The args being passed into StartActivity have the commonly used properties being preserved with DynamicDependency.")] + private static Activity StartActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( + DiagnosticSource diagnosticSource, + Activity activity, + T? args) + { + return diagnosticSource.StartActivity(activity, args); + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "The args being passed into StopActivity have the commonly used properties being preserved with DynamicDependency.")] + private static void StopActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( + DiagnosticSource diagnosticSource, + Activity activity, + T? args) + { + diagnosticSource.StopActivity(activity, args); + } + #endregion } } From f632025be678e6e731853f2471f3062a116b7f7d Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Wed, 31 Mar 2021 12:08:14 -0500 Subject: [PATCH 3/3] Update ref assembly with new attributes. --- .../ref/System.Diagnostics.DiagnosticSource.cs | 2 ++ .../ref/System.Diagnostics.DiagnosticSource.csproj | 1 + .../ref/System.Diagnostics.DiagnosticSourceActivity.cs | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs index 989d4486ffb1a3..1b08291cccd2ab 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.cs @@ -19,6 +19,7 @@ public virtual void Dispose() { } public virtual System.IDisposable Subscribe(System.IObserver> observer, System.Func? isEnabled) { throw null; } public virtual System.IDisposable Subscribe(System.IObserver> observer, System.Predicate? isEnabled) { throw null; } public override string ToString() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public override void Write(string name, object? value) { } } public abstract partial class DiagnosticSource @@ -26,6 +27,7 @@ public abstract partial class DiagnosticSource protected DiagnosticSource() { } public abstract bool IsEnabled(string name); public virtual bool IsEnabled(string name, object? arg1, object? arg2 = null) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public abstract void Write(string name, object? value); } } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.csproj index e34e24c6fbf3bb..779380efcdefc9 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSource.csproj @@ -12,6 +12,7 @@ + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index 73ce2d5eab1539..9402388ca45b93 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -192,7 +192,9 @@ public abstract partial class DiagnosticSource { public virtual void OnActivityExport(System.Diagnostics.Activity activity, object? payload) { } public virtual void OnActivityImport(System.Diagnostics.Activity activity, object? payload) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public System.Diagnostics.Activity StartActivity(System.Diagnostics.Activity activity, object? args) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The type of object being written to DiagnosticSource cannot be discovered statically.")] public void StopActivity(System.Diagnostics.Activity activity, object? args) { } } public enum ActivitySamplingResult