Skip to content

Commit c395276

Browse files
committed
Annotate Serilog.Settings.Configuration as not trim-compatible
Unfortunately I don't have any good news for this library. It looks like the fundamental concept, loading arbitrary types by name from arbitrary assemblies, configured by the user at run-time, is fundamentally incompatible with trimming and AOT. This at least marks it as such. Supporting a feature set like the one provided here would likely require a source generator, or build-time code generation phase.
1 parent eae1ded commit c395276

9 files changed

+183
-8
lines changed

src/Serilog.Settings.Configuration/ConfigurationLoggerConfigurationExtensions.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using System.Diagnostics.CodeAnalysis;
1516
using System.Reflection;
1617
using Microsoft.Extensions.Configuration;
1718
using Microsoft.Extensions.DependencyModel;
@@ -43,6 +44,8 @@ public static class ConfigurationLoggerConfigurationExtensions
4344
/// default will be used.</param>
4445
/// <returns>An object allowing configuration to continue.</returns>
4546
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")]
47+
[RequiresUnreferencedCode(TrimWarningMessages.NotSupportedWhenTrimming)]
48+
[RequiresDynamicCode(TrimWarningMessages.NotSupportedInAot)]
4649
public static LoggerConfiguration Configuration(
4750
this LoggerSettingsConfiguration settingConfiguration,
4851
IConfiguration configuration,
@@ -68,6 +71,8 @@ public static LoggerConfiguration Configuration(
6871
/// default will be used.</param>
6972
/// <returns>An object allowing configuration to continue.</returns>
7073
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")]
74+
[RequiresUnreferencedCode(TrimWarningMessages.NotSupportedWhenTrimming)]
75+
[RequiresDynamicCode(TrimWarningMessages.NotSupportedInAot)]
7176
public static LoggerConfiguration Configuration(
7277
this LoggerSettingsConfiguration settingConfiguration,
7378
IConfiguration configuration,
@@ -84,6 +89,8 @@ public static LoggerConfiguration Configuration(
8489
/// default will be used.</param>
8590
/// <returns>An object allowing configuration to continue.</returns>
8691
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, string sectionName, DependencyContext dependencyContext) instead.")]
92+
[RequiresUnreferencedCode(TrimWarningMessages.NotSupportedWhenTrimming)]
93+
[RequiresDynamicCode(TrimWarningMessages.NotSupportedInAot)]
8794
public static LoggerConfiguration ConfigurationSection(
8895
this LoggerSettingsConfiguration settingConfiguration,
8996
IConfigurationSection configSection,
@@ -115,6 +122,8 @@ public static LoggerConfiguration ConfigurationSection(
115122
/// <param name="configurationAssemblySource">Defines how the package identifies assemblies to scan for sinks and other types.</param>
116123
/// <returns>An object allowing configuration to continue.</returns>
117124
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")]
125+
[RequiresUnreferencedCode(TrimWarningMessages.NotSupportedWhenTrimming)]
126+
[RequiresDynamicCode(TrimWarningMessages.NotSupportedInAot)]
118127
public static LoggerConfiguration Configuration(
119128
this LoggerSettingsConfiguration settingConfiguration,
120129
IConfiguration configuration,
@@ -139,6 +148,8 @@ public static LoggerConfiguration Configuration(
139148
/// <param name="configurationAssemblySource">Defines how the package identifies assemblies to scan for sinks and other types.</param>
140149
/// <returns>An object allowing configuration to continue.</returns>
141150
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")]
151+
[RequiresUnreferencedCode(TrimWarningMessages.NotSupportedWhenTrimming)]
152+
[RequiresDynamicCode(TrimWarningMessages.NotSupportedInAot)]
142153
public static LoggerConfiguration Configuration(
143154
this LoggerSettingsConfiguration settingConfiguration,
144155
IConfiguration configuration,
@@ -154,6 +165,8 @@ public static LoggerConfiguration Configuration(
154165
/// <param name="configurationAssemblySource">Defines how the package identifies assemblies to scan for sinks and other types.</param>
155166
/// <returns>An object allowing configuration to continue.</returns>
156167
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, string sectionName, ConfigurationAssemblySource configurationAssemblySource) instead.")]
168+
[RequiresUnreferencedCode(TrimWarningMessages.NotSupportedWhenTrimming)]
169+
[RequiresDynamicCode(TrimWarningMessages.NotSupportedInAot)]
157170
public static LoggerConfiguration ConfigurationSection(
158171
this LoggerSettingsConfiguration settingConfiguration,
159172
IConfigurationSection configSection,
@@ -176,6 +189,8 @@ public static LoggerConfiguration ConfigurationSection(
176189
/// <param name="assemblies">A collection of assemblies that contains sinks and other types.</param>
177190
/// <returns>An object allowing configuration to continue.</returns>
178191
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")]
192+
[RequiresUnreferencedCode(TrimWarningMessages.NotSupportedWhenTrimming)]
193+
[RequiresDynamicCode(TrimWarningMessages.NotSupportedInAot)]
179194
public static LoggerConfiguration Configuration(
180195
this LoggerSettingsConfiguration settingConfiguration,
181196
IConfiguration configuration,
@@ -198,6 +213,8 @@ public static LoggerConfiguration Configuration(
198213
/// <param name="assemblies">A collection of assemblies that contains sinks and other types.</param>
199214
/// <returns>An object allowing configuration to continue.</returns>
200215
[Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")]
216+
[RequiresUnreferencedCode(TrimWarningMessages.NotSupportedWhenTrimming)]
217+
[RequiresDynamicCode(TrimWarningMessages.NotSupportedInAot)]
201218
public static LoggerConfiguration Configuration(
202219
this LoggerSettingsConfiguration settingConfiguration,
203220
IConfiguration configuration,
@@ -211,6 +228,8 @@ public static LoggerConfiguration Configuration(
211228
/// <param name="configuration">A configuration object which contains a Serilog section.</param>
212229
/// <param name="readerOptions">Options to adjust how the configuration object is processed.</param>
213230
/// <returns>An object allowing configuration to continue.</returns>
231+
[RequiresUnreferencedCode(TrimWarningMessages.NotSupportedWhenTrimming)]
232+
[RequiresDynamicCode(TrimWarningMessages.NotSupportedInAot)]
214233
public static LoggerConfiguration Configuration(
215234
this LoggerSettingsConfiguration settingConfiguration,
216235
IConfiguration configuration,
@@ -225,20 +244,26 @@ public static LoggerConfiguration Configuration(
225244
return settingConfiguration.Settings(configurationReader);
226245
}
227246

247+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
248+
[RequiresDynamicCode(TrimWarningMessages.CreatesArraysOfArbitraryTypes)]
228249
static ConfigurationReader GetConfigurationReader(IConfiguration configuration, ConfigurationReaderOptions readerOptions, DependencyContext? dependencyContext)
229250
{
230251
var assemblyFinder = dependencyContext == null ? AssemblyFinder.Auto() : AssemblyFinder.ForDependencyContext(dependencyContext);
231252
var section = string.IsNullOrWhiteSpace(readerOptions.SectionName) ? configuration : configuration.GetSection(readerOptions.SectionName);
232253
return new ConfigurationReader(section, assemblyFinder, readerOptions, configuration);
233254
}
234255

256+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
257+
[RequiresDynamicCode(TrimWarningMessages.CreatesArraysOfArbitraryTypes)]
235258
static ConfigurationReader GetConfigurationReader(IConfiguration configuration, ConfigurationReaderOptions readerOptions, ConfigurationAssemblySource source)
236259
{
237260
var assemblyFinder = AssemblyFinder.ForSource(source);
238261
var section = string.IsNullOrWhiteSpace(readerOptions.SectionName) ? configuration : configuration.GetSection(readerOptions.SectionName);
239262
return new ConfigurationReader(section, assemblyFinder, readerOptions, configuration);
240263
}
241264

265+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
266+
[RequiresDynamicCode(TrimWarningMessages.CreatesArraysOfArbitraryTypes)]
242267
static ConfigurationReader GetConfigurationReader(IConfiguration configuration, ConfigurationReaderOptions readerOptions, IReadOnlyCollection<Assembly> assemblies)
243268
{
244269
var section = string.IsNullOrWhiteSpace(readerOptions.SectionName) ? configuration : configuration.GetSection(readerOptions.SectionName);

src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<Description>Microsoft.Extensions.Configuration (appsettings.json) support for Serilog.</Description>
55
<VersionPrefix>4.0.0</VersionPrefix>
66
<Authors>Serilog Contributors</Authors>
7-
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
7+
<TargetFrameworks>net7.0;netstandard2.0;net461</TargetFrameworks>
88
<GenerateDocumentationFile>true</GenerateDocumentationFile>
99
<AssemblyName>Serilog.Settings.Configuration</AssemblyName>
1010
<PackageTags>serilog;json</PackageTags>
@@ -15,6 +15,8 @@
1515
<EmbedUntrackedSources>true</EmbedUntrackedSources>
1616
<IncludeSymbols>true</IncludeSymbols>
1717
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
18+
<IsTrimmable>true</IsTrimmable>
19+
<EnableAotAnalyzer>true</EnableAotAnalyzer>
1820
</PropertyGroup>
1921

2022
<ItemGroup>

src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Diagnostics.CodeAnalysis;
12
using System.Reflection;
23
using System.Runtime.CompilerServices;
34
using System.Text.RegularExpressions;
@@ -13,6 +14,8 @@
1314

1415
namespace Serilog.Settings.Configuration;
1516

17+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
18+
[RequiresDynamicCode(TrimWarningMessages.CreatesArraysOfArbitraryTypes)]
1619
class ConfigurationReader : IConfigurationReader
1720
{
1821
const string LevelSwitchNameRegex = @"^\${0,1}[A-Za-z]+[A-Za-z0-9]*$";
@@ -298,6 +301,7 @@ void ApplyEnrichment(LoggerConfiguration loggerConfiguration)
298301
}
299302
}
300303

304+
[RequiresDynamicCode(TrimWarningMessages.CreatesArraysOfArbitraryTypes)]
301305
internal ILookup<string, Dictionary<string, IConfigurationArgumentValue>> GetMethodCalls(IConfiguration directive)
302306
{
303307
var children = directive.GetChildren().ToList();
@@ -331,6 +335,7 @@ static string GetSectionName(IConfigurationSection s)
331335
}
332336
}
333337

338+
[RequiresDynamicCode(TrimWarningMessages.CreatesArraysOfArbitraryTypes)]
334339
internal static IConfigurationArgumentValue GetArgumentValue(IConfigurationSection argumentSection, IReadOnlyCollection<Assembly> configurationAssemblies)
335340
{
336341
IConfigurationArgumentValue argumentValue;
@@ -359,7 +364,7 @@ internal static IConfigurationArgumentValue GetArgumentValue(IConfigurationSecti
359364
static IReadOnlyCollection<Assembly> LoadConfigurationAssemblies(IConfiguration section, AssemblyFinder assemblyFinder)
360365
{
361366
var serilogAssembly = typeof(ILogger).Assembly;
362-
var assemblies = new Dictionary<string, Assembly> { [serilogAssembly.FullName] = serilogAssembly };
367+
var assemblies = new Dictionary<string, Assembly> { [serilogAssembly.FullName!] = serilogAssembly };
363368

364369
var usingSection = section.GetSection("Using");
365370
if (usingSection.GetChildren().Any())
@@ -371,16 +376,16 @@ static IReadOnlyCollection<Assembly> LoadConfigurationAssemblies(IConfiguration
371376
"A zero-length or whitespace assembly name was supplied to a Serilog.Using configuration statement.");
372377

373378
var assembly = Assembly.Load(new AssemblyName(simpleName));
374-
if (!assemblies.ContainsKey(assembly.FullName))
375-
assemblies.Add(assembly.FullName, assembly);
379+
if (!assemblies.ContainsKey(assembly.FullName!))
380+
assemblies.Add(assembly.FullName!, assembly);
376381
}
377382
}
378383

379384
foreach (var assemblyName in assemblyFinder.FindAssembliesContainingName("serilog"))
380385
{
381386
var assumed = Assembly.Load(assemblyName);
382-
if (assumed != null && !assemblies.ContainsKey(assumed.FullName))
383-
assemblies.Add(assumed.FullName, assumed);
387+
if (assumed != null && !assemblies.ContainsKey(assumed.FullName!))
388+
assemblies.Add(assumed.FullName!, assumed);
384389
}
385390

386391
return assemblies.Values.ToList().AsReadOnly();
@@ -504,6 +509,7 @@ static bool ParameterNameMatches(string? actualParameterName, IEnumerable<string
504509
return suppliedNames.Any(s => ParameterNameMatches(actualParameterName, s));
505510
}
506511

512+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
507513
static IReadOnlyCollection<MethodInfo> FindSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies, bool allowInternalTypes, bool allowInternalMethods)
508514
{
509515
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerSinkConfiguration), allowInternalTypes, allowInternalMethods);
@@ -513,6 +519,7 @@ static IReadOnlyCollection<MethodInfo> FindSinkConfigurationMethods(IReadOnlyCol
513519
return found;
514520
}
515521

522+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
516523
static IReadOnlyCollection<MethodInfo> FindAuditSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies, bool allowInternalTypes, bool allowInternalMethods)
517524
{
518525
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerAuditSinkConfiguration), allowInternalTypes, allowInternalMethods);
@@ -521,6 +528,7 @@ static IReadOnlyCollection<MethodInfo> FindAuditSinkConfigurationMethods(IReadOn
521528
return found;
522529
}
523530

531+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
524532
static IReadOnlyCollection<MethodInfo> FindFilterConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies, bool allowInternalTypes, bool allowInternalMethods)
525533
{
526534
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerFilterConfiguration), allowInternalTypes, allowInternalMethods);
@@ -530,6 +538,7 @@ static IReadOnlyCollection<MethodInfo> FindFilterConfigurationMethods(IReadOnlyC
530538
return found;
531539
}
532540

541+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
533542
static IReadOnlyCollection<MethodInfo> FindDestructureConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies, bool allowInternalTypes, bool allowInternalMethods)
534543
{
535544
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerDestructuringConfiguration), allowInternalTypes, allowInternalMethods);
@@ -539,6 +548,7 @@ static IReadOnlyCollection<MethodInfo> FindDestructureConfigurationMethods(IRead
539548
return found;
540549
}
541550

551+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
542552
static IReadOnlyCollection<MethodInfo> FindEventEnricherConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies, bool allowInternalTypes, bool allowInternalMethods)
543553
{
544554
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerEnrichmentConfiguration), allowInternalTypes, allowInternalMethods);
@@ -548,6 +558,7 @@ static IReadOnlyCollection<MethodInfo> FindEventEnricherConfigurationMethods(IRe
548558
return found;
549559
}
550560

561+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
551562
static List<MethodInfo> FindConfigurationExtensionMethods(IReadOnlyCollection<Assembly> configurationAssemblies, Type configType, bool allowInternalTypes, bool allowInternalMethods)
552563
{
553564
// ExtensionAttribute can be polyfilled to support extension methods
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
2+
#if !NET6_0_OR_GREATER
3+
namespace System.Diagnostics.CodeAnalysis
4+
{
5+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)]
6+
internal sealed class DynamicallyAccessedMembersAttribute : Attribute
7+
{
8+
public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
9+
{
10+
MemberTypes = memberTypes;
11+
}
12+
13+
public DynamicallyAccessedMemberTypes MemberTypes { get; }
14+
}
15+
16+
[Flags]
17+
internal enum DynamicallyAccessedMemberTypes
18+
{
19+
//
20+
// Summary:
21+
// Specifies all members.
22+
All = -1,
23+
//
24+
// Summary:
25+
// Specifies no members.
26+
None = 0,
27+
//
28+
// Summary:
29+
// Specifies the default, parameterless public constructor.
30+
PublicParameterlessConstructor = 1,
31+
//
32+
// Summary:
33+
// Specifies all public constructors.
34+
PublicConstructors = 3,
35+
//
36+
// Summary:
37+
// Specifies all non-public constructors.
38+
NonPublicConstructors = 4,
39+
//
40+
// Summary:
41+
// Specifies all public methods.
42+
PublicMethods = 8,
43+
//
44+
// Summary:
45+
// Specifies all non-public methods.
46+
NonPublicMethods = 16,
47+
//
48+
// Summary:
49+
// Specifies all public fields.
50+
PublicFields = 32,
51+
//
52+
// Summary:
53+
// Specifies all non-public fields.
54+
NonPublicFields = 64,
55+
//
56+
// Summary:
57+
// Specifies all public nested types.
58+
PublicNestedTypes = 128,
59+
//
60+
// Summary:
61+
// Specifies all non-public nested types.
62+
NonPublicNestedTypes = 256,
63+
//
64+
// Summary:
65+
// Specifies all public properties.
66+
PublicProperties = 512,
67+
//
68+
// Summary:
69+
// Specifies all non-public properties.
70+
NonPublicProperties = 1024,
71+
//
72+
// Summary:
73+
// Specifies all public events.
74+
PublicEvents = 2048,
75+
//
76+
// Summary:
77+
// Specifies all non-public events.
78+
NonPublicEvents = 4096,
79+
//
80+
// Summary:
81+
// Specifies all interfaces implemented by the type.
82+
Interfaces = 8192
83+
}
84+
}
85+
#endif

src/Serilog.Settings.Configuration/Settings/Configuration/ObjectArgumentValue.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
namespace Serilog.Settings.Configuration;
1010

11+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
12+
[RequiresDynamicCode(TrimWarningMessages.CreatesArraysOfArbitraryTypes)]
1113
class ObjectArgumentValue : IConfigurationArgumentValue
1214
{
1315
readonly IConfigurationSection _section;
@@ -98,6 +100,7 @@ bool TryCreateContainer([NotNullWhen(true)] out object? result)
98100
}
99101
}
100102

103+
[RequiresUnreferencedCode(TrimWarningMessages.UnboundedReflection)]
101104
internal static bool TryBuildCtorExpression(
102105
IConfigurationSection section, Type parameterType, ResolutionContext resolutionContext, [NotNullWhen(true)] out NewExpression? ctorExpression)
103106
{
@@ -218,7 +221,9 @@ static bool TryBindToCtorArgument(object value, Type type, ResolutionContext res
218221
}
219222
}
220223

221-
static bool IsContainer(Type type, [NotNullWhen(true)] out Type? elementType)
224+
static bool IsContainer(
225+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type,
226+
[NotNullWhen(true)] out Type? elementType)
222227
{
223228
elementType = null;
224229
foreach (var iface in type.GetInterfaces())
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#if !NET6_0_OR_GREATER
2+
3+
namespace System.Diagnostics.CodeAnalysis
4+
{
5+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)]
6+
internal sealed class RequiresDynamicCodeAttribute : Attribute
7+
{
8+
public RequiresDynamicCodeAttribute(string message)
9+
{
10+
Message = message;
11+
}
12+
13+
public string Message { get; }
14+
}
15+
}
16+
#endif
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
#if !NET5_0_OR_GREATER
3+
namespace System.Diagnostics.CodeAnalysis
4+
{
5+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)]
6+
internal sealed class RequiresUnreferencedCodeAttribute : Attribute
7+
{
8+
public RequiresUnreferencedCodeAttribute(string message)
9+
{
10+
Message = message;
11+
}
12+
13+
public string Message { get; }
14+
}
15+
}
16+
#endif

0 commit comments

Comments
 (0)