Skip to content

Commit

Permalink
Annotating System.Diagnostics.DiagnosticSource on AOT (dotnet#72706)
Browse files Browse the repository at this point in the history
* Annotating System.Diagnostics.DiagnosticSource on AOT

* FB + enable tests

* FB

* warning message FB

* comment FB2

* Warning message revision to reflect AOT problems at code generation
  • Loading branch information
LakshanF committed Aug 3, 2022
1 parent c1357bc commit 1926f09
Show file tree
Hide file tree
Showing 14 changed files with 61 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public virtual void Dispose() { }
public virtual System.IDisposable Subscribe(System.IObserver<System.Collections.Generic.KeyValuePair<string, object?>> observer, System.Predicate<string>? 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.")]
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
public override void Write(string name, object? value) { }
}
public abstract partial class DiagnosticSource
Expand All @@ -28,6 +29,7 @@ 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.")]
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
public abstract void Write(string name, object? value);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
<CLSCompliant>false</CLSCompliant>
Expand All @@ -15,6 +15,10 @@
<Compile Include="$(CoreLibSharedDir)System\Runtime\CompilerServices\IsExternalInit.cs" />
</ItemGroup>

<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
<Compile Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\RequiresDynamicCodeAttribute.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == '$(NetCoreAppCurrent)'">
<ProjectReference Include="$(LibrariesProjectRoot)System.Runtime\ref\System.Runtime.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,10 @@ 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.")]
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
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.")]
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
public void StopActivity(System.Diagnostics.Activity activity, object? args) { }
}
public enum ActivitySamplingResult
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<IsPackable>true</IsPackable>
<!-- Lifetime rules introduced in C# 11 impact scenarios in net6 framework -->
<LangVersion Condition="'$(TargetFramework)' == 'net6.0'">10</LangVersion>
<EnableAOTAnalyzer>true</EnableAOTAnalyzer>
<PackageDescription>Provides Classes that allow you to decouple code logging rich (unserializable) diagnostics/telemetry (e.g. framework) from code that consumes it (e.g. tools)

Commonly Used Types:
Expand Down Expand Up @@ -103,6 +104,10 @@ System.Diagnostics.DiagnosticSource</PackageDescription>
<Compile Include="$(CoreLibSharedDir)System\Runtime\CompilerServices\IsExternalInit.cs" />
</ItemGroup>

<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))" >
<Compile Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\RequiresDynamicCodeAttribute.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' or
'$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="System\Diagnostics\Activity.DateTime.corefx.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public partial class DiagnosticListener : DiagnosticSource, IObservable<KeyValue
/// </summary>
public static IObservable<DiagnosticListener> AllListeners
{
[UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
Justification = "ENABLE_HTTP_HANDLER is not enabled in the .NET current version")]
get
{
#if ENABLE_HTTP_HANDLER
Expand Down Expand Up @@ -253,6 +255,7 @@ public override bool IsEnabled(string name, object? arg1, object? arg2 = null)
/// Override abstract method
/// </summary>
[RequiresUnreferencedCode(WriteRequiresUnreferencedCode)]
[RequiresDynamicCode(WriteRequiresDynamicCode)]
public override void Write(string name, object? value)
{
for (DiagnosticSubscription? curSubscription = _subscriptions; curSubscription != null; curSubscription = curSubscription.Next)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace System.Diagnostics
public abstract partial class DiagnosticSource
{
internal const string WriteRequiresUnreferencedCode = "The type of object being written to DiagnosticSource cannot be discovered statically.";
internal const string WriteRequiresDynamicCode = "DiagnosticSource may require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.";

/// <summary>
/// Write is a generic way of logging complex payloads. Each notification
Expand All @@ -35,6 +36,7 @@ public abstract partial class DiagnosticSource
/// <param name="value">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.</param>
[RequiresUnreferencedCode(WriteRequiresUnreferencedCode)]
[RequiresDynamicCode(WriteRequiresDynamicCode)]
public abstract void Write(string name, object? value);

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public abstract partial class DiagnosticSource
/// <returns>Started Activity for convenient chaining</returns>
/// <seealso cref="Activity"/>
[RequiresUnreferencedCode(WriteRequiresUnreferencedCode)]
[RequiresDynamicCode(WriteRequiresDynamicCode)]
public Activity StartActivity(Activity activity, object? args)
{
activity.Start();
Expand All @@ -44,6 +45,7 @@ public Activity StartActivity(Activity activity, object? args)
/// <param name="args">An object that represent the value being passed as a payload for the event.</param>
/// <seealso cref="Activity"/>
[RequiresUnreferencedCode(WriteRequiresUnreferencedCode)]
[RequiresDynamicCode(WriteRequiresDynamicCode)]
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,8 @@ public FilterAndTransform(string filterAndPayloadSpec, int startIdx, int endIdx,
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2119",
Justification = "DAM on EventSource references this compiler-generated local function which calls a " +
"method that requires unreferenced code. EventSource will not access this local function.")]
[UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
Justification = "DiagnosticSource.Write is marked with RequiresDynamicCode.")]
void OnEventWritten(KeyValuePair<string, object?> evnt)
{
// The filter given to the DiagnosticSource may not work if users don't is 'IsEnabled' as expected.
Expand Down Expand Up @@ -888,6 +890,8 @@ internal static void CreateActivityListener(DiagnosticSourceEventSource eventSou
[DynamicDependency(nameof(TimeSpan.Ticks), typeof(TimeSpan))]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")]
[UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
Justification = "Activity is a reference type and is safe in aot.")]
private static void OnActivityStarted(DiagnosticSourceEventSource eventSource, Activity activity)
{
FilterAndTransform? list = eventSource._activitySourceSpecs;
Expand All @@ -907,6 +911,8 @@ private static void OnActivityStarted(DiagnosticSourceEventSource eventSource, A

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
Justification = "Activity's properties are being preserved with the DynamicDependencies on OnActivityStarted.")]
[UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
Justification = "Activity is a reference type and is safe with aot.")]
private static void OnActivityStopped(DiagnosticSourceEventSource eventSource, Activity activity)
{
FilterAndTransform? list = eventSource._activitySourceSpecs;
Expand Down Expand Up @@ -1009,6 +1015,7 @@ private void Dispose()
Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " +
"requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")]
[RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)]
[RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)]
public List<KeyValuePair<string, string?>> Morph(object? args)
{
// Transform the args into a bag of key-value strings.
Expand Down Expand Up @@ -1190,6 +1197,7 @@ public TransformSpec(string transformSpec, int startIdx, int endIdx, TransformSp
Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " +
"requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")]
[RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)]
[RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)]
public KeyValuePair<string, string?> Morph(object? obj)
{
for (PropertySpec? cur = _fetches; cur != null; cur = cur.Next)
Expand Down Expand Up @@ -1244,6 +1252,7 @@ public PropertySpec(string propertyName, PropertySpec? next)
Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " +
"requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")]
[RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)]
[RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)]
public object? Fetch(object? obj)
{
PropertyFetch? fetch = _fetchForExpectedType;
Expand Down Expand Up @@ -1290,6 +1299,7 @@ public PropertyFetch(Type? type)
Justification = "In EventSource, EnsureDescriptorsInitialized's use of GetType preserves this method which " +
"requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")]
[RequiresUnreferencedCode(DiagnosticSource.WriteRequiresUnreferencedCode)]
[RequiresDynamicCode(DiagnosticSource.WriteRequiresDynamicCode)]
public static PropertyFetch FetcherForProperty(Type? type, string propertyName)
{
if (propertyName == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Reflection;
using System.Reflection.Emit;
Expand All @@ -24,6 +25,7 @@ namespace System.Diagnostics
/// when it sees the System.Net.Http.Desktop source, subscribe to it. This will trigger the
/// initialization of this DiagnosticListener.
/// </summary>
[RequiresDynamicCode(WriteRequiresDynamicCode)]
internal sealed class HttpHandlerDiagnosticListener : DiagnosticListener
{
/// <summary>
Expand Down Expand Up @@ -202,6 +204,7 @@ public override void Remove(object key)
/// intercept each new ServicePoint object being added to ServicePointManager.s_ServicePointTable
/// and replace its ConnectionGroupList hashtable field.
/// </summary>
[RequiresDynamicCode(WriteRequiresDynamicCode)]
private sealed class ServicePointHashtable : HashtableWrapper
{
public ServicePointHashtable(Hashtable table) : base(table)
Expand Down Expand Up @@ -242,6 +245,7 @@ public override object this[object key]
/// intercept each new ConnectionGroup object being added to ServicePoint.m_ConnectionGroupList
/// and replace its m_ConnectionList arraylist field.
/// </summary>
[RequiresDynamicCode(WriteRequiresDynamicCode)]
private sealed class ConnectionGroupHashtable : HashtableWrapper
{
public ConnectionGroupHashtable(Hashtable table) : base(table)
Expand Down Expand Up @@ -481,6 +485,7 @@ public override void TrimToSize()
/// intercept each new Connection object being added to ConnectionGroup.m_ConnectionList
/// and replace its m_WriteList arraylist field.
/// </summary>
[RequiresDynamicCode(WriteRequiresDynamicCode)]
private sealed class ConnectionArrayList : ArrayListWrapper
{
public ConnectionArrayList(ArrayList list) : base(list)
Expand Down Expand Up @@ -511,6 +516,7 @@ public override int Add(object value)
/// It also intercepts all HttpWebRequest objects that are about to get removed from
/// Connection.m_WriteList as they have completed the request.
/// </summary>
[RequiresDynamicCode(WriteRequiresDynamicCode)]
private sealed class HttpWebRequestArrayList : ArrayListWrapper
{
public HttpWebRequestArrayList(ArrayList list) : base(list)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Versioning;
using System.Security;
using System.Threading;
Expand Down Expand Up @@ -249,6 +250,8 @@ private void RemoveInstrumentState(Instrument instrument, InstrumentState state)
return instrumentState;
}

[UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
Justification = "MakeGenericType is creating instances over reference types that works fine in AOT.")]
internal InstrumentState? BuildInstrumentState(Instrument instrument)
{
Func<Aggregator?>? createAggregatorFunc = GetAggregatorFactory(instrument);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,7 @@ private void AssertActivityMatchesEvent(Activity a, DiagnosticSourceEvent e, boo
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/72801", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))]
public void NoExceptionThrownWhenProcessingStaticActivityProperties()
{
// Ensures that no exception is thrown when static properties on the Activity type are passed to EventListener.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
<PropertyGroup>
<DefineConstants Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">$(DefineConstants);MEMORYMARSHAL_SUPPORT</DefineConstants>
</PropertyGroup>
<ItemGroup>
<RdXmlFile Include="default.rd.xml" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
<Compile Include="DiagnosticSourceEventSourceBridgeTests.cs" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Directives>
<Application>
<Assembly Name="mscorlib" />
<Assembly Name="System.Runtime" />
<Assembly Name="System.Private.CoreLib">
<Type Name="System.IEquatable`1[[System.Diagnostics.ActivityLink, System.Diagnostics.DiagnosticSource]]">
<Method Name="Equals" Dynamic="Required All">
</Method>
</Type>
</Assembly>
<Assembly Name="System.Diagnostics.DiagnosticSource">
<Type Name="System.Diagnostics.ActivityEvent" Dynamic="Required All" />
<Type Name="System.Diagnostics.Activity+TagsLinkedList" Dynamic="Required All" />
<Type Name="System.Diagnostics.DiagLinkedList`1[[System.Diagnostics.ActivityEvent, System.Diagnostics.DiagnosticSource]]" Dynamic="Required All" />
</Assembly>
</Application>
</Directives>
1 change: 0 additions & 1 deletion src/libraries/tests.proj
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,6 @@
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Security.Cryptography.Xml\tests\System.Security.Cryptography.Xml.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)Microsoft.Extensions.Logging.EventSource\tests\Microsoft.Extensions.Logging.EventSource.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.ComponentModel.Annotations\tests\System.ComponentModel.Annotations.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Diagnostics.DiagnosticSource\tests\System.Diagnostics.DiagnosticSource.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Threading.RateLimiting\tests\System.Threading.RateLimiting.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)Microsoft.Extensions.Caching.Memory\tests\Microsoft.Extensions.Caching.Memory.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)Microsoft.Extensions.Configuration.Xml\tests\Microsoft.Extensions.Configuration.Xml.Tests.csproj" />
Expand Down

0 comments on commit 1926f09

Please sign in to comment.