Skip to content

Commit 9f28bbc

Browse files
authored
Merge pull request #140 from tsimbalar/add-supported-methods
Add support and tests for more configuration methods
2 parents a1eda73 + 4c932e4 commit 9f28bbc

File tree

8 files changed

+352
-84
lines changed

8 files changed

+352
-84
lines changed

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

+9-8
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ internal static MethodInfo SelectConfigurationMethod(IEnumerable<MethodInfo> can
362362
.FirstOrDefault();
363363
}
364364

365-
internal static IList<MethodInfo> FindSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
365+
static IList<MethodInfo> FindSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
366366
{
367367
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerSinkConfiguration));
368368
if (configurationAssemblies.Contains(typeof(LoggerSinkConfiguration).GetTypeInfo().Assembly))
@@ -371,14 +371,15 @@ internal static IList<MethodInfo> FindSinkConfigurationMethods(IReadOnlyCollecti
371371
return found;
372372
}
373373

374-
internal static IList<MethodInfo> FindAuditSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
374+
static IList<MethodInfo> FindAuditSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
375375
{
376376
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerAuditSinkConfiguration));
377-
377+
if (configurationAssemblies.Contains(typeof(LoggerAuditSinkConfiguration).GetTypeInfo().Assembly))
378+
found.AddRange(SurrogateConfigurationMethods.AuditTo);
378379
return found;
379380
}
380381

381-
internal static IList<MethodInfo> FindFilterConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
382+
static IList<MethodInfo> FindFilterConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
382383
{
383384
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerFilterConfiguration));
384385
if (configurationAssemblies.Contains(typeof(LoggerFilterConfiguration).GetTypeInfo().Assembly))
@@ -387,7 +388,7 @@ internal static IList<MethodInfo> FindFilterConfigurationMethods(IReadOnlyCollec
387388
return found;
388389
}
389390

390-
internal static IList<MethodInfo> FindDestructureConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
391+
static IList<MethodInfo> FindDestructureConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
391392
{
392393
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerDestructuringConfiguration));
393394
if (configurationAssemblies.Contains(typeof(LoggerDestructuringConfiguration).GetTypeInfo().Assembly))
@@ -396,7 +397,7 @@ internal static IList<MethodInfo> FindDestructureConfigurationMethods(IReadOnlyC
396397
return found;
397398
}
398399

399-
internal static IList<MethodInfo> FindEventEnricherConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
400+
static IList<MethodInfo> FindEventEnricherConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
400401
{
401402
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerEnrichmentConfiguration));
402403
if (configurationAssemblies.Contains(typeof(LoggerEnrichmentConfiguration).GetTypeInfo().Assembly))
@@ -405,7 +406,7 @@ internal static IList<MethodInfo> FindEventEnricherConfigurationMethods(IReadOnl
405406
return found;
406407
}
407408

408-
internal static List<MethodInfo> FindConfigurationExtensionMethods(IReadOnlyCollection<Assembly> configurationAssemblies, Type configType)
409+
static List<MethodInfo> FindConfigurationExtensionMethods(IReadOnlyCollection<Assembly> configurationAssemblies, Type configType)
409410
{
410411
return configurationAssemblies
411412
.SelectMany(a => a.ExportedTypes
@@ -422,7 +423,7 @@ internal static bool IsValidSwitchName(string input)
422423
return Regex.IsMatch(input, LevelSwitchNameRegex);
423424
}
424425

425-
internal static LogEventLevel ParseLogEventLevel(string value)
426+
static LogEventLevel ParseLogEventLevel(string value)
426427
{
427428
if (!Enum.TryParse(value, out LogEventLevel parsedLevel))
428429
throw new InvalidOperationException($"The value {value} is not a valid Serilog level.");
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Linq.Expressions;
3+
using System.Linq;
44
using System.Reflection;
55
using Serilog.Configuration;
66
using Serilog.Core;
@@ -10,66 +10,73 @@ namespace Serilog.Settings.Configuration
1010
{
1111
/// <summary>
1212
/// Contains "fake extension" methods for the Serilog configuration API.
13-
/// By default the settings knows how to find extension methods, but some configuration
13+
/// By default the settings know how to find extension methods, but some configuration
1414
/// are actually "regular" method calls and would not be found otherwise.
1515
///
1616
/// This static class contains internal methods that can be used instead.
1717
///
1818
/// </summary>
1919
static class SurrogateConfigurationMethods
2020
{
21-
public static IEnumerable<MethodInfo> WriteTo
22-
{
23-
get
24-
{
25-
yield return GetSurrogateConfigurationMethod<LoggerSinkConfiguration, Action<LoggerConfiguration>, LoggingLevelSwitch>((c, a, s) => Logger(c, a, LevelAlias.Minimum, s));
26-
}
27-
}
28-
29-
public static IEnumerable<MethodInfo> Filter
30-
{
31-
get
32-
{
33-
yield return GetSurrogateConfigurationMethod<LoggerFilterConfiguration, ILogEventFilter, object>((c, f, _) => With(c, f));
34-
}
35-
}
36-
37-
public static IEnumerable<MethodInfo> Destructure
38-
{
39-
get
40-
{
41-
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, IDestructuringPolicy, object>((c, d, _) => With(c, d));
42-
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, int, object>((c, m, _) => ToMaximumDepth(c, m));
43-
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, int, object>((c, m, _) => ToMaximumStringLength(c, m));
44-
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, int, object>((c, m, _) => ToMaximumCollectionCount(c, m));
45-
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, Type, object>((c, t, _) => AsScalar(c, t));
46-
}
47-
}
48-
49-
public static IEnumerable<MethodInfo> Enrich
50-
{
51-
get
52-
{
53-
yield return GetSurrogateConfigurationMethod<LoggerEnrichmentConfiguration, object, object>((c, _, __) => FromLogContext(c));
54-
}
55-
}
56-
57-
static MethodInfo GetSurrogateConfigurationMethod<TConfiguration, TArg1, TArg2>(Expression<Action<TConfiguration, TArg1, TArg2>> method)
58-
=> (method.Body as MethodCallExpression)?.Method;
21+
static readonly Dictionary<Type, MethodInfo[]> SurrogateMethodCandidates = typeof(SurrogateConfigurationMethods)
22+
.GetTypeInfo().DeclaredMethods
23+
.GroupBy(m => m.GetParameters().First().ParameterType)
24+
.ToDictionary(g => g.Key, g => g.ToArray());
25+
26+
27+
internal static readonly MethodInfo[] WriteTo = SurrogateMethodCandidates[typeof(LoggerSinkConfiguration)];
28+
internal static readonly MethodInfo[] AuditTo = SurrogateMethodCandidates[typeof(LoggerAuditSinkConfiguration)];
29+
internal static readonly MethodInfo[] Enrich = SurrogateMethodCandidates[typeof(LoggerEnrichmentConfiguration)];
30+
internal static readonly MethodInfo[] Destructure = SurrogateMethodCandidates[typeof(LoggerDestructuringConfiguration)];
31+
internal static readonly MethodInfo[] Filter = SurrogateMethodCandidates[typeof(LoggerFilterConfiguration)];
5932

6033
/*
6134
Pass-through calls to various Serilog config methods which are
62-
implemented as instance methods rather than extension methods. The
63-
FindXXXConfigurationMethods calls (above) use these to add method
64-
invocation expressions as surrogates so that SelectConfigurationMethod
65-
has a way to match and invoke these instance methods.
35+
implemented as instance methods rather than extension methods.
36+
ConfigurationReader adds those to the already discovered extension methods
37+
so they can be invoked as well.
6638
*/
6739

40+
// ReSharper disable UnusedMember.Local
41+
// those methods are discovered through reflection by `SurrogateMethodCandidates`
42+
// ReSharper has no way to see that they are actually used ...
43+
44+
// .WriteTo...
45+
// ========
46+
static LoggerConfiguration Sink(
47+
LoggerSinkConfiguration loggerSinkConfiguration,
48+
ILogEventSink sink,
49+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
50+
LoggingLevelSwitch levelSwitch = null)
51+
=> loggerSinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch);
52+
53+
static LoggerConfiguration Logger(
54+
LoggerSinkConfiguration loggerSinkConfiguration,
55+
Action<LoggerConfiguration> configureLogger,
56+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
57+
LoggingLevelSwitch levelSwitch = null)
58+
=> loggerSinkConfiguration.Logger(configureLogger, restrictedToMinimumLevel, levelSwitch);
59+
60+
// .AuditTo...
61+
// ========
62+
static LoggerConfiguration Sink(
63+
LoggerAuditSinkConfiguration auditSinkConfiguration,
64+
ILogEventSink sink,
65+
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
66+
LoggingLevelSwitch levelSwitch = null)
67+
=> auditSinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch);
68+
69+
// .Filter...
70+
// =======
6871
// TODO: add overload for array argument (ILogEventEnricher[])
72+
// expose `With(params ILogEventFilter[] filters)` as if it was `With(ILogEventFilter filter)`
6973
static LoggerConfiguration With(LoggerFilterConfiguration loggerFilterConfiguration, ILogEventFilter filter)
7074
=> loggerFilterConfiguration.With(filter);
7175

76+
// .Destructure...
77+
// ============
7278
// TODO: add overload for array argument (IDestructuringPolicy[])
79+
// expose `With(params IDestructuringPolicy[] destructuringPolicies)` as if it was `With(IDestructuringPolicy policy)`
7380
static LoggerConfiguration With(LoggerDestructuringConfiguration loggerDestructuringConfiguration, IDestructuringPolicy policy)
7481
=> loggerDestructuringConfiguration.With(policy);
7582

@@ -85,15 +92,17 @@ static LoggerConfiguration ToMaximumCollectionCount(LoggerDestructuringConfigura
8592
static LoggerConfiguration AsScalar(LoggerDestructuringConfiguration loggerDestructuringConfiguration, Type scalarType)
8693
=> loggerDestructuringConfiguration.AsScalar(scalarType);
8794

95+
// .Enrich...
96+
// =======
97+
// expose `With(params ILogEventEnricher[] enrichers)` as if it was `With(ILogEventEnricher enricher)`
98+
static LoggerConfiguration With(
99+
LoggerEnrichmentConfiguration loggerEnrichmentConfiguration,
100+
ILogEventEnricher enricher)
101+
=> loggerEnrichmentConfiguration.With(enricher);
102+
88103
static LoggerConfiguration FromLogContext(LoggerEnrichmentConfiguration loggerEnrichmentConfiguration)
89104
=> loggerEnrichmentConfiguration.FromLogContext();
90105

91-
// Unlike the other configuration methods, Logger is an instance method rather than an extension.
92-
static LoggerConfiguration Logger(
93-
LoggerSinkConfiguration loggerSinkConfiguration,
94-
Action<LoggerConfiguration> configureLogger,
95-
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
96-
LoggingLevelSwitch levelSwitch = null)
97-
=> loggerSinkConfiguration.Logger(configureLogger, restrictedToMinimumLevel, levelSwitch);
106+
// ReSharper restore UnusedMember.Local
98107
}
99108
}

0 commit comments

Comments
 (0)